This commit is contained in:
Igor Pavlov
2014-11-23 00:00:00 +00:00
committed by Kornel Lesiński
parent 83f8ddcc5b
commit f08f4dcc3c
1158 changed files with 76451 additions and 35082 deletions

242
CPP/7zip/Archive/SquashfsHandler.cpp Executable file → Normal file
View File

@@ -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;
// for some squashfs files: fileSize = rem + 3 !!!
if (_h.Major >= 3)
{
if (fileSize < 3)
return S_FALSE;
fileSize -= 3;
}
if (fileSize > rem)
return S_FALSE;
rem = fileSize;
if (_h.Major >= 3)
{
if (rem < 3)
return S_FALSE;
rem -= 3;
}
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)