mirror of
https://github.com/Xevion/easy7zip.git
synced 2025-12-06 09:14:58 -06:00
9.18
This commit is contained in:
committed by
Kornel Lesiński
parent
2eb60a0598
commit
c65230d858
@@ -193,11 +193,9 @@ HRESULT CEncoder::Encode(
|
||||
// UInt64 outStreamStartPos;
|
||||
// RINOK(stream->Seek(0, STREAM_SEEK_CUR, &outStreamStartPos));
|
||||
|
||||
CSequentialInStreamSizeCount2 *inStreamSizeCountSpec =
|
||||
new CSequentialInStreamSizeCount2;
|
||||
CSequentialInStreamSizeCount2 *inStreamSizeCountSpec = new CSequentialInStreamSizeCount2;
|
||||
CMyComPtr<ISequentialInStream> inStreamSizeCount = inStreamSizeCountSpec;
|
||||
CSequentialOutStreamSizeCount *outStreamSizeCountSpec =
|
||||
new CSequentialOutStreamSizeCount;
|
||||
CSequentialOutStreamSizeCount *outStreamSizeCountSpec = new CSequentialOutStreamSizeCount;
|
||||
CMyComPtr<ISequentialOutStream> outStreamSizeCount = outStreamSizeCountSpec;
|
||||
|
||||
inStreamSizeCountSpec->Init(inStream);
|
||||
@@ -226,13 +224,11 @@ HRESULT CEncoder::Encode(
|
||||
_mixerCoderSpec->_coders[i].QueryInterface(IID_ICompressWriteCoderProperties, (void **)&writeCoderProperties);
|
||||
if (writeCoderProperties != NULL)
|
||||
{
|
||||
CSequentialOutStreamImp *outStreamSpec = new CSequentialOutStreamImp;
|
||||
CDynBufSeqOutStream *outStreamSpec = new CDynBufSeqOutStream;
|
||||
CMyComPtr<ISequentialOutStream> outStream(outStreamSpec);
|
||||
outStreamSpec->Init();
|
||||
writeCoderProperties->WriteCoderProperties(outStream);
|
||||
size_t size = outStreamSpec->GetSize();
|
||||
encodingInfo.Props.SetCapacity(size);
|
||||
memmove(encodingInfo.Props, outStreamSpec->GetBuffer(), size);
|
||||
outStreamSpec->CopyToBuffer(encodingInfo.Props);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -250,8 +246,7 @@ HRESULT CEncoder::Encode(
|
||||
RINOK(_mixerCoder->Code(&inStreamPointers.Front(), NULL, 1,
|
||||
&outStreamPointers.Front(), NULL, outStreamPointers.Size(), compressProgress));
|
||||
|
||||
ConvertBindInfoToFolderItemInfo(_decompressBindInfo, _decompressionMethods,
|
||||
folderItem);
|
||||
ConvertBindInfoToFolderItemInfo(_decompressBindInfo, _decompressionMethods, folderItem);
|
||||
|
||||
packSizes.Add(outStreamSizeCountSpec->GetSize());
|
||||
|
||||
|
||||
@@ -280,28 +280,46 @@ void CInByte2::ReadString(UString &s)
|
||||
_pos += rem + 2;
|
||||
}
|
||||
|
||||
static inline bool TestSignatureCandidate(const Byte *p)
|
||||
static inline bool TestSignature(const Byte *p)
|
||||
{
|
||||
for (int i = 0; i < kSignatureSize; i++)
|
||||
if (p[i] != kSignature[i])
|
||||
return false;
|
||||
return (p[0x1A] == 0 && p[0x1B] == 0);
|
||||
return CrcCalc(p + 12, 20) == GetUi32(p + 8);
|
||||
}
|
||||
|
||||
#ifdef FORMAT_7Z_RECOVERY
|
||||
static inline bool TestSignature2(const Byte *p)
|
||||
{
|
||||
int i;
|
||||
for (i = 0; i < kSignatureSize; i++)
|
||||
if (p[i] != kSignature[i])
|
||||
return false;
|
||||
if (CrcCalc(p + 12, 20) == GetUi32(p + 8))
|
||||
return true;
|
||||
for (i = 8; i < kHeaderSize; i++)
|
||||
if (p[i] != 0)
|
||||
return false;
|
||||
return (p[6] != 0 || p[7] != 0);
|
||||
}
|
||||
#else
|
||||
#define TestSignature2(p) TestSignature(p)
|
||||
#endif
|
||||
|
||||
HRESULT CInArchive::FindAndReadSignature(IInStream *stream, const UInt64 *searchHeaderSizeLimit)
|
||||
{
|
||||
RINOK(ReadStream_FALSE(stream, _header, kHeaderSize));
|
||||
|
||||
if (TestSignatureCandidate(_header))
|
||||
if (TestSignature2(_header))
|
||||
return S_OK;
|
||||
|
||||
CByteBuffer byteBuffer;
|
||||
const UInt32 kBufferSize = (1 << 16);
|
||||
byteBuffer.SetCapacity(kBufferSize);
|
||||
Byte *buffer = byteBuffer;
|
||||
UInt32 numPrevBytes = kHeaderSize - 1;
|
||||
memcpy(buffer, _header + 1, numPrevBytes);
|
||||
UInt64 curTestPos = _arhiveBeginStreamPosition + 1;
|
||||
UInt32 numPrevBytes = kHeaderSize;
|
||||
memcpy(buffer, _header, kHeaderSize);
|
||||
UInt64 curTestPos = _arhiveBeginStreamPosition;
|
||||
for (;;)
|
||||
{
|
||||
if (searchHeaderSizeLimit != NULL)
|
||||
@@ -316,14 +334,14 @@ HRESULT CInArchive::FindAndReadSignature(IInStream *stream, const UInt64 *search
|
||||
if (processedSize == 0)
|
||||
return S_FALSE;
|
||||
}
|
||||
while (numPrevBytes < kHeaderSize);
|
||||
UInt32 numTests = numPrevBytes - kHeaderSize + 1;
|
||||
while (numPrevBytes <= kHeaderSize);
|
||||
UInt32 numTests = numPrevBytes - kHeaderSize;
|
||||
for (UInt32 pos = 0; pos < numTests; pos++)
|
||||
{
|
||||
for (; buffer[pos] != '7' && pos < numTests; pos++);
|
||||
if (pos == numTests)
|
||||
break;
|
||||
if (TestSignatureCandidate(buffer + pos))
|
||||
if (TestSignature(buffer + pos))
|
||||
{
|
||||
memcpy(_header, buffer + pos, kHeaderSize);
|
||||
curTestPos += pos;
|
||||
@@ -812,7 +830,7 @@ HRESULT CInArchive::ReadAndDecodePackedStreams(
|
||||
ThrowUnsupported();
|
||||
data.SetCapacity(unpackSize);
|
||||
|
||||
CSequentialOutStreamImp2 *outStreamSpec = new CSequentialOutStreamImp2;
|
||||
CBufPtrSeqOutStream *outStreamSpec = new CBufPtrSeqOutStream;
|
||||
CMyComPtr<ISequentialOutStream> outStream = outStreamSpec;
|
||||
outStreamSpec->Init(data, unpackSize);
|
||||
|
||||
@@ -1164,23 +1182,24 @@ HRESULT CInArchive::ReadDatabase2(
|
||||
nextHeaderCRC = CrcCalc(buf + i, (size_t)nextHeaderSize);
|
||||
RINOK(_stream->Seek(cur, STREAM_SEEK_SET, NULL));
|
||||
}
|
||||
else
|
||||
#endif
|
||||
|
||||
#ifdef FORMAT_7Z_RECOVERY
|
||||
crcFromArchive = crc;
|
||||
#endif
|
||||
{
|
||||
if (crc != crcFromArchive)
|
||||
ThrowIncorrect();
|
||||
}
|
||||
|
||||
db.ArchiveInfo.StartPositionAfterHeader = _arhiveBeginStreamPosition + kHeaderSize;
|
||||
|
||||
if (crc != crcFromArchive)
|
||||
ThrowIncorrect();
|
||||
|
||||
if (nextHeaderSize == 0)
|
||||
return S_OK;
|
||||
|
||||
if (nextHeaderSize > (UInt64)0xFFFFFFFF)
|
||||
return S_FALSE;
|
||||
|
||||
if ((Int64)nextHeaderOffset < 0)
|
||||
return S_FALSE;
|
||||
|
||||
RINOK(_stream->Seek(nextHeaderOffset, STREAM_SEEK_CUR, NULL));
|
||||
|
||||
CByteBuffer buffer2;
|
||||
|
||||
@@ -2,6 +2,8 @@
|
||||
|
||||
#include "StdAfx.h"
|
||||
|
||||
#include "../../../../C/Types.h"
|
||||
|
||||
#include "ItemNameUtils.h"
|
||||
|
||||
namespace NArchive {
|
||||
|
||||
@@ -6,72 +6,61 @@
|
||||
|
||||
STDMETHODIMP CMultiStream::Read(void *data, UInt32 size, UInt32 *processedSize)
|
||||
{
|
||||
if(processedSize != NULL)
|
||||
if (processedSize)
|
||||
*processedSize = 0;
|
||||
while(_streamIndex < Streams.Size() && size > 0)
|
||||
if (size == 0)
|
||||
return S_OK;
|
||||
if (_pos >= _totalLength)
|
||||
return (_pos == _totalLength) ? S_OK : E_FAIL;
|
||||
|
||||
{
|
||||
CSubStreamInfo &s = Streams[_streamIndex];
|
||||
if (_pos == s.Size)
|
||||
int left = 0, mid = _streamIndex, right = Streams.Size();
|
||||
for (;;)
|
||||
{
|
||||
_streamIndex++;
|
||||
_pos = 0;
|
||||
continue;
|
||||
CSubStreamInfo &m = Streams[mid];
|
||||
if (_pos < m.GlobalOffset)
|
||||
right = mid;
|
||||
else if (_pos >= m.GlobalOffset + m.Size)
|
||||
left = mid + 1;
|
||||
else
|
||||
{
|
||||
_streamIndex = mid;
|
||||
break;
|
||||
}
|
||||
mid = (left + right) / 2;
|
||||
}
|
||||
RINOK(s.Stream->Seek(s.Pos + _pos, STREAM_SEEK_SET, 0));
|
||||
UInt32 sizeToRead = UInt32(MyMin((UInt64)size, s.Size - _pos));
|
||||
UInt32 realProcessed;
|
||||
HRESULT result = s.Stream->Read(data, sizeToRead, &realProcessed);
|
||||
data = (void *)((Byte *)data + realProcessed);
|
||||
size -= realProcessed;
|
||||
if(processedSize != NULL)
|
||||
*processedSize += realProcessed;
|
||||
_pos += realProcessed;
|
||||
_seekPos += realProcessed;
|
||||
RINOK(result);
|
||||
break;
|
||||
_streamIndex = mid;
|
||||
}
|
||||
return S_OK;
|
||||
|
||||
CSubStreamInfo &s = Streams[_streamIndex];
|
||||
UInt64 localPos = _pos - s.GlobalOffset;
|
||||
if (localPos != s.LocalPos)
|
||||
{
|
||||
RINOK(s.Stream->Seek(localPos, STREAM_SEEK_SET, &s.LocalPos));
|
||||
}
|
||||
UInt64 rem = s.Size - localPos;
|
||||
if (size > rem)
|
||||
size = (UInt32)rem;
|
||||
HRESULT result = s.Stream->Read(data, size, &size);
|
||||
_pos += size;
|
||||
s.LocalPos += size;
|
||||
if (processedSize)
|
||||
*processedSize = size;
|
||||
return result;
|
||||
}
|
||||
|
||||
STDMETHODIMP CMultiStream::Seek(Int64 offset, UInt32 seekOrigin,
|
||||
UInt64 *newPosition)
|
||||
STDMETHODIMP CMultiStream::Seek(Int64 offset, UInt32 seekOrigin, UInt64 *newPosition)
|
||||
{
|
||||
UInt64 newPos;
|
||||
switch(seekOrigin)
|
||||
{
|
||||
case STREAM_SEEK_SET:
|
||||
newPos = offset;
|
||||
break;
|
||||
case STREAM_SEEK_CUR:
|
||||
newPos = _seekPos + offset;
|
||||
break;
|
||||
case STREAM_SEEK_END:
|
||||
newPos = _totalLength + offset;
|
||||
break;
|
||||
default:
|
||||
return STG_E_INVALIDFUNCTION;
|
||||
case STREAM_SEEK_SET: _pos = offset; break;
|
||||
case STREAM_SEEK_CUR: _pos = _pos + offset; break;
|
||||
case STREAM_SEEK_END: _pos = _totalLength + offset; break;
|
||||
default: return STG_E_INVALIDFUNCTION;
|
||||
}
|
||||
_seekPos = 0;
|
||||
for (_streamIndex = 0; _streamIndex < Streams.Size(); _streamIndex++)
|
||||
{
|
||||
UInt64 size = Streams[_streamIndex].Size;
|
||||
if (newPos < _seekPos + size)
|
||||
{
|
||||
_pos = newPos - _seekPos;
|
||||
_seekPos += _pos;
|
||||
if (newPosition != 0)
|
||||
*newPosition = newPos;
|
||||
return S_OK;
|
||||
}
|
||||
_seekPos += size;
|
||||
}
|
||||
if (newPos == _seekPos)
|
||||
{
|
||||
if (newPosition != 0)
|
||||
*newPosition = newPos;
|
||||
return S_OK;
|
||||
}
|
||||
return E_FAIL;
|
||||
if (newPosition != 0)
|
||||
*newPosition = _pos;
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -1,36 +1,44 @@
|
||||
// MultiStream.h
|
||||
|
||||
#ifndef __MULTISTREAM_H
|
||||
#define __MULTISTREAM_H
|
||||
#ifndef __MULTI_STREAM_H
|
||||
#define __MULTI_STREAM_H
|
||||
|
||||
#include "../../../Common/MyCom.h"
|
||||
#include "../../../Common/MyVector.h"
|
||||
#include "../../Archive/IArchive.h"
|
||||
|
||||
#include "../../IStream.h"
|
||||
|
||||
class CMultiStream:
|
||||
public IInStream,
|
||||
public CMyUnknownImp
|
||||
{
|
||||
int _streamIndex;
|
||||
UInt64 _pos;
|
||||
UInt64 _seekPos;
|
||||
UInt64 _totalLength;
|
||||
int _streamIndex;
|
||||
public:
|
||||
struct CSubStreamInfo
|
||||
{
|
||||
CMyComPtr<IInStream> Stream;
|
||||
UInt64 Pos;
|
||||
UInt64 Size;
|
||||
UInt64 GlobalOffset;
|
||||
UInt64 LocalPos;
|
||||
};
|
||||
CObjectVector<CSubStreamInfo> Streams;
|
||||
void Init()
|
||||
|
||||
HRESULT Init()
|
||||
{
|
||||
_streamIndex = 0;
|
||||
_pos = 0;
|
||||
_seekPos = 0;
|
||||
_totalLength = 0;
|
||||
UInt64 total = 0;
|
||||
for (int i = 0; i < Streams.Size(); i++)
|
||||
_totalLength += Streams[i].Size;
|
||||
{
|
||||
CSubStreamInfo &s = Streams[i];
|
||||
s.GlobalOffset = total;
|
||||
total += Streams[i].Size;
|
||||
RINOK(s.Stream->Seek(0, STREAM_SEEK_CUR, &s.LocalPos));
|
||||
}
|
||||
_totalLength = total;
|
||||
_pos = 0;
|
||||
_streamIndex = 0;
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
MY_UNKNOWN_IMP1(IInStream)
|
||||
|
||||
644
CPP/7zip/Archive/CramfsHandler.cpp
Executable file
644
CPP/7zip/Archive/CramfsHandler.cpp
Executable file
@@ -0,0 +1,644 @@
|
||||
// CramfsHandler.cpp
|
||||
|
||||
#include "StdAfx.h"
|
||||
|
||||
#include "../../../C/7zCrc.h"
|
||||
#include "../../../C/CpuArch.h"
|
||||
#include "../../../C/Alloc.h"
|
||||
|
||||
#include "Common/ComTry.h"
|
||||
#include "Common/StringConvert.h"
|
||||
|
||||
#include "Windows/PropVariantUtils.h"
|
||||
|
||||
#include "../Common/LimitedStreams.h"
|
||||
#include "../Common/ProgressUtils.h"
|
||||
#include "../Common/RegisterArc.h"
|
||||
#include "../Common/StreamObjects.h"
|
||||
#include "../Common/StreamUtils.h"
|
||||
|
||||
#include "../Compress/CopyCoder.h"
|
||||
#include "../Compress/ZlibDecoder.h"
|
||||
|
||||
namespace NArchive {
|
||||
namespace NCramfs {
|
||||
|
||||
#define SIGNATURE { 'C','o','m','p','r','e','s','s','e','d',' ','R','O','M','F','S' }
|
||||
|
||||
static const UInt32 kSignatureSize = 16;
|
||||
static const char kSignature[kSignatureSize] = SIGNATURE;
|
||||
|
||||
static const UInt32 kArcSizeMax = (256 + 16) << 20;
|
||||
static const UInt32 kNumFilesMax = (1 << 19);
|
||||
static const unsigned kNumDirLevelsMax = (1 << 8);
|
||||
|
||||
static const UInt32 kHeaderSize = 0x40;
|
||||
static const unsigned kHeaderNameSize = 16;
|
||||
static const UInt32 kNodeSize = 12;
|
||||
|
||||
static const UInt32 kFlag_FsVer2 = (1 << 0);
|
||||
|
||||
static const CUInt32PCharPair k_Flags[] =
|
||||
{
|
||||
{ 0, "Ver2" },
|
||||
{ 1, "SortedDirs" },
|
||||
{ 8, "Holes" },
|
||||
{ 9, "WrongSignature" },
|
||||
{ 10, "ShiftedRootOffset" }
|
||||
};
|
||||
|
||||
static const unsigned kBlockSizeLog = 12;
|
||||
static const UInt32 kBlockSize = 1 << kBlockSizeLog;
|
||||
|
||||
/*
|
||||
struct CNode
|
||||
{
|
||||
UInt16 Mode;
|
||||
UInt16 Uid;
|
||||
UInt32 Size;
|
||||
Byte Gid;
|
||||
UInt32 NameLen;
|
||||
UInt32 Offset;
|
||||
|
||||
void Parse(const Byte *p)
|
||||
{
|
||||
Mode = GetUi16(p);
|
||||
Uid = GetUi16(p + 2);
|
||||
Size = Get32(p + 4) & 0xFFFFFF;
|
||||
Gid = p[7];
|
||||
NameLen = p[8] & 0x3F;
|
||||
Offset = Get32(p + 8) >> 6;
|
||||
}
|
||||
};
|
||||
*/
|
||||
|
||||
#define Get32(p) (be ? GetBe32(p) : GetUi32(p))
|
||||
|
||||
static UInt32 GetMode(const Byte *p, bool be) { return be ? GetBe16(p) : GetUi16(p); }
|
||||
static bool IsDir(const Byte *p, bool be) { return (GetMode(p, be) & 0xF000) == 0x4000; }
|
||||
|
||||
static UInt32 GetSize(const Byte *p, bool be)
|
||||
{
|
||||
if (be)
|
||||
return GetBe32(p + 4) >> 8;
|
||||
else
|
||||
return GetUi32(p + 4) & 0xFFFFFF;
|
||||
}
|
||||
|
||||
static UInt32 GetNameLen(const Byte *p, bool be)
|
||||
{
|
||||
if (be)
|
||||
return (p[8] & 0xFC);
|
||||
else
|
||||
return (p[8] & 0x3F) << 2;
|
||||
}
|
||||
|
||||
static UInt32 GetOffset(const Byte *p, bool be)
|
||||
{
|
||||
if (be)
|
||||
return (GetBe32(p + 8) & 0x03FFFFFF) << 2;
|
||||
else
|
||||
return GetUi32(p + 8) >> 6 << 2;
|
||||
}
|
||||
|
||||
struct CItem
|
||||
{
|
||||
UInt32 Offset;
|
||||
int Parent;
|
||||
};
|
||||
|
||||
struct CHeader
|
||||
{
|
||||
bool be;
|
||||
UInt32 Size;
|
||||
UInt32 Flags;
|
||||
// UInt32 Future;
|
||||
UInt32 Crc;
|
||||
// UInt32 Edition;
|
||||
UInt32 NumBlocks;
|
||||
UInt32 NumFiles;
|
||||
char Name[kHeaderNameSize];
|
||||
|
||||
bool Parse(const Byte *p)
|
||||
{
|
||||
if (memcmp(p + 16, kSignature, kSignatureSize) != 0)
|
||||
return false;
|
||||
switch(GetUi32(p))
|
||||
{
|
||||
case 0x28CD3D45: be = false; break;
|
||||
case 0x453DCD28: be = true; break;
|
||||
default: return false;
|
||||
}
|
||||
Size = Get32(p + 4);
|
||||
Flags = Get32(p + 8);
|
||||
// Future = Get32(p + 0xC);
|
||||
Crc = Get32(p + 0x20);
|
||||
// Edition = Get32(p + 0x24);
|
||||
NumBlocks = Get32(p + 0x28);
|
||||
NumFiles = Get32(p + 0x2C);
|
||||
memcpy(Name, p + 0x30, kHeaderNameSize);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool IsVer2() const { return (Flags & kFlag_FsVer2) != 0; }
|
||||
};
|
||||
|
||||
class CHandler:
|
||||
public IInArchive,
|
||||
public IInArchiveGetStream,
|
||||
public CMyUnknownImp
|
||||
{
|
||||
CRecordVector<CItem> _items;
|
||||
CMyComPtr<IInStream> _stream;
|
||||
Byte *_data;
|
||||
UInt32 _size;
|
||||
UInt32 _headersSize;
|
||||
AString _errorMessage;
|
||||
CHeader _h;
|
||||
|
||||
// Current file
|
||||
|
||||
NCompress::NZlib::CDecoder *_zlibDecoderSpec;
|
||||
CMyComPtr<ICompressCoder> _zlibDecoder;
|
||||
|
||||
CBufInStream *_inStreamSpec;
|
||||
CMyComPtr<ISequentialInStream> _inStream;
|
||||
|
||||
CBufPtrSeqOutStream *_outStreamSpec;
|
||||
CMyComPtr<ISequentialOutStream> _outStream;
|
||||
|
||||
UInt32 _curBlocksOffset;
|
||||
UInt32 _curNumBlocks;
|
||||
|
||||
HRESULT OpenDir(int parent, UInt32 baseOffsetBase, unsigned level);
|
||||
HRESULT Open2(IInStream *inStream);
|
||||
AString GetPath(int index) const;
|
||||
bool GetPackSize(int index, UInt32 &res) const;
|
||||
void Free();
|
||||
public:
|
||||
CHandler(): _data(0) {}
|
||||
~CHandler() { Free(); }
|
||||
MY_UNKNOWN_IMP2(IInArchive, IInArchiveGetStream)
|
||||
INTERFACE_IInArchive(;)
|
||||
STDMETHOD(GetStream)(UInt32 index, ISequentialInStream **stream);
|
||||
HRESULT ReadBlock(UInt64 blockIndex, Byte *dest, size_t blockSize);
|
||||
};
|
||||
|
||||
static const STATPROPSTG kProps[] =
|
||||
{
|
||||
{ NULL, kpidPath, VT_BSTR},
|
||||
{ NULL, kpidIsDir, VT_BOOL},
|
||||
{ NULL, kpidSize, VT_UI4},
|
||||
{ NULL, kpidPackSize, VT_UI4},
|
||||
{ NULL, kpidPosixAttrib, VT_UI4}
|
||||
// { NULL, kpidOffset, VT_UI4}
|
||||
};
|
||||
|
||||
static const STATPROPSTG kArcProps[] =
|
||||
{
|
||||
{ NULL, kpidName, VT_BSTR},
|
||||
{ NULL, kpidBigEndian, VT_BOOL},
|
||||
{ NULL, kpidCharacts, VT_BSTR},
|
||||
{ NULL, kpidPhySize, VT_UI4},
|
||||
{ NULL, kpidHeadersSize, VT_UI4},
|
||||
{ NULL, kpidNumSubFiles, VT_UI4},
|
||||
{ NULL, kpidNumBlocks, VT_UI4}
|
||||
};
|
||||
|
||||
IMP_IInArchive_Props
|
||||
IMP_IInArchive_ArcProps
|
||||
|
||||
HRESULT CHandler::OpenDir(int parent, UInt32 baseOffset, unsigned level)
|
||||
{
|
||||
const Byte *p = _data + baseOffset;
|
||||
bool be = _h.be;
|
||||
if (!IsDir(p, be))
|
||||
return S_OK;
|
||||
UInt32 offset = GetOffset(p, be);
|
||||
UInt32 size = GetSize(p, be);
|
||||
if (offset == 0 && size == 0)
|
||||
return S_OK;
|
||||
UInt32 end = offset + size;
|
||||
if (offset < kHeaderSize || end > _size || level > kNumDirLevelsMax)
|
||||
return S_FALSE;
|
||||
if (end > _headersSize)
|
||||
_headersSize = end;
|
||||
|
||||
int startIndex = _items.Size();
|
||||
|
||||
while (size != 0)
|
||||
{
|
||||
if (size < kNodeSize || (UInt32)_items.Size() >= kNumFilesMax)
|
||||
return S_FALSE;
|
||||
CItem item;
|
||||
item.Parent = parent;
|
||||
item.Offset = offset;
|
||||
_items.Add(item);
|
||||
UInt32 nodeLen = kNodeSize + GetNameLen(_data + offset, be);
|
||||
if (size < nodeLen)
|
||||
return S_FALSE;
|
||||
offset += nodeLen;
|
||||
size -= nodeLen;
|
||||
}
|
||||
|
||||
int endIndex = _items.Size();
|
||||
for (int i = startIndex; i < endIndex; i++)
|
||||
{
|
||||
RINOK(OpenDir(i, _items[i].Offset, level + 1));
|
||||
}
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
HRESULT CHandler::Open2(IInStream *inStream)
|
||||
{
|
||||
Byte buf[kHeaderSize];
|
||||
RINOK(ReadStream_FALSE(inStream, buf, kHeaderSize));
|
||||
if (!_h.Parse(buf))
|
||||
return S_FALSE;
|
||||
if (_h.IsVer2())
|
||||
{
|
||||
if (_h.Size < kHeaderSize || _h.Size > kArcSizeMax || _h.NumFiles > kNumFilesMax)
|
||||
return S_FALSE;
|
||||
}
|
||||
else
|
||||
{
|
||||
UInt64 size;
|
||||
RINOK(inStream->Seek(0, STREAM_SEEK_END, &size));
|
||||
if (size > kArcSizeMax)
|
||||
return S_FALSE;
|
||||
_h.Size = (UInt32)size;
|
||||
RINOK(inStream->Seek(kHeaderSize, STREAM_SEEK_SET, NULL));
|
||||
}
|
||||
_data = (Byte *)MidAlloc(_h.Size);
|
||||
if (_data == 0)
|
||||
return E_OUTOFMEMORY;
|
||||
memcpy(_data, buf, kHeaderSize);
|
||||
size_t processed = _h.Size - kHeaderSize;
|
||||
RINOK(ReadStream(inStream, _data + kHeaderSize, &processed));
|
||||
if (processed < kNodeSize)
|
||||
return S_FALSE;
|
||||
_size = kHeaderSize + (UInt32)processed;
|
||||
if (_size != _h.Size)
|
||||
_errorMessage = "Unexpected end of archive";
|
||||
else
|
||||
{
|
||||
SetUi32(_data + 0x20, 0);
|
||||
if (_h.IsVer2())
|
||||
if (CrcCalc(_data, _h.Size) != _h.Crc)
|
||||
_errorMessage = "CRC error";
|
||||
}
|
||||
if (_h.IsVer2())
|
||||
_items.Reserve(_h.NumFiles - 1);
|
||||
return OpenDir(-1, kHeaderSize, 0);
|
||||
}
|
||||
|
||||
AString CHandler::GetPath(int index) const
|
||||
{
|
||||
unsigned len = 0;
|
||||
int indexMem = index;
|
||||
do
|
||||
{
|
||||
const CItem &item = _items[index];
|
||||
index = item.Parent;
|
||||
const Byte *p = _data + item.Offset;
|
||||
unsigned size = GetNameLen(p, _h.be);
|
||||
p += kNodeSize;
|
||||
unsigned i;
|
||||
for (i = 0; i < size && p[i]; i++);
|
||||
len += i + 1;
|
||||
}
|
||||
while (index >= 0);
|
||||
len--;
|
||||
|
||||
AString path;
|
||||
char *dest = path.GetBuffer(len) + len;
|
||||
index = indexMem;
|
||||
for (;;)
|
||||
{
|
||||
const CItem &item = _items[index];
|
||||
index = item.Parent;
|
||||
const Byte *p = _data + item.Offset;
|
||||
unsigned size = GetNameLen(p, _h.be);
|
||||
p += kNodeSize;
|
||||
unsigned i;
|
||||
for (i = 0; i < size && p[i]; i++);
|
||||
dest -= i;
|
||||
memcpy(dest, p, i);
|
||||
if (index < 0)
|
||||
break;
|
||||
*(--dest) = CHAR_PATH_SEPARATOR;
|
||||
}
|
||||
path.ReleaseBuffer(len);
|
||||
return path;
|
||||
}
|
||||
|
||||
bool CHandler::GetPackSize(int index, UInt32 &res) const
|
||||
{
|
||||
const CItem &item = _items[index];
|
||||
const Byte *p = _data + item.Offset;
|
||||
bool be = _h.be;
|
||||
UInt32 offset = GetOffset(p, be);
|
||||
if (offset < kHeaderSize)
|
||||
return false;
|
||||
UInt32 numBlocks = (GetSize(p, be) + kBlockSize - 1) >> kBlockSizeLog;
|
||||
UInt32 start = offset + numBlocks * 4;
|
||||
if (start > _size)
|
||||
return false;
|
||||
UInt32 end = Get32(_data + start - 4);
|
||||
if (end < start)
|
||||
return false;
|
||||
res = end - start;
|
||||
return true;
|
||||
}
|
||||
|
||||
STDMETHODIMP CHandler::Open(IInStream *stream, const UInt64 *, IArchiveOpenCallback * /* callback */)
|
||||
{
|
||||
COM_TRY_BEGIN
|
||||
{
|
||||
Close();
|
||||
RINOK(Open2(stream));
|
||||
_stream = stream;
|
||||
}
|
||||
return S_OK;
|
||||
COM_TRY_END
|
||||
}
|
||||
|
||||
void CHandler::Free()
|
||||
{
|
||||
MidFree(_data);
|
||||
_data = 0;
|
||||
}
|
||||
|
||||
STDMETHODIMP CHandler::Close()
|
||||
{
|
||||
_headersSize = 0;
|
||||
_items.Clear();
|
||||
_stream.Release();
|
||||
_errorMessage.Empty();
|
||||
Free();
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
STDMETHODIMP CHandler::GetNumberOfItems(UInt32 *numItems)
|
||||
{
|
||||
*numItems = _items.Size();
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
STDMETHODIMP CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value)
|
||||
{
|
||||
COM_TRY_BEGIN
|
||||
NWindows::NCOM::CPropVariant prop;
|
||||
switch(propID)
|
||||
{
|
||||
case kpidName:
|
||||
{
|
||||
char dest[kHeaderNameSize + 4];
|
||||
memcpy(dest, _h.Name, kHeaderNameSize);
|
||||
dest[kHeaderNameSize] = 0;
|
||||
prop = dest;
|
||||
break;
|
||||
}
|
||||
case kpidBigEndian: prop = _h.be; break;
|
||||
case kpidCharacts: FLAGS_TO_PROP(k_Flags, _h.Flags, prop); break;
|
||||
case kpidNumBlocks: if (_h.IsVer2()) prop = _h.NumBlocks; break;
|
||||
case kpidNumSubFiles: if (_h.IsVer2()) prop = _h.NumFiles; break;
|
||||
case kpidPhySize: if (_h.IsVer2()) prop = _h.Size; break;
|
||||
case kpidHeadersSize: prop = _headersSize; break;
|
||||
case kpidError: if (!_errorMessage.IsEmpty()) prop = _errorMessage; break;
|
||||
}
|
||||
prop.Detach(value);
|
||||
return S_OK;
|
||||
COM_TRY_END
|
||||
}
|
||||
|
||||
STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *value)
|
||||
{
|
||||
COM_TRY_BEGIN
|
||||
NWindows::NCOM::CPropVariant prop;
|
||||
const CItem &item = _items[index];
|
||||
const Byte *p = _data + item.Offset;
|
||||
bool be = _h.be;
|
||||
bool isDir = IsDir(p, be);
|
||||
switch(propID)
|
||||
{
|
||||
case kpidPath: prop = MultiByteToUnicodeString(GetPath(index), CP_OEMCP); break;
|
||||
case kpidIsDir: prop = isDir; break;
|
||||
// case kpidOffset: prop = (UInt32)GetOffset(p, be); break;
|
||||
case kpidSize: if (!isDir) prop = GetSize(p, be); break;
|
||||
case kpidPackSize:
|
||||
if (!isDir)
|
||||
{
|
||||
UInt32 size;
|
||||
if (GetPackSize(index, size))
|
||||
prop = size;
|
||||
}
|
||||
break;
|
||||
case kpidPosixAttrib: prop = (UInt32)GetMode(p, be); break;
|
||||
}
|
||||
prop.Detach(value);
|
||||
return S_OK;
|
||||
COM_TRY_END
|
||||
}
|
||||
|
||||
class CCramfsInStream: public CCachedInStream
|
||||
{
|
||||
HRESULT ReadBlock(UInt64 blockIndex, Byte *dest, size_t blockSize);
|
||||
public:
|
||||
CHandler *Handler;
|
||||
};
|
||||
|
||||
HRESULT CCramfsInStream::ReadBlock(UInt64 blockIndex, Byte *dest, size_t blockSize)
|
||||
{
|
||||
return Handler->ReadBlock(blockIndex, dest, blockSize);
|
||||
}
|
||||
|
||||
HRESULT CHandler::ReadBlock(UInt64 blockIndex, Byte *dest, size_t blockSize)
|
||||
{
|
||||
if (!_zlibDecoder)
|
||||
{
|
||||
_zlibDecoderSpec = new NCompress::NZlib::CDecoder();
|
||||
_zlibDecoder = _zlibDecoderSpec;
|
||||
}
|
||||
if (!_inStream)
|
||||
{
|
||||
_inStreamSpec = new CBufInStream();
|
||||
_inStream = _inStreamSpec;
|
||||
}
|
||||
if (!_outStream)
|
||||
{
|
||||
_outStreamSpec = new CBufPtrSeqOutStream();
|
||||
_outStream = _outStreamSpec;
|
||||
}
|
||||
bool be = _h.be;
|
||||
const Byte *p = _data + (_curBlocksOffset + (UInt32)blockIndex * 4);
|
||||
UInt32 start = (blockIndex == 0 ? _curBlocksOffset + _curNumBlocks * 4: Get32(p - 4));
|
||||
UInt32 end = Get32(p);
|
||||
if (end < start || end > _size)
|
||||
return S_FALSE;
|
||||
UInt32 inSize = end - start;
|
||||
_inStreamSpec->Init(_data + start, inSize);
|
||||
_outStreamSpec->Init(dest, blockSize);
|
||||
RINOK(_zlibDecoder->Code(_inStream, _outStream, NULL, NULL, NULL));
|
||||
return (_zlibDecoderSpec->GetInputProcessedSize() == inSize &&
|
||||
_outStreamSpec->GetPos() == blockSize) ? S_OK : S_FALSE;
|
||||
}
|
||||
|
||||
STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems,
|
||||
Int32 testMode, IArchiveExtractCallback *extractCallback)
|
||||
{
|
||||
COM_TRY_BEGIN
|
||||
bool allFilesMode = (numItems == (UInt32)-1);
|
||||
if (allFilesMode)
|
||||
numItems = _items.Size();
|
||||
if (numItems == 0)
|
||||
return S_OK;
|
||||
bool be = _h.be;
|
||||
UInt64 totalSize = 0;
|
||||
UInt32 i;
|
||||
for (i = 0; i < numItems; i++)
|
||||
{
|
||||
const Byte *p = _data + _items[allFilesMode ? i : indices[i]].Offset;
|
||||
if (!IsDir(p, be))
|
||||
totalSize += GetSize(p, be);
|
||||
}
|
||||
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);
|
||||
|
||||
CLimitedSequentialInStream *streamSpec = new CLimitedSequentialInStream;
|
||||
CMyComPtr<ISequentialInStream> inStream(streamSpec);
|
||||
streamSpec->SetStream(_stream);
|
||||
|
||||
for (i = 0; i < numItems; i++)
|
||||
{
|
||||
lps->InSize = totalPackSize;
|
||||
lps->OutSize = totalSize;
|
||||
RINOK(lps->SetCur());
|
||||
CMyComPtr<ISequentialOutStream> outStream;
|
||||
Int32 askMode = testMode ?
|
||||
NExtract::NAskMode::kTest :
|
||||
NExtract::NAskMode::kExtract;
|
||||
UInt32 index = allFilesMode ? i : indices[i];
|
||||
const CItem &item = _items[index];
|
||||
RINOK(extractCallback->GetStream(index, &outStream, askMode));
|
||||
const Byte *p = _data + item.Offset;
|
||||
|
||||
if (IsDir(p, be))
|
||||
{
|
||||
RINOK(extractCallback->PrepareOperation(askMode));
|
||||
RINOK(extractCallback->SetOperationResult(NExtract::NOperationResult::kOK));
|
||||
continue;
|
||||
}
|
||||
UInt32 curSize = GetSize(p, be);
|
||||
totalSize += curSize;
|
||||
UInt32 packSize;
|
||||
if (GetPackSize(index, packSize))
|
||||
totalPackSize += packSize;
|
||||
|
||||
if (!testMode && !outStream)
|
||||
continue;
|
||||
RINOK(extractCallback->PrepareOperation(askMode));
|
||||
|
||||
UInt32 offset = GetOffset(p, be);
|
||||
if (offset < kHeaderSize)
|
||||
curSize = 0;
|
||||
|
||||
int res = NExtract::NOperationResult::kDataError;
|
||||
{
|
||||
CMyComPtr<ISequentialInStream> inSeqStream;
|
||||
CMyComPtr<IInStream> inStream;
|
||||
HRESULT hres = GetStream(index, &inSeqStream);
|
||||
if (inSeqStream)
|
||||
inSeqStream.QueryInterface(IID_IInStream, &inStream);
|
||||
if (hres == E_OUTOFMEMORY)
|
||||
return E_OUTOFMEMORY;
|
||||
if (hres == S_FALSE || !inStream)
|
||||
res = NExtract::NOperationResult::kUnSupportedMethod;
|
||||
else
|
||||
{
|
||||
RINOK(hres);
|
||||
if (inStream)
|
||||
{
|
||||
HRESULT hres = copyCoder->Code(inStream, outStream, NULL, NULL, progress);
|
||||
if (hres != S_OK && hres != S_FALSE)
|
||||
{
|
||||
RINOK(hres);
|
||||
}
|
||||
if (copyCoderSpec->TotalSize == curSize && hres == S_OK)
|
||||
res = NExtract::NOperationResult::kOK;
|
||||
}
|
||||
}
|
||||
}
|
||||
RINOK(extractCallback->SetOperationResult(res));
|
||||
}
|
||||
return S_OK;
|
||||
COM_TRY_END
|
||||
}
|
||||
|
||||
STDMETHODIMP CHandler::GetStream(UInt32 index, ISequentialInStream **stream)
|
||||
{
|
||||
COM_TRY_BEGIN
|
||||
|
||||
const CItem &item = _items[index];
|
||||
const Byte *p = _data + item.Offset;
|
||||
|
||||
bool be = _h.be;
|
||||
if (IsDir(p, be))
|
||||
return E_FAIL;
|
||||
|
||||
UInt32 size = GetSize(p, be);
|
||||
UInt32 numBlocks = (size + kBlockSize - 1) >> kBlockSizeLog;
|
||||
UInt32 offset = GetOffset(p, be);
|
||||
if (offset < kHeaderSize)
|
||||
{
|
||||
if (offset != 0)
|
||||
return S_FALSE;
|
||||
CBufInStream *streamSpec = new CBufInStream;
|
||||
CMyComPtr<IInStream> streamTemp = streamSpec;
|
||||
streamSpec->Init(NULL, 0);
|
||||
*stream = streamTemp.Detach();
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
if (offset + numBlocks * 4 > _size)
|
||||
return S_FALSE;
|
||||
UInt32 prev = offset;
|
||||
for (UInt32 i = 0; i < numBlocks; i++)
|
||||
{
|
||||
UInt32 next = Get32(_data + offset + i * 4);
|
||||
if (next < prev || next > _size)
|
||||
return S_FALSE;
|
||||
prev = next;
|
||||
}
|
||||
|
||||
CCramfsInStream *streamSpec = new CCramfsInStream;
|
||||
CMyComPtr<IInStream> streamTemp = streamSpec;
|
||||
_curNumBlocks = numBlocks;
|
||||
_curBlocksOffset = offset;
|
||||
streamSpec->Handler = this;
|
||||
if (!streamSpec->Alloc(kBlockSizeLog, 21 - kBlockSizeLog))
|
||||
return E_OUTOFMEMORY;
|
||||
streamSpec->Init(size);
|
||||
*stream = streamTemp.Detach();
|
||||
|
||||
return S_OK;
|
||||
COM_TRY_END
|
||||
}
|
||||
|
||||
static IInArchive *CreateArc() { return new NArchive::NCramfs::CHandler; }
|
||||
|
||||
static CArcInfo g_ArcInfo =
|
||||
{ L"CramFS", L"cramfs", 0, 0xD3, SIGNATURE, kSignatureSize, false, CreateArc, 0 };
|
||||
|
||||
REGISTER_ARC(Cramfs)
|
||||
|
||||
}}
|
||||
@@ -277,9 +277,9 @@ static const CUInt32PCharPair g_AbiOS[] =
|
||||
|
||||
static const CUInt32PCharPair g_SegmentFlags[] =
|
||||
{
|
||||
{ 1 << 0, "Execute" },
|
||||
{ 1 << 1, "Write" },
|
||||
{ 1 << 2, "Read" }
|
||||
{ 0, "Execute" },
|
||||
{ 1, "Write" },
|
||||
{ 2, "Read" }
|
||||
};
|
||||
|
||||
static const char *g_Types[] =
|
||||
|
||||
BIN
CPP/7zip/Archive/Icons/squashfs.ico
Executable file
BIN
CPP/7zip/Archive/Icons/squashfs.ico
Executable file
Binary file not shown.
|
After Width: | Height: | Size: 3.6 KiB |
@@ -24,7 +24,7 @@ using namespace NTime;
|
||||
namespace NArchive {
|
||||
namespace NIso {
|
||||
|
||||
static STATPROPSTG kProps[] =
|
||||
static const STATPROPSTG kProps[] =
|
||||
{
|
||||
{ NULL, kpidPath, VT_BSTR},
|
||||
{ NULL, kpidIsDir, VT_BOOL},
|
||||
@@ -33,8 +33,17 @@ static STATPROPSTG kProps[] =
|
||||
{ NULL, kpidMTime, VT_FILETIME}
|
||||
};
|
||||
|
||||
static const STATPROPSTG kArcProps[] =
|
||||
{
|
||||
{ NULL, kpidComment, VT_BSTR},
|
||||
{ NULL, kpidCTime, VT_FILETIME},
|
||||
{ NULL, kpidMTime, VT_FILETIME}
|
||||
// { NULL, kpidPhySize, VT_UI8},
|
||||
// { NULL, kpidHeadersSize, VT_UI8}
|
||||
};
|
||||
|
||||
IMP_IInArchive_Props
|
||||
IMP_IInArchive_ArcProps_NO
|
||||
IMP_IInArchive_ArcProps
|
||||
|
||||
STDMETHODIMP CHandler::Open(IInStream *stream,
|
||||
const UInt64 * /* maxCheckStartPosition */,
|
||||
@@ -66,6 +75,58 @@ STDMETHODIMP CHandler::GetNumberOfItems(UInt32 *numItems)
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
static void AddString(AString &s, const char *name, const Byte *p, int size)
|
||||
{
|
||||
int i;
|
||||
for (i = 0; i < size && p[i]; i++);
|
||||
for (; i > 0 && p[i - 1] == ' '; i--);
|
||||
if (i != 0)
|
||||
{
|
||||
AString d;
|
||||
memcpy(d.GetBuffer(i), p, i);
|
||||
d.ReleaseBuffer(i);
|
||||
s += '\n';
|
||||
s += name;
|
||||
s += ": ";
|
||||
s += d;
|
||||
}
|
||||
}
|
||||
|
||||
#define ADD_STRING(n, v) AddString(s, n, vol. ## v, sizeof(vol. ## v))
|
||||
|
||||
STDMETHODIMP CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value)
|
||||
{
|
||||
COM_TRY_BEGIN
|
||||
NWindows::NCOM::CPropVariant prop;
|
||||
const CVolumeDescriptor &vol = _archive.VolDescs[_archive.MainVolDescIndex];
|
||||
switch(propID)
|
||||
{
|
||||
case kpidComment:
|
||||
{
|
||||
AString s;
|
||||
ADD_STRING("System", SystemId);
|
||||
ADD_STRING("Volume", VolumeId);
|
||||
ADD_STRING("VolumeSet", VolumeSetId);
|
||||
ADD_STRING("Publisher", PublisherId);
|
||||
ADD_STRING("Preparer", DataPreparerId);
|
||||
ADD_STRING("Application", ApplicationId);
|
||||
ADD_STRING("Copyright", CopyrightFileId);
|
||||
ADD_STRING("Abstract", AbstractFileId);
|
||||
ADD_STRING("Bib", BibFileId);
|
||||
prop = s;
|
||||
break;
|
||||
}
|
||||
case kpidCTime: { FILETIME utc; if (vol.CTime.GetFileTime(utc)) prop = utc; break; }
|
||||
case kpidMTime: { FILETIME utc; if (vol.MTime.GetFileTime(utc)) prop = utc; break; }
|
||||
// case kpidPhySize: break;
|
||||
// case kpidHeadersSize: break;
|
||||
case kpidError: if (_archive.IncorrectBigEndian) prop = "Incorrect big-endian headers"; break;
|
||||
}
|
||||
prop.Detach(value);
|
||||
return S_OK;
|
||||
COM_TRY_END
|
||||
}
|
||||
|
||||
STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *value)
|
||||
{
|
||||
COM_TRY_BEGIN
|
||||
@@ -87,9 +148,7 @@ STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *val
|
||||
prop = (const wchar_t *)s;
|
||||
break;
|
||||
}
|
||||
case kpidIsDir:
|
||||
prop = false;
|
||||
break;
|
||||
case kpidIsDir: prop = false; break;
|
||||
case kpidSize:
|
||||
case kpidPackSize:
|
||||
prop = (UInt64)_archive.GetBootItemSize(index);
|
||||
@@ -121,9 +180,7 @@ STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *val
|
||||
prop = (const wchar_t *)NItemName::GetOSName2(s);
|
||||
}
|
||||
break;
|
||||
case kpidIsDir:
|
||||
prop = item.IsDir();
|
||||
break;
|
||||
case kpidIsDir: prop = item.IsDir(); break;
|
||||
case kpidSize:
|
||||
case kpidPackSize:
|
||||
if (!item.IsDir())
|
||||
@@ -131,16 +188,9 @@ STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *val
|
||||
break;
|
||||
case kpidMTime:
|
||||
{
|
||||
FILETIME utcFileTime;
|
||||
if (item.DateTime.GetFileTime(utcFileTime))
|
||||
prop = utcFileTime;
|
||||
/*
|
||||
else
|
||||
{
|
||||
utcFileTime.dwLowDateTime = 0;
|
||||
utcFileTime.dwHighDateTime = 0;
|
||||
}
|
||||
*/
|
||||
FILETIME utc;
|
||||
if (item.DateTime.GetFileTime(utc))
|
||||
prop = utc;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -65,7 +65,7 @@ UInt16 CInArchive::ReadUInt16()
|
||||
for (int i = 0; i < 2; i++)
|
||||
{
|
||||
if (b[i] != b[3 - i])
|
||||
throw 1;
|
||||
IncorrectBigEndian = true;
|
||||
value |= ((UInt16)(b[i]) << (8 * i));
|
||||
}
|
||||
return (UInt16)value;
|
||||
@@ -440,6 +440,7 @@ HRESULT CInArchive::Open(IInStream *inStream)
|
||||
|
||||
void CInArchive::Clear()
|
||||
{
|
||||
IncorrectBigEndian = false;
|
||||
Refs.Clear();
|
||||
_rootDir.Clear();
|
||||
VolDescs.Clear();
|
||||
|
||||
@@ -111,6 +111,20 @@ struct CDateTime
|
||||
signed char GmtOffset; // min intervals from -48 (West) to +52 (East) recorded.
|
||||
bool NotSpecified() const { return Year == 0 && Month == 0 && Day == 0 &&
|
||||
Hour == 0 && Minute == 0 && Second == 0 && GmtOffset == 0; }
|
||||
|
||||
bool GetFileTime(FILETIME &ft) const
|
||||
{
|
||||
UInt64 value;
|
||||
bool res = NWindows::NTime::GetSecondsSince1601(Year, Month, Day, Hour, Minute, Second, value);
|
||||
if (res)
|
||||
{
|
||||
value -= (UInt64)((Int64)GmtOffset * 15 * 60);
|
||||
value *= 10000000;
|
||||
}
|
||||
ft.dwLowDateTime = (DWORD)value;
|
||||
ft.dwHighDateTime = (DWORD)(value >> 32);
|
||||
return res;
|
||||
}
|
||||
};
|
||||
|
||||
struct CBootRecordDescriptor
|
||||
@@ -268,6 +282,7 @@ public:
|
||||
int MainVolDescIndex;
|
||||
UInt32 BlockSize;
|
||||
CObjectVector<CBootInitialEntry> BootEntries;
|
||||
bool IncorrectBigEndian;
|
||||
|
||||
|
||||
bool IsJoliet() const { return VolDescs[MainVolDescIndex].IsJoliet(); }
|
||||
|
||||
@@ -266,7 +266,7 @@ HRESULT CInArchive::GetNextItem(bool &filled, CItemEx &item)
|
||||
return (startHeader[0] == 0) ? S_OK: S_FALSE;
|
||||
|
||||
const Byte *p = header;
|
||||
memmove(item.Method, p, kMethodIdSize);
|
||||
memcpy(item.Method, p, kMethodIdSize);
|
||||
if (!item.IsValidMethod())
|
||||
return S_OK;
|
||||
p += kMethodIdSize;
|
||||
|
||||
@@ -77,16 +77,16 @@ static const char *g_FileTypes[] =
|
||||
|
||||
static const CUInt32PCharPair g_Flags[] =
|
||||
{
|
||||
{ (UInt32)1 << 31, "PURE_INSTRUCTIONS" },
|
||||
{ 1 << 30, "NO_TOC" },
|
||||
{ 1 << 29, "STRIP_STATIC_SYMS" },
|
||||
{ 1 << 28, "NO_DEAD_STRIP" },
|
||||
{ 1 << 27, "LIVE_SUPPORT" },
|
||||
{ 1 << 26, "SELF_MODIFYING_CODE" },
|
||||
{ 1 << 25, "DEBUG" },
|
||||
{ 1 << 10, "SOME_INSTRUCTIONS" },
|
||||
{ 1 << 9, "EXT_RELOC" },
|
||||
{ 1 << 8, "LOC_RELOC" }
|
||||
{ 31, "PURE_INSTRUCTIONS" },
|
||||
{ 30, "NO_TOC" },
|
||||
{ 29, "STRIP_STATIC_SYMS" },
|
||||
{ 28, "NO_DEAD_STRIP" },
|
||||
{ 27, "LIVE_SUPPORT" },
|
||||
{ 26, "SELF_MODIFYING_CODE" },
|
||||
{ 25, "DEBUG" },
|
||||
{ 10, "SOME_INSTRUCTIONS" },
|
||||
{ 9, "EXT_RELOC" },
|
||||
{ 8, "LOC_RELOC" }
|
||||
};
|
||||
|
||||
static const CUInt32PCharPair g_MachinePairs[] =
|
||||
|
||||
@@ -300,53 +300,53 @@ void CSection::Parse(const Byte *p)
|
||||
|
||||
static const CUInt32PCharPair g_HeaderCharacts[] =
|
||||
{
|
||||
{ 1 << 1, "Executable" },
|
||||
{ 1 << 13, "DLL" },
|
||||
{ 1 << 8, "32-bit" },
|
||||
{ 1 << 5, "LargeAddress" },
|
||||
{ 1 << 0, "NoRelocs" },
|
||||
{ 1 << 2, "NoLineNums" },
|
||||
{ 1 << 3, "NoLocalSyms" },
|
||||
{ 1 << 4, "AggressiveWsTrim" },
|
||||
{ 1 << 9, "NoDebugInfo" },
|
||||
{ 1 << 10, "RemovableRun" },
|
||||
{ 1 << 11, "NetRun" },
|
||||
{ 1 << 12, "System" },
|
||||
{ 1 << 14, "UniCPU" },
|
||||
{ 1 << 7, "Little-Endian" },
|
||||
{ 1 << 15, "Big-Endian" }
|
||||
{ 1, "Executable" },
|
||||
{ 13, "DLL" },
|
||||
{ 8, "32-bit" },
|
||||
{ 5, "LargeAddress" },
|
||||
{ 0, "NoRelocs" },
|
||||
{ 2, "NoLineNums" },
|
||||
{ 3, "NoLocalSyms" },
|
||||
{ 4, "AggressiveWsTrim" },
|
||||
{ 9, "NoDebugInfo" },
|
||||
{ 10, "RemovableRun" },
|
||||
{ 11, "NetRun" },
|
||||
{ 12, "System" },
|
||||
{ 14, "UniCPU" },
|
||||
{ 7, "Little-Endian" },
|
||||
{ 15, "Big-Endian" }
|
||||
};
|
||||
|
||||
static const CUInt32PCharPair g_DllCharacts[] =
|
||||
{
|
||||
{ 1 << 6, "Relocated" },
|
||||
{ 1 << 7, "Integrity" },
|
||||
{ 1 << 8, "NX-Compatible" },
|
||||
{ 1 << 9, "NoIsolation" },
|
||||
{ 1 << 10, "NoSEH" },
|
||||
{ 1 << 11, "NoBind" },
|
||||
{ 1 << 13, "WDM" },
|
||||
{ 1 << 15, "TerminalServerAware" }
|
||||
{ 6, "Relocated" },
|
||||
{ 7, "Integrity" },
|
||||
{ 8, "NX-Compatible" },
|
||||
{ 9, "NoIsolation" },
|
||||
{ 10, "NoSEH" },
|
||||
{ 11, "NoBind" },
|
||||
{ 13, "WDM" },
|
||||
{ 15, "TerminalServerAware" }
|
||||
};
|
||||
|
||||
static const CUInt32PCharPair g_SectFlags[] =
|
||||
{
|
||||
{ 1 << 3, "NoPad" },
|
||||
{ 1 << 5, "Code" },
|
||||
{ 1 << 6, "InitializedData" },
|
||||
{ 1 << 7, "UninitializedData" },
|
||||
{ 1 << 9, "Comments" },
|
||||
{ 1 << 11, "Remove" },
|
||||
{ 1 << 12, "COMDAT" },
|
||||
{ 1 << 15, "GP" },
|
||||
{ 1 << 24, "ExtendedRelocations" },
|
||||
{ 1 << 25, "Discardable" },
|
||||
{ 1 << 26, "NotCached" },
|
||||
{ 1 << 27, "NotPaged" },
|
||||
{ 1 << 28, "Shared" },
|
||||
{ 1 << 29, "Execute" },
|
||||
{ 1 << 30, "Read" },
|
||||
{ (UInt32)1 << 31, "Write" }
|
||||
{ 3, "NoPad" },
|
||||
{ 5, "Code" },
|
||||
{ 6, "InitializedData" },
|
||||
{ 7, "UninitializedData" },
|
||||
{ 9, "Comments" },
|
||||
{ 11, "Remove" },
|
||||
{ 12, "COMDAT" },
|
||||
{ 15, "GP" },
|
||||
{ 24, "ExtendedRelocations" },
|
||||
{ 25, "Discardable" },
|
||||
{ 26, "NotCached" },
|
||||
{ 27, "NotPaged" },
|
||||
{ 28, "Shared" },
|
||||
{ 29, "Execute" },
|
||||
{ 30, "Read" },
|
||||
{ 31, "Write" }
|
||||
};
|
||||
|
||||
static const CUInt32PCharPair g_MachinePairs[] =
|
||||
@@ -1723,6 +1723,14 @@ STDMETHODIMP CHandler::GetStream(UInt32 index, ISequentialInStream **stream)
|
||||
size_t offset = item.Offset - sect.Va;
|
||||
if (!CheckItem(sect, item, offset))
|
||||
return S_FALSE;
|
||||
if (item.HeaderSize == 0)
|
||||
{
|
||||
CBufInStream *streamSpec = new CBufInStream;
|
||||
CMyComPtr<IInStream> streamTemp2 = streamSpec;
|
||||
streamSpec->Init(_buf + offset, item.Size, (IInArchive *)this);
|
||||
*stream = streamTemp2.Detach();
|
||||
return S_OK;
|
||||
}
|
||||
referenceBuf->Buf.SetCapacity(item.HeaderSize + item.Size);
|
||||
memcpy(referenceBuf->Buf, item.Header, item.HeaderSize);
|
||||
memcpy(referenceBuf->Buf + item.HeaderSize, _buf + offset, item.Size);
|
||||
|
||||
@@ -46,7 +46,7 @@ static const int kNumHostOSes = sizeof(kHostOS) / sizeof(kHostOS[0]);
|
||||
|
||||
static const wchar_t *kUnknownOS = L"Unknown";
|
||||
|
||||
STATPROPSTG kProps[] =
|
||||
static const STATPROPSTG kProps[] =
|
||||
{
|
||||
{ NULL, kpidPath, VT_BSTR},
|
||||
{ NULL, kpidIsDir, VT_BOOL},
|
||||
@@ -68,7 +68,7 @@ STATPROPSTG kProps[] =
|
||||
{ NULL, kpidUnpackVer, VT_UI1}
|
||||
};
|
||||
|
||||
STATPROPSTG kArcProps[] =
|
||||
static const STATPROPSTG kArcProps[] =
|
||||
{
|
||||
{ NULL, kpidSolid, VT_BOOL},
|
||||
{ NULL, kpidNumBlocks, VT_UI4},
|
||||
@@ -93,7 +93,7 @@ UInt64 CHandler::GetPackSize(int refIndex) const
|
||||
|
||||
STDMETHODIMP CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value)
|
||||
{
|
||||
// COM_TRY_BEGIN
|
||||
COM_TRY_BEGIN
|
||||
NWindows::NCOM::CPropVariant prop;
|
||||
switch(propID)
|
||||
{
|
||||
@@ -112,10 +112,11 @@ STDMETHODIMP CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value)
|
||||
prop = (UInt32)numBlocks;
|
||||
break;
|
||||
}
|
||||
case kpidError: if (!_errorMessage.IsEmpty()) prop = _errorMessage; break;
|
||||
}
|
||||
prop.Detach(value);
|
||||
return S_OK;
|
||||
// COM_TRY_END
|
||||
COM_TRY_END
|
||||
}
|
||||
|
||||
STDMETHODIMP CHandler::GetNumberOfItems(UInt32 *numItems)
|
||||
@@ -396,7 +397,14 @@ HRESULT CHandler::Open2(IInStream *stream,
|
||||
for (;;)
|
||||
{
|
||||
bool decryptionError;
|
||||
HRESULT result = archive.GetNextItem(item, getTextPassword, decryptionError);
|
||||
AString errorMessageLoc;
|
||||
HRESULT result = archive.GetNextItem(item, getTextPassword, decryptionError, errorMessageLoc);
|
||||
if (errorMessageLoc)
|
||||
{
|
||||
if (!_errorMessage.IsEmpty())
|
||||
_errorMessage += '\n';
|
||||
_errorMessage += errorMessageLoc;
|
||||
}
|
||||
if (result == S_FALSE)
|
||||
{
|
||||
if (decryptionError && _items.IsEmpty())
|
||||
@@ -461,6 +469,7 @@ STDMETHODIMP CHandler::Open(IInStream *stream,
|
||||
STDMETHODIMP CHandler::Close()
|
||||
{
|
||||
COM_TRY_BEGIN
|
||||
_errorMessage.Empty();
|
||||
_refItems.Clear();
|
||||
_items.Clear();
|
||||
_archives.Clear();
|
||||
|
||||
@@ -32,6 +32,7 @@ private:
|
||||
CObjectVector<CItemEx> _items;
|
||||
CObjectVector<CInArchive> _archives;
|
||||
NArchive::NRar::CInArchiveInfo _archiveInfo;
|
||||
AString _errorMessage;
|
||||
|
||||
DECL_EXTERNAL_CODECS_VARS
|
||||
|
||||
|
||||
@@ -18,16 +18,16 @@ namespace NBlockType
|
||||
{
|
||||
enum EBlockType
|
||||
{
|
||||
kMarker = 0x72,
|
||||
kArchiveHeader = 0x73,
|
||||
kFileHeader = 0x74,
|
||||
kCommentHeader = 0x75,
|
||||
kOldAuthenticity = 0x76,
|
||||
kSubBlock = 0x77,
|
||||
kRecoveryRecord = 0x78,
|
||||
kAuthenticity = 0x79,
|
||||
|
||||
kEndOfArchive = 0x7B // Is not safe
|
||||
kMarker = 0x72,
|
||||
kArchiveHeader,
|
||||
kFileHeader,
|
||||
kCommentHeader,
|
||||
kOldAuthenticity,
|
||||
kOldSubBlock,
|
||||
kRecoveryRecord,
|
||||
kAuthenticity,
|
||||
kSubBlock,
|
||||
kEndOfArchive
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
@@ -372,14 +372,14 @@ void CInArchive::AddToSeekValue(UInt64 addValue)
|
||||
m_Position += addValue;
|
||||
}
|
||||
|
||||
HRESULT CInArchive::GetNextItem(CItemEx &item, ICryptoGetTextPassword *getTextPassword, bool &decryptionError)
|
||||
HRESULT CInArchive::GetNextItem(CItemEx &item, ICryptoGetTextPassword *getTextPassword, bool &decryptionError, AString &errorMessage)
|
||||
{
|
||||
decryptionError = false;
|
||||
if (m_SeekOnArchiveComment)
|
||||
SkipArchiveComment();
|
||||
for (;;)
|
||||
{
|
||||
if(!SeekInArchive(m_Position))
|
||||
if (!SeekInArchive(m_Position))
|
||||
return S_FALSE;
|
||||
if (!m_CryptoMode && (m_ArchiveHeader.Flags &
|
||||
NHeader::NArchive::kBlockHeadersAreEncrypted) != 0)
|
||||
@@ -438,8 +438,11 @@ HRESULT CInArchive::GetNextItem(CItemEx &item, ICryptoGetTextPassword *getTextPa
|
||||
}
|
||||
|
||||
m_FileHeaderData.EnsureCapacity(7);
|
||||
if(!ReadBytesAndTestSize((Byte *)m_FileHeaderData, 7))
|
||||
if (!ReadBytesAndTestSize((Byte *)m_FileHeaderData, 7))
|
||||
{
|
||||
errorMessage = "Unexpected end of archive";
|
||||
return S_FALSE;
|
||||
}
|
||||
|
||||
m_CurData = (Byte *)m_FileHeaderData;
|
||||
m_CurPos = 0;
|
||||
|
||||
@@ -110,7 +110,7 @@ class CInArchive
|
||||
public:
|
||||
HRESULT Open(IInStream *inStream, const UInt64 *searchHeaderSizeLimit);
|
||||
void Close();
|
||||
HRESULT GetNextItem(CItemEx &item, ICryptoGetTextPassword *getTextPassword, bool &decryptionError);
|
||||
HRESULT GetNextItem(CItemEx &item, ICryptoGetTextPassword *getTextPassword, bool &decryptionError, AString &errorMessage);
|
||||
|
||||
void SkipArchiveComment();
|
||||
|
||||
|
||||
@@ -79,7 +79,7 @@ static HRESULT RedSigHeaderSig(IInStream *inStream, CSigHeaderSig &h)
|
||||
char dat[kCSigHeaderSigSize];
|
||||
char *cur = dat;
|
||||
RINOK(ReadStream_FALSE(inStream, dat, kCSigHeaderSigSize));
|
||||
memmove(h.Magic, cur, 4);
|
||||
memcpy(h.Magic, cur, 4);
|
||||
cur += 4;
|
||||
cur += 4;
|
||||
h.IndexLen = Get32(cur);
|
||||
@@ -95,7 +95,7 @@ HRESULT OpenArchive(IInStream *inStream)
|
||||
char *cur = leadData;
|
||||
CLead lead;
|
||||
RINOK(ReadStream_FALSE(inStream, leadData, kLeadSize));
|
||||
memmove(lead.Magic, cur, 4);
|
||||
memcpy(lead.Magic, cur, 4);
|
||||
cur += 4;
|
||||
lead.Major = *cur++;
|
||||
lead.Minor = *cur++;
|
||||
@@ -103,7 +103,7 @@ HRESULT OpenArchive(IInStream *inStream)
|
||||
cur += 2;
|
||||
lead.ArchNum = Get16(cur);
|
||||
cur += 2;
|
||||
memmove(lead.Name, cur, sizeof(lead.Name));
|
||||
memcpy(lead.Name, cur, sizeof(lead.Name));
|
||||
cur += sizeof(lead.Name);
|
||||
lead.OSNum = Get16(cur);
|
||||
cur += 2;
|
||||
|
||||
@@ -347,7 +347,6 @@ STDMETHODIMP CHandler::GetStream(UInt32 index, ISequentialInStream **stream)
|
||||
{
|
||||
CMultiStream::CSubStreamInfo subStreamInfo;
|
||||
subStreamInfo.Stream = _streams[i];
|
||||
subStreamInfo.Pos = 0;
|
||||
subStreamInfo.Size = _sizes[i];
|
||||
streamSpec->Streams.Add(subStreamInfo);
|
||||
}
|
||||
|
||||
1959
CPP/7zip/Archive/SquashfsHandler.cpp
Executable file
1959
CPP/7zip/Archive/SquashfsHandler.cpp
Executable file
File diff suppressed because it is too large
Load Diff
@@ -10,6 +10,8 @@
|
||||
|
||||
#include "../../Common/LimitedStreams.h"
|
||||
#include "../../Common/ProgressUtils.h"
|
||||
#include "../../Common/StreamObjects.h"
|
||||
#include "../../Common/StreamUtils.h"
|
||||
|
||||
#include "../Common/ItemNameUtils.h"
|
||||
|
||||
@@ -21,7 +23,9 @@ using namespace NWindows;
|
||||
namespace NArchive {
|
||||
namespace NTar {
|
||||
|
||||
static STATPROPSTG kProps[] =
|
||||
static const char *kUnexpectedEnd = "Unexpected end of archive";
|
||||
|
||||
static const STATPROPSTG kProps[] =
|
||||
{
|
||||
{ NULL, kpidPath, VT_BSTR},
|
||||
{ NULL, kpidIsDir, VT_BOOL},
|
||||
@@ -34,8 +38,14 @@ static STATPROPSTG kProps[] =
|
||||
{ NULL, kpidLink, VT_BSTR}
|
||||
};
|
||||
|
||||
static const STATPROPSTG kArcProps[] =
|
||||
{
|
||||
{ NULL, kpidPhySize, VT_UI8},
|
||||
{ NULL, kpidHeadersSize, VT_UI8}
|
||||
};
|
||||
|
||||
IMP_IInArchive_Props
|
||||
IMP_IInArchive_ArcProps_NO_Table
|
||||
IMP_IInArchive_ArcProps
|
||||
|
||||
STDMETHODIMP CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value)
|
||||
{
|
||||
@@ -43,11 +53,22 @@ STDMETHODIMP CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value)
|
||||
switch(propID)
|
||||
{
|
||||
case kpidPhySize: if (_phySizeDefined) prop = _phySize; break;
|
||||
case kpidHeadersSize: if (_phySizeDefined) prop = _headersSize; break;
|
||||
case kpidError: if (!_errorMessage.IsEmpty()) prop = _errorMessage; break;
|
||||
}
|
||||
prop.Detach(value);
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
HRESULT CHandler::ReadItem2(ISequentialInStream *stream, bool &filled, CItemEx &item)
|
||||
{
|
||||
item.HeaderPos = _phySize;
|
||||
RINOK(ReadItem(stream, filled, item, _errorMessage));
|
||||
_phySize += item.HeaderSize;
|
||||
_headersSize += item.HeaderSize;
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
HRESULT CHandler::Open2(IInStream *stream, IArchiveOpenCallback *callback)
|
||||
{
|
||||
UInt64 endPos = 0;
|
||||
@@ -56,26 +77,29 @@ HRESULT CHandler::Open2(IInStream *stream, IArchiveOpenCallback *callback)
|
||||
RINOK(stream->Seek(0, STREAM_SEEK_SET, NULL));
|
||||
}
|
||||
|
||||
_isGood = true;
|
||||
UInt64 pos = 0;
|
||||
_phySizeDefined = true;
|
||||
for (;;)
|
||||
{
|
||||
CItemEx item;
|
||||
bool filled;
|
||||
item.HeaderPosition = pos;
|
||||
RINOK(ReadItem(stream, filled, item));
|
||||
RINOK(ReadItem2(stream, filled, item));
|
||||
if (!filled)
|
||||
break;
|
||||
_items.Add(item);
|
||||
|
||||
RINOK(stream->Seek(item.GetPackSize(), STREAM_SEEK_CUR, &pos));
|
||||
if (pos > endPos)
|
||||
return S_FALSE;
|
||||
if (pos == endPos)
|
||||
RINOK(stream->Seek(item.GetPackSize(), STREAM_SEEK_CUR, &_phySize));
|
||||
if (_phySize > endPos)
|
||||
{
|
||||
_isGood = false;
|
||||
_errorMessage = kUnexpectedEnd;
|
||||
break;
|
||||
}
|
||||
/*
|
||||
if (_phySize == endPos)
|
||||
{
|
||||
_errorMessage = "There are no trailing zero-filled records";
|
||||
break;
|
||||
}
|
||||
*/
|
||||
if (callback != NULL)
|
||||
{
|
||||
if (_items.Size() == 1)
|
||||
@@ -85,7 +109,7 @@ HRESULT CHandler::Open2(IInStream *stream, IArchiveOpenCallback *callback)
|
||||
if (_items.Size() % 100 == 0)
|
||||
{
|
||||
UInt64 numFiles = _items.Size();
|
||||
RINOK(callback->SetCompleted(&numFiles, &pos));
|
||||
RINOK(callback->SetCompleted(&numFiles, &_phySize));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -132,7 +156,10 @@ STDMETHODIMP CHandler::OpenSeq(ISequentialInStream *stream)
|
||||
|
||||
STDMETHODIMP CHandler::Close()
|
||||
{
|
||||
_errorMessage.Empty();
|
||||
_phySizeDefined = false;
|
||||
_phySize = 0;
|
||||
_headersSize = 0;
|
||||
_curIndex = 0;
|
||||
_latestIsRead = false;
|
||||
_items.Clear();
|
||||
@@ -161,16 +188,24 @@ HRESULT CHandler::SkipTo(UInt32 index)
|
||||
{
|
||||
UInt64 packSize = _latestItem.GetPackSize();
|
||||
RINOK(copyCoderSpec->Code(_seqStream, NULL, &packSize, &packSize, NULL));
|
||||
_phySize += copyCoderSpec->TotalSize;
|
||||
if (copyCoderSpec->TotalSize != packSize)
|
||||
{
|
||||
_errorMessage = kUnexpectedEnd;
|
||||
return S_FALSE;
|
||||
}
|
||||
_latestIsRead = false;
|
||||
_curIndex++;
|
||||
}
|
||||
else
|
||||
{
|
||||
bool filled;
|
||||
// item.HeaderPosition = pos;
|
||||
RINOK(ReadItem(_seqStream, filled, _latestItem));
|
||||
RINOK(ReadItem2(_seqStream, filled, _latestItem));
|
||||
if (!filled)
|
||||
{
|
||||
_phySizeDefined = true;
|
||||
return E_INVALIDARG;
|
||||
}
|
||||
_latestIsRead = true;
|
||||
}
|
||||
}
|
||||
@@ -203,10 +238,10 @@ STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *val
|
||||
|
||||
switch(propID)
|
||||
{
|
||||
case kpidPath: prop = NItemName::GetOSName2(TarStringToUnicode(item->Name)); break;
|
||||
case kpidIsDir: prop = item->IsDir(); break;
|
||||
case kpidSize: prop = item->Size; break;
|
||||
case kpidPackSize: prop = item->GetPackSize(); break;
|
||||
case kpidPath: prop = NItemName::GetOSName2(TarStringToUnicode(item->Name)); break;
|
||||
case kpidIsDir: prop = item->IsDir(); break;
|
||||
case kpidSize: prop = item->GetUnpackSize(); break;
|
||||
case kpidPackSize: prop = item->GetPackSize(); break;
|
||||
case kpidMTime:
|
||||
if (item->MTime != 0)
|
||||
{
|
||||
@@ -216,9 +251,9 @@ STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *val
|
||||
}
|
||||
break;
|
||||
case kpidPosixAttrib: prop = item->Mode; break;
|
||||
case kpidUser: prop = TarStringToUnicode(item->User); break;
|
||||
case kpidGroup: prop = TarStringToUnicode(item->Group); break;
|
||||
case kpidLink: prop = TarStringToUnicode(item->LinkName); break;
|
||||
case kpidUser: prop = TarStringToUnicode(item->User); break;
|
||||
case kpidGroup: prop = TarStringToUnicode(item->Group); break;
|
||||
case kpidLink: prop = TarStringToUnicode(item->LinkName); break;
|
||||
}
|
||||
prop.Detach(value);
|
||||
return S_OK;
|
||||
@@ -242,7 +277,7 @@ HRESULT CHandler::Extract(const UInt32 *indices, UInt32 numItems,
|
||||
UInt64 totalSize = 0;
|
||||
UInt32 i;
|
||||
for (i = 0; i < numItems; i++)
|
||||
totalSize += _items[allFilesMode ? i : indices[i]].Size;
|
||||
totalSize += _items[allFilesMode ? i : indices[i]].GetUnpackSize();
|
||||
extractCallback->SetTotal(totalSize);
|
||||
|
||||
UInt64 totalPackSize;
|
||||
@@ -282,7 +317,8 @@ HRESULT CHandler::Extract(const UInt32 *indices, UInt32 numItems,
|
||||
item = &_items[index];
|
||||
|
||||
RINOK(extractCallback->GetStream(index, &realOutStream, askMode));
|
||||
totalSize += item->Size;
|
||||
UInt64 unpackSize = item->GetUnpackSize();
|
||||
totalSize += unpackSize;
|
||||
totalPackSize += item->GetPackSize();
|
||||
if (item->IsDir())
|
||||
{
|
||||
@@ -302,14 +338,21 @@ HRESULT CHandler::Extract(const UInt32 *indices, UInt32 numItems,
|
||||
|
||||
outStreamSpec->SetStream(realOutStream);
|
||||
realOutStream.Release();
|
||||
outStreamSpec->Init(skipMode ? 0 : item->Size, true);
|
||||
outStreamSpec->Init(skipMode ? 0 : unpackSize, true);
|
||||
|
||||
if (!seqMode)
|
||||
if (item->IsLink())
|
||||
{
|
||||
RINOK(_stream->Seek(item->GetDataPosition(), STREAM_SEEK_SET, NULL));
|
||||
RINOK(WriteStream(outStreamSpec, (const char *)item->LinkName, item->LinkName.Length()));
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!seqMode)
|
||||
{
|
||||
RINOK(_stream->Seek(item->GetDataPosition(), STREAM_SEEK_SET, NULL));
|
||||
}
|
||||
streamSpec->Init(item->GetPackSize());
|
||||
RINOK(copyCoder->Code(inStream, outStream, NULL, NULL, progress));
|
||||
}
|
||||
streamSpec->Init(item->GetPackSize());
|
||||
RINOK(copyCoder->Code(inStream, outStream, NULL, NULL, progress));
|
||||
if (seqMode)
|
||||
{
|
||||
_latestIsRead = false;
|
||||
@@ -328,6 +371,14 @@ STDMETHODIMP CHandler::GetStream(UInt32 index, ISequentialInStream **stream)
|
||||
{
|
||||
COM_TRY_BEGIN
|
||||
const CItemEx &item = _items[index];
|
||||
if (item.IsLink())
|
||||
{
|
||||
CBufInStream *streamSpec = new CBufInStream;
|
||||
CMyComPtr<IInStream> streamTemp = streamSpec;
|
||||
streamSpec->Init((const Byte *)(const char *)item.LinkName, item.LinkName.Length(), (IInArchive *)this);
|
||||
*stream = streamTemp.Detach();
|
||||
return S_OK;
|
||||
}
|
||||
return CreateLimitedInStream(_stream, item.GetDataPosition(), item.Size, stream);
|
||||
COM_TRY_END
|
||||
}
|
||||
|
||||
@@ -23,18 +23,20 @@ class CHandler:
|
||||
CObjectVector<CItemEx> _items;
|
||||
CMyComPtr<IInStream> _stream;
|
||||
CMyComPtr<ISequentialInStream> _seqStream;
|
||||
bool _isGood;
|
||||
|
||||
UInt32 _curIndex;
|
||||
bool _latestIsRead;
|
||||
CItemEx _latestItem;
|
||||
|
||||
UInt64 _phySize;
|
||||
UInt64 _headersSize;
|
||||
bool _phySizeDefined;
|
||||
AString _errorMessage;
|
||||
|
||||
NCompress::CCopyCoder *copyCoderSpec;
|
||||
CMyComPtr<ICompressCoder> copyCoder;
|
||||
|
||||
HRESULT ReadItem2(ISequentialInStream *stream, bool &filled, CItemEx &itemInfo);
|
||||
HRESULT Open2(IInStream *stream, IArchiveOpenCallback *callback);
|
||||
HRESULT SkipTo(UInt32 index);
|
||||
|
||||
|
||||
@@ -37,7 +37,7 @@ STDMETHODIMP CHandler::UpdateItems(ISequentialOutStream *outStream, UInt32 numIt
|
||||
IArchiveUpdateCallback *callback)
|
||||
{
|
||||
COM_TRY_BEGIN
|
||||
if ((_stream && !_isGood) || _seqStream)
|
||||
if ((_stream && !_errorMessage.IsEmpty()) || _seqStream)
|
||||
return E_NOTIMPL;
|
||||
CObjectVector<CUpdateItem> updateItems;
|
||||
for (UInt32 i = 0; i < numItems; i++)
|
||||
|
||||
@@ -63,29 +63,40 @@ static void ReadString(const char *s, int size, AString &result)
|
||||
result = temp;
|
||||
}
|
||||
|
||||
static HRESULT GetNextItemReal(ISequentialInStream *stream, bool &filled, CItemEx &item, size_t &processedSize)
|
||||
static HRESULT GetNextItemReal(ISequentialInStream *stream, bool &filled, CItemEx &item, AString &error)
|
||||
{
|
||||
item.LongLinkSize = 0;
|
||||
char buf[NFileHeader::kRecordSize];
|
||||
char *p = buf;
|
||||
|
||||
error.Empty();
|
||||
filled = false;
|
||||
|
||||
bool thereAreEmptyRecords = false;
|
||||
for (;;)
|
||||
{
|
||||
processedSize = NFileHeader::kRecordSize;
|
||||
size_t processedSize = NFileHeader::kRecordSize;
|
||||
RINOK(ReadStream(stream, buf, &processedSize));
|
||||
if (processedSize == 0)
|
||||
{
|
||||
if (!thereAreEmptyRecords )
|
||||
error = "There are no trailing zero-filled records";
|
||||
return S_OK;
|
||||
}
|
||||
if (processedSize != NFileHeader::kRecordSize)
|
||||
return S_FALSE;
|
||||
{
|
||||
error = "There is no correct record at the end of archive";
|
||||
return S_OK;
|
||||
}
|
||||
item.HeaderSize += NFileHeader::kRecordSize;
|
||||
if (!IsRecordLast(buf))
|
||||
break;
|
||||
thereAreEmptyRecords = true;
|
||||
}
|
||||
if (thereAreEmptyRecords)
|
||||
return S_FALSE;
|
||||
{
|
||||
error = "There are data after end of archive";
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
ReadString(p, NFileHeader::kNameSize, item.Name); p += NFileHeader::kNameSize;
|
||||
|
||||
@@ -143,59 +154,54 @@ static HRESULT GetNextItemReal(ISequentialInStream *stream, bool &filled, CItemE
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
HRESULT ReadItem(ISequentialInStream *stream, bool &filled, CItemEx &item)
|
||||
HRESULT ReadItem(ISequentialInStream *stream, bool &filled, CItemEx &item, AString &error)
|
||||
{
|
||||
size_t processedSize;
|
||||
RINOK(GetNextItemReal(stream, filled, item, processedSize));
|
||||
if (!filled)
|
||||
return S_OK;
|
||||
// GNUtar extension
|
||||
if (item.LinkFlag == 'L' || // NEXT file has a long name
|
||||
item.LinkFlag == 'K') // NEXT file has a long linkname
|
||||
item.HeaderSize = 0;
|
||||
bool flagL = false;
|
||||
bool flagK = false;
|
||||
AString nameL;
|
||||
AString nameK;
|
||||
for (;;)
|
||||
{
|
||||
if (item.Name.Compare(NFileHeader::kLongLink) != 0)
|
||||
if (item.Name.Compare(NFileHeader::kLongLink2) != 0)
|
||||
RINOK(GetNextItemReal(stream, filled, item, error));
|
||||
if (!filled)
|
||||
return S_OK;
|
||||
if (item.LinkFlag == 'L' || // NEXT file has a long name
|
||||
item.LinkFlag == 'K') // NEXT file has a long linkname
|
||||
{
|
||||
AString *name;
|
||||
if (item.LinkFlag == 'L')
|
||||
{ if (flagL) return S_FALSE; flagL = true; name = &nameL; }
|
||||
else
|
||||
{ if (flagK) return S_FALSE; flagK = true; name = &nameK; }
|
||||
|
||||
if (item.Name.Compare(NFileHeader::kLongLink) != 0 &&
|
||||
item.Name.Compare(NFileHeader::kLongLink2) != 0)
|
||||
return S_FALSE;
|
||||
|
||||
AString fullName;
|
||||
if (item.Size > (1 << 15))
|
||||
if (item.Size > (1 << 14))
|
||||
return S_FALSE;
|
||||
int packSize = (int)item.GetPackSize();
|
||||
char *buf = name->GetBuffer(packSize);
|
||||
RINOK(ReadStream_FALSE(stream, buf, packSize));
|
||||
item.HeaderSize += packSize;
|
||||
buf[(size_t)item.Size] = '\0';
|
||||
name->ReleaseBuffer();
|
||||
continue;
|
||||
}
|
||||
if (item.LinkFlag == 'g' || item.LinkFlag == 'x' || item.LinkFlag == 'X')
|
||||
{
|
||||
// pax Extended Header
|
||||
}
|
||||
else if (item.LinkFlag == NFileHeader::NLinkFlag::kDumpDir)
|
||||
{
|
||||
// GNU Extensions to the Archive Format
|
||||
}
|
||||
else if (item.LinkFlag > '7' || (item.LinkFlag < '0' && item.LinkFlag != 0))
|
||||
return S_FALSE;
|
||||
int packSize = (int)item.GetPackSize();
|
||||
char *buffer = fullName.GetBuffer(packSize + 1);
|
||||
|
||||
RINOK(ReadStream_FALSE(stream, buffer, packSize));
|
||||
processedSize += packSize;
|
||||
buffer[item.Size] = '\0';
|
||||
fullName.ReleaseBuffer();
|
||||
|
||||
UInt64 headerPosition = item.HeaderPosition;
|
||||
if (item.LinkFlag == 'L')
|
||||
{
|
||||
size_t processedSize2;
|
||||
RINOK(GetNextItemReal(stream, filled, item, processedSize2));
|
||||
item.LongLinkSize = (unsigned)processedSize;
|
||||
}
|
||||
else
|
||||
{
|
||||
item.LongLinkSize = (unsigned)processedSize - NFileHeader::kRecordSize;
|
||||
item.Size = 0;
|
||||
}
|
||||
item.Name = fullName;
|
||||
item.HeaderPosition = headerPosition;
|
||||
}
|
||||
else if (item.LinkFlag == 'g' || item.LinkFlag == 'x' || item.LinkFlag == 'X')
|
||||
{
|
||||
// pax Extended Header
|
||||
if (flagL) item.Name = nameL;
|
||||
if (flagK) item.LinkName = nameK;
|
||||
return S_OK;
|
||||
}
|
||||
else if (item.LinkFlag == NFileHeader::NLinkFlag::kDumpDir)
|
||||
{
|
||||
// GNU Extensions to the Archive Format
|
||||
return S_OK;
|
||||
}
|
||||
else if (item.LinkFlag > '7' || (item.LinkFlag < '0' && item.LinkFlag != 0))
|
||||
return S_FALSE;
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
}}
|
||||
|
||||
@@ -1,9 +1,8 @@
|
||||
// Archive/TarIn.h
|
||||
// TarIn.h
|
||||
|
||||
#ifndef __ARCHIVE_TAR_IN_H
|
||||
#define __ARCHIVE_TAR_IN_H
|
||||
|
||||
#include "Common/MyCom.h"
|
||||
#include "../../IStream.h"
|
||||
|
||||
#include "TarItem.h"
|
||||
@@ -11,7 +10,7 @@
|
||||
namespace NArchive {
|
||||
namespace NTar {
|
||||
|
||||
HRESULT ReadItem(ISequentialInStream *stream, bool &filled, CItemEx &itemInfo);
|
||||
HRESULT ReadItem(ISequentialInStream *stream, bool &filled, CItemEx &itemInfo, AString &error);
|
||||
|
||||
}}
|
||||
|
||||
|
||||
@@ -31,6 +31,9 @@ struct CItem
|
||||
bool DeviceMajorDefined;
|
||||
bool DeviceMinorDefined;
|
||||
|
||||
bool IsLink() const { return LinkFlag == NFileHeader::NLinkFlag::kSymbolicLink && (Size == 0); }
|
||||
UInt64 GetUnpackSize() const { return IsLink() ? LinkName.Length() : Size; }
|
||||
|
||||
bool IsDir() const
|
||||
{
|
||||
switch(LinkFlag)
|
||||
@@ -58,10 +61,10 @@ struct CItem
|
||||
|
||||
struct CItemEx: public CItem
|
||||
{
|
||||
UInt64 HeaderPosition;
|
||||
unsigned LongLinkSize;
|
||||
UInt64 GetDataPosition() const { return HeaderPosition + LongLinkSize + NFileHeader::kRecordSize; }
|
||||
UInt64 GetFullSize() const { return LongLinkSize + NFileHeader::kRecordSize + Size; }
|
||||
UInt64 HeaderPos;
|
||||
unsigned HeaderSize;
|
||||
UInt64 GetDataPosition() const { return HeaderPos + HeaderSize; }
|
||||
UInt64 GetFullSize() const { return HeaderSize + Size; }
|
||||
};
|
||||
|
||||
}}
|
||||
|
||||
@@ -111,25 +111,25 @@ HRESULT UpdateArchive(IInStream *inStream, ISequentialOutStream *outStream,
|
||||
}
|
||||
else
|
||||
{
|
||||
const CItemEx &existItemInfo = inputItems[ui.IndexInArchive];
|
||||
const CItemEx &existItem = inputItems[ui.IndexInArchive];
|
||||
UInt64 size;
|
||||
if (ui.NewProps)
|
||||
{
|
||||
RINOK(outArchive.WriteHeader(item));
|
||||
RINOK(inStream->Seek(existItemInfo.GetDataPosition(), STREAM_SEEK_SET, NULL));
|
||||
size = existItemInfo.Size;
|
||||
RINOK(inStream->Seek(existItem.GetDataPosition(), STREAM_SEEK_SET, NULL));
|
||||
size = existItem.Size;
|
||||
}
|
||||
else
|
||||
{
|
||||
RINOK(inStream->Seek(existItemInfo.HeaderPosition, STREAM_SEEK_SET, NULL));
|
||||
size = existItemInfo.GetFullSize();
|
||||
RINOK(inStream->Seek(existItem.HeaderPos, STREAM_SEEK_SET, NULL));
|
||||
size = existItem.GetFullSize();
|
||||
}
|
||||
streamSpec->Init(size);
|
||||
|
||||
RINOK(copyCoder->Code(inStreamLimited, outStream, NULL, NULL, progress));
|
||||
if (copyCoderSpec->TotalSize != size)
|
||||
return E_FAIL;
|
||||
RINOK(outArchive.FillDataResidual(existItemInfo.Size));
|
||||
RINOK(outArchive.FillDataResidual(existItem.Size));
|
||||
complexity += size;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -323,25 +323,13 @@ static void AddTagUInt64(AString &s, const char *name, UInt64 value)
|
||||
AddTag(s, name, temp);
|
||||
}
|
||||
|
||||
static void ConvertUInt32ToHex(UInt32 value, char *s)
|
||||
{
|
||||
for (int i = 0; i < 8; i++)
|
||||
{
|
||||
int t = value & 0xF;
|
||||
value >>= 4;
|
||||
s[7 - i] = (char)((t < 10) ? ('0' + t) : ('A' + (t - 10)));
|
||||
}
|
||||
s[8] = '\0';
|
||||
}
|
||||
|
||||
|
||||
static AString TimeToXml(FILETIME &ft)
|
||||
{
|
||||
AString res;
|
||||
char temp[16] = { '0', 'x' };
|
||||
ConvertUInt32ToHex(ft.dwHighDateTime, temp + 2);
|
||||
ConvertUInt32ToHexWithZeros(ft.dwHighDateTime, temp + 2);
|
||||
AddTag(res, "HIGHPART", temp);
|
||||
ConvertUInt32ToHex(ft.dwLowDateTime, temp + 2);
|
||||
ConvertUInt32ToHexWithZeros(ft.dwLowDateTime, temp + 2);
|
||||
AddTag(res, "LOWPART", temp);
|
||||
return res;
|
||||
}
|
||||
|
||||
@@ -240,7 +240,7 @@ static HRESULT UnpackData(IInStream *inStream, const CResource &resource, bool l
|
||||
buf.Free();
|
||||
buf.SetCapacity(size);
|
||||
|
||||
CSequentialOutStreamImp2 *outStreamSpec = new CSequentialOutStreamImp2();
|
||||
CBufPtrSeqOutStream *outStreamSpec = new CBufPtrSeqOutStream();
|
||||
CMyComPtr<ISequentialOutStream> outStream = outStreamSpec;
|
||||
outStreamSpec->Init((Byte *)buf, size);
|
||||
|
||||
|
||||
@@ -268,7 +268,7 @@ HRESULT CHandler::Open2(IInStream *stream)
|
||||
inStreamLimSpec->SetStream(stream);
|
||||
inStreamLimSpec->Init(packSize);
|
||||
|
||||
CSequentialOutStreamImp2 *outStreamLimSpec = new CSequentialOutStreamImp2;
|
||||
CBufPtrSeqOutStream *outStreamLimSpec = new CBufPtrSeqOutStream;
|
||||
CMyComPtr<ISequentialOutStream> outStreamLim(outStreamLimSpec);
|
||||
outStreamLimSpec->Init((Byte *)ss, (size_t)unpackSize);
|
||||
|
||||
|
||||
@@ -53,18 +53,17 @@ HRESULT CLzmaEncoder::SetCoderProperties(const PROPID *propIDs, const PROPVARIAN
|
||||
EncoderSpec = new NCompress::NLzma::CEncoder;
|
||||
Encoder = EncoderSpec;
|
||||
}
|
||||
CSequentialOutStreamImp *outStreamSpec = new CSequentialOutStreamImp;
|
||||
CBufPtrSeqOutStream *outStreamSpec = new CBufPtrSeqOutStream;
|
||||
CMyComPtr<ISequentialOutStream> outStream(outStreamSpec);
|
||||
outStreamSpec->Init();
|
||||
outStreamSpec->Init(Header + 4, kLzmaPropsSize);
|
||||
RINOK(EncoderSpec->SetCoderProperties(propIDs, props, numProps));
|
||||
RINOK(EncoderSpec->WriteCoderProperties(outStream));
|
||||
if (outStreamSpec->GetSize() != kLzmaPropsSize)
|
||||
if (outStreamSpec->GetPos() != kLzmaPropsSize)
|
||||
return E_FAIL;
|
||||
Header[0] = MY_VER_MAJOR;
|
||||
Header[1] = MY_VER_MINOR;
|
||||
Header[2] = kLzmaPropsSize;
|
||||
Header[3] = 0;
|
||||
memcpy(Header + 4, outStreamSpec->GetBuffer(), kLzmaPropsSize);
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user