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

github.com/kornelski/7z.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'CPP/7zip/Archive/SquashfsHandler.cpp')
-rw-r--r--[-rwxr-xr-x]CPP/7zip/Archive/SquashfsHandler.cpp240
1 files changed, 138 insertions, 102 deletions
diff --git a/CPP/7zip/Archive/SquashfsHandler.cpp b/CPP/7zip/Archive/SquashfsHandler.cpp
index efaffed1..617a1d66 100755..100644
--- a/CPP/7zip/Archive/SquashfsHandler.cpp
+++ b/CPP/7zip/Archive/SquashfsHandler.cpp
@@ -7,12 +7,12 @@
#include "../../../C/CpuArch.h"
#include "../../../C/Xz.h"
-#include "Common/ComTry.h"
-#include "Common/IntToString.h"
-#include "Common/StringConvert.h"
+#include "../../Common/ComTry.h"
+#include "../../Common/IntToString.h"
+#include "../../Common/StringConvert.h"
-#include "Windows/PropVariantUtils.h"
-#include "Windows/Time.h"
+#include "../../Windows/PropVariantUtils.h"
+#include "../../Windows/TimeUtils.h"
#include "../Common/CWrappers.h"
#include "../Common/LimitedStreams.h"
@@ -59,8 +59,6 @@ UInt64 Get64b(const Byte *p, bool be) { return be ? GetBe64(p) : GetUi64(p); }
#define GET_32(offs, dest) dest = Get32(p + (offs));
#define GET_64(offs, dest) dest = Get64(p + (offs));
-static const UInt32 kSignatureSize = 4;
-#define SIGNATURE { 'h', 's', 'q', 's' }
static const UInt32 kSignature32_LE = 0x73717368;
static const UInt32 kSignature32_BE = 0x68737173;
static const UInt32 kSignature32_LZ = 0x71736873;
@@ -72,11 +70,11 @@ static const UInt32 kSignature32_LZ = 0x71736873;
static const char *k_Methods[] =
{
- "Unknown",
- "ZLIB",
- "LZMA",
- "LZO",
- "XZ"
+ "Unknown"
+ , "ZLIB"
+ , "LZMA"
+ , "LZO"
+ , "XZ"
};
static const UInt32 kMetadataBlockSizeLog = 13;
@@ -315,17 +313,17 @@ UInt32 CNode::Parse1(const Byte *p, UInt32 size, const CHeader &_h)
UInt16 t = Get16(p);
if (be)
{
- Type = t >> 12;
- Mode = t & 0xFFF;
- Uid = p[2] >> 4;
- Gid = p[2] & 0xF;
+ Type = (UInt16)(t >> 12);
+ Mode = (UInt16)(t & 0xFFF);
+ Uid = (UInt16)(p[2] >> 4);
+ Gid = (UInt16)(p[2] & 0xF);
}
else
{
- Type = t & 0xF;
- Mode = t >> 4;
- Uid = p[2] & 0xF;
- Gid = p[2] >> 4;
+ Type = (UInt16)(t & 0xF);
+ Mode = (UInt16)(t >> 4);
+ Uid = (UInt16)(p[2] & 0xF);
+ Gid = (UInt16)(p[2] >> 4);
}
// Xattr = kXattr_Empty;
@@ -339,20 +337,20 @@ UInt32 CNode::Parse1(const Byte *p, UInt32 size, const CHeader &_h)
Byte t = p[3];
if (be)
{
- Type = t >> 4;
- Offset = t & 0xF;
+ Type = (UInt16)(t >> 4);
+ Offset = (UInt16)(t & 0xF);
}
else
{
- Type = t & 0xF;
- Offset = t >> 4;
+ Type = (UInt16)(t & 0xF);
+ Offset = (UInt16)(t >> 4);
}
return (Type == kType_FIFO || Type == kType_SOCK) ? 4 : 0;
}
Type--;
- Uid += (Type / 5) * 16;
- Type = (Type % 5) + 1;
+ Uid = (UInt16)(Uid + (Type / 5) * 16);
+ Type = (UInt16)((Type % 5) + 1);
if (Type == kType_FILE)
{
@@ -418,13 +416,13 @@ UInt32 CNode::Parse2(const Byte *p, UInt32 size, const CHeader &_h)
UInt16 t = Get16(p);
if (be)
{
- Type = t >> 12;
- Mode = t & 0xFFF;
+ Type = (UInt16)(t >> 12);
+ Mode = (UInt16)(t & 0xFFF);
}
else
{
- Type = t & 0xF;
- Mode = t >> 4;
+ Type = (UInt16)(t & 0xF);
+ Mode = (UInt16)(t >> 4);
}
Uid = p[2];
Gid = p[3];
@@ -548,13 +546,13 @@ UInt32 CNode::Parse3(const Byte *p, UInt32 size, const CHeader &_h)
UInt16 t = Get16(p);
if (be)
{
- Type = t >> 12;
- Mode = t & 0xFFF;
+ Type = (UInt16)(t >> 12);
+ Mode = (UInt16)(t & 0xFFF);
}
else
{
- Type = t & 0xF;
- Mode = t >> 4;
+ Type = (UInt16)(t & 0xF);
+ Mode = (UInt16)(t >> 4);
}
Uid = p[2];
Gid = p[3];
@@ -841,6 +839,8 @@ class CHandler:
// CByteBuffer _uids;
// CByteBuffer _gids;
CHeader _h;
+ bool _noPropsLZMA;
+ bool _needCheckLzma;
CMyComPtr<IInStream> _stream;
UInt64 _sizeCalculated;
@@ -922,31 +922,30 @@ CHandler::CHandler()
_dynOutStream = _dynOutStreamSpec;
}
-static const STATPROPSTG kProps[] =
+static const Byte 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}
- // { NULL, kpidUser, VT_BSTR},
- // { NULL, kpidGroup, VT_BSTR},
- // { NULL, kpidLinks, VT_UI4},
- // { NULL, kpidOffset, VT_UI4}
+ kpidPath,
+ kpidIsDir,
+ kpidSize,
+ kpidPackSize,
+ kpidMTime,
+ kpidPosixAttrib
+ // kpidUser,
+ // kpidGroup,
+ // kpidLinks,
+ // kpidOffset
};
-static const STATPROPSTG kArcProps[] =
+static const Byte kArcProps[] =
{
- { NULL, kpidFileSystem, VT_BSTR},
- { NULL, kpidMethod, VT_BSTR},
- { NULL, kpidBlock, VT_UI4},
- { NULL, kpidPhySize, VT_UI8},
- { NULL, kpidHeadersSize, VT_UI8},
- { NULL, kpidBigEndian, VT_BOOL},
- { NULL, kpidCTime, VT_FILETIME},
- { NULL, kpidCharacts, VT_BSTR}
- // { NULL, kpidNumBlocks, VT_UI4}
+ kpidHeadersSize,
+ kpidFileSystem,
+ kpidMethod,
+ kpidBlock,
+ kpidBigEndian,
+ kpidCTime,
+ kpidCharacts
+ // kpidNumBlocks
};
IMP_IInArchive_Props
@@ -1115,12 +1114,25 @@ HRESULT CHandler::Decompress(ISequentialOutStream *outStream, Byte *outBuf, bool
UInt32 method = _h.Method;
if (_h.SeveralMethods)
{
- Byte props[1];
- RINOK(ReadStream_FALSE(_stream, props, 1));
- method = (props[0] == 0x5D ? kMethod_LZMA : kMethod_ZLIB);
+ Byte b;
+ RINOK(ReadStream_FALSE(_stream, &b, 1));
RINOK(_stream->Seek(-1, STREAM_SEEK_CUR, NULL));
+ method = (b == 0x5D ? kMethod_LZMA : kMethod_ZLIB);
}
+ if (method == kMethod_ZLIB && _needCheckLzma)
+ {
+ Byte b;
+ RINOK(ReadStream_FALSE(_stream, &b, 1));
+ RINOK(_stream->Seek(-1, STREAM_SEEK_CUR, NULL));
+ if (b == 0)
+ {
+ _noPropsLZMA = true;
+ method = _h.Method = kMethod_LZMA;
+ }
+ _needCheckLzma = false;
+ }
+
if (method == kMethod_ZLIB)
{
if (!_zlibDecoder)
@@ -1140,24 +1152,34 @@ HRESULT CHandler::Decompress(ISequentialOutStream *outStream, Byte *outBuf, bool
_lzmaDecoderSpec->FinishStream = true;
_lzmaDecoder = _lzmaDecoderSpec;
}
- const UInt32 kPropsSize = 5 + 8;
+ const UInt32 kPropsSize = LZMA_PROPS_SIZE + 8;
Byte props[kPropsSize];
- ReadStream_FALSE(_limitedInStream, props, kPropsSize);
- RINOK(_lzmaDecoderSpec->SetDecoderProperties2(props, 5));
- UInt64 outSize = GetUi64(props + 5);
- if (outSize > outSizeMax)
- return S_FALSE;
+ UInt32 propsSize;
+ UInt64 outSize;
+ if (_noPropsLZMA)
+ {
+ props[0] = 0x5D;
+ SetUi32(&props[1], _h.BlockSize);
+ propsSize = 0;
+ outSize = outSizeMax;
+ }
+ else
+ {
+ RINOK(ReadStream_FALSE(_limitedInStream, props, kPropsSize));
+ propsSize = kPropsSize;
+ outSize = GetUi64(&props[LZMA_PROPS_SIZE]);
+ if (outSize > outSizeMax)
+ return S_FALSE;
+ }
+ RINOK(_lzmaDecoderSpec->SetDecoderProperties2(props, LZMA_PROPS_SIZE));
RINOK(_lzmaDecoder->Code(_limitedInStream, outStream, NULL, &outSize, NULL));
- if (inSize != kPropsSize + _lzmaDecoderSpec->GetInputProcessedSize())
+ if (inSize != propsSize + _lzmaDecoderSpec->GetInputProcessedSize())
return S_FALSE;
}
else
{
- if (_inputBuffer.GetCapacity() < inSize)
- {
- _inputBuffer.Free();
- _inputBuffer.SetCapacity(inSize);
- }
+ if (_inputBuffer.Size() < inSize)
+ _inputBuffer.Alloc(inSize);
RINOK(ReadStream_FALSE(_stream, _inputBuffer, inSize));
Byte *dest = outBuf;
@@ -1287,22 +1309,23 @@ HRESULT CHandler::OpenDir(int parent, UInt32 startBlock, UInt32 offset, unsigned
if (blockIndex < 0)
return S_FALSE;
unpackPos = _dirs.UnpackPos[blockIndex] + n.Offset;
- if (unpackPos < n.Offset || unpackPos > _dirs.Data.GetCapacity())
+ if (unpackPos < n.Offset || unpackPos > _dirs.Data.Size())
return S_FALSE;
- UInt32 rem = (UInt32)_dirs.Data.GetCapacity() - unpackPos;
+ UInt32 rem = (UInt32)_dirs.Data.Size() - unpackPos;
const Byte *p = _dirs.Data + unpackPos;
UInt32 fileSize = (UInt32)n.FileSize;
- if (fileSize > rem)
- return S_FALSE;
- rem = fileSize;
+ // for some squashfs files: fileSize = rem + 3 !!!
if (_h.Major >= 3)
{
- if (rem < 3)
+ if (fileSize < 3)
return S_FALSE;
- rem -= 3;
+ fileSize -= 3;
}
+ if (fileSize > rem)
+ return S_FALSE;
+ rem = fileSize;
CRecordVector<CTempItem> tempItems;
while (rem != 0)
@@ -1412,7 +1435,7 @@ HRESULT CHandler::OpenDir(int parent, UInt32 startBlock, UInt32 offset, unsigned
}
int startItemIndex = _items.Size() - tempItems.Size();
- for (int i = 0; i < tempItems.Size(); i++)
+ FOR_VECTOR (i, tempItems)
{
const CTempItem &tempItem = tempItems[i];
int index = startItemIndex + i;
@@ -1443,9 +1466,11 @@ HRESULT CHandler::Open2(IInStream *inStream)
if (!_h.IsSupported())
return E_NOTIMPL;
+ _noPropsLZMA = false;
+ _needCheckLzma = false;
switch (_h.Method)
{
- case kMethod_ZLIB:
+ case kMethod_ZLIB: _needCheckLzma = true; break;
case kMethod_LZMA:
case kMethod_LZO:
case kMethod_XZ:
@@ -1461,14 +1486,13 @@ HRESULT CHandler::Open2(IInStream *inStream)
{
if (_h.NumFrags > kNumFilesMax)
return S_FALSE;
- _frags.Reserve(_h.NumFrags);
- CByteBuffer data;
+ _frags.ClearAndReserve(_h.NumFrags);
unsigned bigFrag = (_h.Major > 2);
unsigned fragPtrsInBlockLog = kMetadataBlockSizeLog - (3 + bigFrag);
UInt32 numBlocks = (_h.NumFrags + (1 << fragPtrsInBlockLog) - 1) >> fragPtrsInBlockLog;
size_t numBlocksBytes = (size_t)numBlocks << (2 + bigFrag);
- data.SetCapacity(numBlocksBytes);
+ CByteBuffer data(numBlocksBytes);
RINOK(inStream->Seek(_h.FragTable, STREAM_SEEK_SET, NULL));
RINOK(ReadStream_FALSE(inStream, data, numBlocksBytes));
bool be = _h.be;
@@ -1518,11 +1542,11 @@ HRESULT CHandler::Open2(IInStream *inStream)
return S_FALSE;
{
UInt32 pos = 0;
- UInt32 totalSize = (UInt32)_inodesData.Data.GetCapacity();
- _nodesPos.Reserve(_h.NumInodes);
- _nodes.Reserve(_h.NumInodes);
+ UInt32 totalSize = (UInt32)_inodesData.Data.Size();
+ _nodesPos.ClearAndReserve(_h.NumInodes);
+ _nodes.ClearAndReserve(_h.NumInodes);
// we use _blockToNode for binary search seed optimizations
- _blockToNode.Reserve(_inodesData.GetNumBlocks() + 1);
+ _blockToNode.ClearAndReserve(_inodesData.GetNumBlocks() + 1);
int curBlock = 0;
for (UInt32 i = 0; i < _h.NumInodes; i++)
{
@@ -1544,8 +1568,8 @@ HRESULT CHandler::Open2(IInStream *inStream)
_blockToNode.Add(_nodesPos.Size());
curBlock++;
}
- _nodesPos.Add(pos);
- _nodes.Add(n);
+ _nodesPos.AddInReserved(pos);
+ _nodes.AddInReserved(n);
pos += size;
}
_blockToNode.Add(_nodesPos.Size());
@@ -1657,7 +1681,6 @@ STDMETHODIMP CHandler::Open(IInStream *stream, const UInt64 *, IArchiveOpenCallb
HRESULT res;
try
{
- RINOK(stream->Seek(0, STREAM_SEEK_SET, NULL));
_openCallback = callback;
res = Open2(stream);
}
@@ -1679,6 +1702,8 @@ STDMETHODIMP CHandler::Open(IInStream *stream, const UInt64 *, IArchiveOpenCallb
STDMETHODIMP CHandler::Close()
{
+ _sizeCalculated = 0;
+
_limitedInStreamSpec->ReleaseStream();
_stream.Release();
@@ -1801,12 +1826,14 @@ STDMETHODIMP CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value)
case kpidMethod:
{
const char *s;
- if (_h.SeveralMethods)
+ if (_noPropsLZMA)
+ s = "LZMA Spec";
+ else if (_h.SeveralMethods)
s = "LZMA ZLIB";
else
{
s = k_Methods[0];
- if (_h.Method < sizeof(k_Methods) / sizeof(k_Methods[0]))
+ if (_h.Method < ARRAY_SIZE(k_Methods))
s = k_Methods[_h.Method];
}
prop = s;
@@ -1906,7 +1933,7 @@ STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *val
}
case kpidPosixAttrib:
{
- if (node.Type != 0 && node.Type < sizeof(k_TypeToMode) / sizeof(k_TypeToMode[0]))
+ if (node.Type != 0 && node.Type < ARRAY_SIZE(k_TypeToMode))
prop = (UInt32)(node.Mode & 0xFFF) | k_TypeToMode[node.Type];
break;
}
@@ -1914,7 +1941,7 @@ STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *val
case kpidUser:
{
UInt32 offset = node.Uid * 4;
- if (offset < _uids.GetCapacity())
+ if (offset < _uids.Size())
prop = (UInt32)Get32(_uids + offset);
break;
}
@@ -1923,13 +1950,13 @@ STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *val
if (_h.Major == 4 || node.Gid == _h.GetSpecGuidIndex())
{
UInt32 offset = node.Uid * 4;
- if (offset < _uids.GetCapacity())
+ if (offset < _uids.Size())
prop = (UInt32)Get32(_uids + offset);
}
else
{
UInt32 offset = node.Gid * 4;
- if (offset < _gids.GetCapacity())
+ if (offset < _gids.Size())
prop = (UInt32)Get32(_gids + offset);
}
break;
@@ -2028,7 +2055,7 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems,
Int32 testMode, IArchiveExtractCallback *extractCallback)
{
COM_TRY_BEGIN
- bool allFilesMode = (numItems == (UInt32)-1);
+ bool allFilesMode = (numItems == (UInt32)(Int32)-1);
if (allFilesMode)
numItems = _items.Size();
if (numItems == 0)
@@ -2095,7 +2122,7 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems,
{
if (hres == E_OUTOFMEMORY)
return hres;
- res = NExtract::NOperationResult::kUnSupportedMethod;
+ res = NExtract::NOperationResult::kUnsupportedMethod;
}
else
{
@@ -2110,7 +2137,7 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems,
}
else if (hres == E_NOTIMPL)
{
- res = NExtract::NOperationResult::kUnSupportedMethod;
+ res = NExtract::NOperationResult::kUnsupportedMethod;
}
else if(hres != S_FALSE)
{
@@ -2157,10 +2184,10 @@ STDMETHODIMP CHandler::GetStream(UInt32 index, ISequentialInStream **stream)
_nodeIndex = item.Node;
size_t cacheSize = _h.BlockSize;
- if (_cachedBlock.GetCapacity() != cacheSize)
+ if (_cachedBlock.Size() != cacheSize)
{
ClearCache();
- _cachedBlock.SetCapacity(cacheSize);
+ _cachedBlock.Alloc(cacheSize);
}
CSquashfsInStream *streamSpec = new CSquashfsInStream;
@@ -2179,10 +2206,19 @@ STDMETHODIMP CHandler::GetStream(UInt32 index, ISequentialInStream **stream)
COM_TRY_END
}
-static IInArchive *CreateArc() { return new NArchive::NSquashfs::CHandler; }
+IMP_CreateArcIn
static CArcInfo g_ArcInfo =
- { L"SquashFS", L"squashfs", 0, 0xD2, SIGNATURE, kSignatureSize, false, CreateArc, 0 };
+ { "SquashFS", "squashfs", 0, 0xD2,
+ 3 * (1 + 4),
+ {
+ 4, 'h', 's', 'q', 's',
+ 4, 's', 'q', 's', 'h',
+ 4, 's', 'h', 's', 'q',
+ },
+ 0,
+ NArcInfoFlags::kMultiSignature,
+ CreateArc };
REGISTER_ARC(Cramfs)