mirror of
https://github.com/Xevion/easy7zip.git
synced 2025-12-13 12:11:38 -06:00
22.00
This commit is contained in:
155
CPP/7zip/Archive/SquashfsHandler.cpp
Normal file → Executable file
155
CPP/7zip/Archive/SquashfsHandler.cpp
Normal file → Executable file
@@ -76,7 +76,7 @@ static const char * const k_Methods[] =
|
||||
, "XZ"
|
||||
};
|
||||
|
||||
static const UInt32 kMetadataBlockSizeLog = 13;
|
||||
static const unsigned kMetadataBlockSizeLog = 13;
|
||||
static const UInt32 kMetadataBlockSize = (1 << kMetadataBlockSizeLog);
|
||||
|
||||
enum
|
||||
@@ -408,7 +408,7 @@ UInt32 CNode::Parse1(const Byte *p, UInt32 size, const CHeader &_h)
|
||||
|
||||
UInt32 CNode::Parse2(const Byte *p, UInt32 size, const CHeader &_h)
|
||||
{
|
||||
bool be = _h.be;
|
||||
const bool be = _h.be;
|
||||
if (size < 4)
|
||||
return 0;
|
||||
{
|
||||
@@ -541,7 +541,7 @@ UInt32 CNode::Parse2(const Byte *p, UInt32 size, const CHeader &_h)
|
||||
|
||||
UInt32 CNode::Parse3(const Byte *p, UInt32 size, const CHeader &_h)
|
||||
{
|
||||
bool be = _h.be;
|
||||
const bool be = _h.be;
|
||||
if (size < 12)
|
||||
return 0;
|
||||
|
||||
@@ -843,8 +843,8 @@ class CHandler:
|
||||
CData _inodesData;
|
||||
CData _dirs;
|
||||
CRecordVector<CFrag> _frags;
|
||||
// CByteBuffer _uids;
|
||||
// CByteBuffer _gids;
|
||||
CByteBuffer _uids;
|
||||
CByteBuffer _gids;
|
||||
CHeader _h;
|
||||
bool _noPropsLZMA;
|
||||
bool _needCheckLzma;
|
||||
@@ -891,14 +891,20 @@ class CHandler:
|
||||
_cachedUnpackBlockSize = 0;
|
||||
}
|
||||
|
||||
HRESULT Seek2(UInt64 offset)
|
||||
{
|
||||
return _stream->Seek(offset, STREAM_SEEK_SET, NULL);
|
||||
}
|
||||
|
||||
HRESULT Decompress(ISequentialOutStream *outStream, Byte *outBuf, bool *outBufWasWritten, UInt32 *outBufWasWrittenSize,
|
||||
UInt32 inSize, UInt32 outSizeMax);
|
||||
HRESULT ReadMetadataBlock(UInt32 &packSize);
|
||||
HRESULT ReadMetadataBlock2();
|
||||
HRESULT ReadData(CData &data, UInt64 start, UInt64 end);
|
||||
|
||||
HRESULT OpenDir(int parent, UInt32 startBlock, UInt32 offset, unsigned level, int &nodeIndex);
|
||||
HRESULT ScanInodes(UInt64 ptr);
|
||||
// HRESULT ReadUids(UInt64 start, UInt32 num, CByteBuffer &ids);
|
||||
HRESULT ReadUids(UInt64 start, UInt32 num, CByteBuffer &ids);
|
||||
HRESULT Open2(IInStream *inStream);
|
||||
AString GetPath(int index) const;
|
||||
bool GetPackSize(int index, UInt64 &res, bool fillOffsets);
|
||||
@@ -938,9 +944,9 @@ static const Byte kProps[] =
|
||||
kpidSize,
|
||||
kpidPackSize,
|
||||
kpidMTime,
|
||||
kpidPosixAttrib
|
||||
// kpidUser,
|
||||
// kpidGroup,
|
||||
kpidPosixAttrib,
|
||||
kpidUserId,
|
||||
kpidGroupId
|
||||
// kpidLinks,
|
||||
// kpidOffset
|
||||
};
|
||||
@@ -1280,14 +1286,14 @@ HRESULT CHandler::Decompress(ISequentialOutStream *outStream, Byte *outBuf, bool
|
||||
HRESULT CHandler::ReadMetadataBlock(UInt32 &packSize)
|
||||
{
|
||||
Byte temp[3];
|
||||
unsigned offset = _h.NeedCheckData() ? 3 : 2;
|
||||
const unsigned offset = _h.NeedCheckData() ? 3 : 2;
|
||||
if (offset > packSize)
|
||||
return S_FALSE;
|
||||
RINOK(ReadStream_FALSE(_stream, temp, offset));
|
||||
// if (NeedCheckData && Major < 4) checkByte must be = 0xFF
|
||||
bool be = _h.be;
|
||||
const bool be = _h.be;
|
||||
UInt32 size = Get16(temp);
|
||||
bool isCompressed = ((size & kNotCompressedBit16) == 0);
|
||||
const bool isCompressed = ((size & kNotCompressedBit16) == 0);
|
||||
if (size != kNotCompressedBit16)
|
||||
size &= ~kNotCompressedBit16;
|
||||
|
||||
@@ -1311,12 +1317,20 @@ HRESULT CHandler::ReadMetadataBlock(UInt32 &packSize)
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
|
||||
HRESULT CHandler::ReadMetadataBlock2()
|
||||
{
|
||||
_dynOutStreamSpec->Init();
|
||||
UInt32 packSize = kMetadataBlockSize + 3; // check it
|
||||
return ReadMetadataBlock(packSize);
|
||||
}
|
||||
|
||||
HRESULT CHandler::ReadData(CData &data, UInt64 start, UInt64 end)
|
||||
{
|
||||
if (end < start || end - start >= ((UInt64)1 << 32))
|
||||
return S_FALSE;
|
||||
const UInt32 size = (UInt32)(end - start);
|
||||
RINOK(_stream->Seek(start, STREAM_SEEK_SET, NULL));
|
||||
RINOK(Seek2(start));
|
||||
_dynOutStreamSpec->Init();
|
||||
UInt32 packPos = 0;
|
||||
while (packPos != size)
|
||||
@@ -1395,7 +1409,7 @@ HRESULT CHandler::OpenDir(int parent, UInt32 startBlock, UInt32 offset, unsigned
|
||||
CRecordVector<CTempItem> tempItems;
|
||||
while (rem != 0)
|
||||
{
|
||||
bool be = _h.be;
|
||||
const bool be = _h.be;
|
||||
UInt32 count;
|
||||
CTempItem tempItem;
|
||||
if (_h.Major <= 2)
|
||||
@@ -1519,15 +1533,15 @@ HRESULT CHandler::OpenDir(int parent, UInt32 startBlock, UInt32 offset, unsigned
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
/*
|
||||
HRESULT CHandler::ReadUids(UInt64 start, UInt32 num, CByteBuffer &ids)
|
||||
{
|
||||
size_t size = num * 4;
|
||||
ids.SetCapacity(size);
|
||||
RINOK(_stream->Seek(start, STREAM_SEEK_SET, NULL));
|
||||
const size_t size = (size_t)num * 4;
|
||||
ids.Alloc(size);
|
||||
if (num == 0)
|
||||
return S_OK;
|
||||
RINOK(Seek2(start));
|
||||
return ReadStream_FALSE(_stream, ids, size);
|
||||
}
|
||||
*/
|
||||
|
||||
HRESULT CHandler::Open2(IInStream *inStream)
|
||||
{
|
||||
@@ -1560,24 +1574,22 @@ HRESULT CHandler::Open2(IInStream *inStream)
|
||||
if (_h.NumFrags > kNumFilesMax)
|
||||
return S_FALSE;
|
||||
_frags.ClearAndReserve(_h.NumFrags);
|
||||
unsigned bigFrag = (_h.Major > 2);
|
||||
const 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);
|
||||
const unsigned fragPtrsInBlockLog = kMetadataBlockSizeLog - (3 + bigFrag);
|
||||
const UInt32 numBlocks = (_h.NumFrags + (1 << fragPtrsInBlockLog) - 1) >> fragPtrsInBlockLog;
|
||||
const size_t numBlocksBytes = (size_t)numBlocks << (2 + bigFrag);
|
||||
CByteBuffer data(numBlocksBytes);
|
||||
RINOK(inStream->Seek(_h.FragTable, STREAM_SEEK_SET, NULL));
|
||||
RINOK(Seek2(_h.FragTable));
|
||||
RINOK(ReadStream_FALSE(inStream, data, numBlocksBytes));
|
||||
bool be = _h.be;
|
||||
const bool be = _h.be;
|
||||
|
||||
for (UInt32 i = 0; i < numBlocks; i++)
|
||||
{
|
||||
UInt64 offset = bigFrag ? Get64(data + i * 8) : Get32(data + i * 4);
|
||||
RINOK(_stream->Seek(offset, STREAM_SEEK_SET, NULL));
|
||||
_dynOutStreamSpec->Init();
|
||||
UInt32 packSize = kMetadataBlockSize + 3;
|
||||
RINOK(ReadMetadataBlock(packSize));
|
||||
UInt32 unpackSize = (UInt32)_dynOutStreamSpec->GetSize();
|
||||
const UInt64 offset = bigFrag ? Get64(data + i * 8) : Get32(data + i * 4);
|
||||
RINOK(Seek2(offset));
|
||||
RINOK(ReadMetadataBlock2());
|
||||
const UInt32 unpackSize = (UInt32)_dynOutStreamSpec->GetSize();
|
||||
if (unpackSize != kMetadataBlockSize)
|
||||
if (i != numBlocks - 1 || unpackSize != ((_h.NumFrags << (3 + bigFrag)) & (kMetadataBlockSize - 1)))
|
||||
return S_FALSE;
|
||||
@@ -1605,8 +1617,6 @@ HRESULT CHandler::Open2(IInStream *inStream)
|
||||
return S_FALSE;
|
||||
}
|
||||
|
||||
// RINOK(inStream->Seek(_h.InodeTable, STREAM_SEEK_SET, NULL));
|
||||
|
||||
RINOK(ReadData(_inodesData, _h.InodeTable, _h.DirTable));
|
||||
RINOK(ReadData(_dirs, _h.DirTable, _h.FragTable));
|
||||
|
||||
@@ -1655,7 +1665,6 @@ HRESULT CHandler::Open2(IInStream *inStream)
|
||||
int rootNodeIndex;
|
||||
RINOK(OpenDir(-1, (UInt32)absOffset, (UInt32)_h.RootInode & 0xFFFF, 0, rootNodeIndex));
|
||||
|
||||
/*
|
||||
if (_h.Major < 4)
|
||||
{
|
||||
RINOK(ReadUids(_h.UidTable, _h.NumUids, _uids));
|
||||
@@ -1663,33 +1672,34 @@ HRESULT CHandler::Open2(IInStream *inStream)
|
||||
}
|
||||
else
|
||||
{
|
||||
UInt32 size = _h.NumIDs * 4;
|
||||
_uids.SetCapacity(size);
|
||||
const UInt32 size = (UInt32)_h.NumIDs * 4;
|
||||
_uids.Alloc(size);
|
||||
|
||||
UInt32 numBlocks = (size + kMetadataBlockSize - 1) / kMetadataBlockSize;
|
||||
UInt32 numBlocksBytes = numBlocks << 3;
|
||||
const UInt32 numBlocks = (size + kMetadataBlockSize - 1) / kMetadataBlockSize;
|
||||
const UInt32 numBlocksBytes = numBlocks << 3;
|
||||
CByteBuffer data;
|
||||
data.SetCapacity(numBlocksBytes);
|
||||
RINOK(inStream->Seek(_h.UidTable, STREAM_SEEK_SET, NULL));
|
||||
data.Alloc(numBlocksBytes);
|
||||
RINOK(Seek2(_h.UidTable));
|
||||
RINOK(ReadStream_FALSE(inStream, data, numBlocksBytes));
|
||||
|
||||
for (UInt32 i = 0; i < numBlocks; i++)
|
||||
{
|
||||
UInt64 offset = GetUi64(data + i * 8);
|
||||
UInt32 unpackSize, packSize;
|
||||
RINOK(_stream->Seek(offset, STREAM_SEEK_SET, NULL));
|
||||
RINOK(ReadMetadataBlock(NULL, _uids + kMetadataBlockSize * i, packSize, unpackSize));
|
||||
const UInt64 offset = GetUi64(data + i * 8);
|
||||
RINOK(Seek2(offset));
|
||||
// RINOK(ReadMetadataBlock(NULL, _uids + kMetadataBlockSize * i, packSize, unpackSize));
|
||||
RINOK(ReadMetadataBlock2());
|
||||
const size_t unpackSize = _dynOutStreamSpec->GetSize();
|
||||
if (unpackSize != kMetadataBlockSize)
|
||||
if (i != numBlocks - 1 || unpackSize != (size & (kMetadataBlockSize - 1)))
|
||||
return S_FALSE;
|
||||
memcpy(_uids + kMetadataBlockSize * i, _dynOutStreamSpec->GetBuffer(), unpackSize);
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
||||
{
|
||||
const UInt32 alignSize = 1 << 12;
|
||||
Byte buf[alignSize];
|
||||
RINOK(inStream->Seek(_h.Size, STREAM_SEEK_SET, NULL));
|
||||
RINOK(Seek2(_h.Size));
|
||||
UInt32 rem = (UInt32)(0 - _h.Size) & (alignSize - 1);
|
||||
_sizeCalculated = _h.Size;
|
||||
if (rem != 0)
|
||||
@@ -1710,7 +1720,7 @@ AString CHandler::GetPath(int index) const
|
||||
{
|
||||
unsigned len = 0;
|
||||
int indexMem = index;
|
||||
bool be = _h.be;
|
||||
const bool be = _h.be;
|
||||
do
|
||||
{
|
||||
const CItem &item = _items[index];
|
||||
@@ -1804,9 +1814,9 @@ bool CHandler::GetPackSize(int index, UInt64 &totalPack, bool fillOffsets)
|
||||
totalPack = 0;
|
||||
const CItem &item = _items[index];
|
||||
const CNode &node = _nodes[item.Node];
|
||||
UInt32 ptr = _nodesPos[item.Node];
|
||||
const UInt32 ptr = _nodesPos[item.Node];
|
||||
const Byte *p = _inodesData.Data + ptr;
|
||||
bool be = _h.be;
|
||||
const bool be = _h.be;
|
||||
|
||||
UInt32 type = node.Type;
|
||||
UInt32 offset;
|
||||
@@ -1936,11 +1946,7 @@ STDMETHODIMP CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value)
|
||||
case kpidBigEndian: prop = _h.be; break;
|
||||
case kpidCTime:
|
||||
if (_h.CTime != 0)
|
||||
{
|
||||
FILETIME ft;
|
||||
NWindows::NTime::UnixTimeToFileTime(_h.CTime, ft);
|
||||
prop = ft;
|
||||
}
|
||||
PropVariant_SetFrom_UnixTime(prop, _h.CTime);
|
||||
break;
|
||||
case kpidCharacts: FLAGS_TO_PROP(k_Flags, _h.Flags, prop); break;
|
||||
// case kpidNumBlocks: prop = _h.NumFrags; break;
|
||||
@@ -1979,8 +1985,8 @@ STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *val
|
||||
NWindows::NCOM::CPropVariant prop;
|
||||
const CItem &item = _items[index];
|
||||
const CNode &node = _nodes[item.Node];
|
||||
bool isDir = node.IsDir();
|
||||
bool be = _h.be;
|
||||
const bool isDir = node.IsDir();
|
||||
const bool be = _h.be;
|
||||
|
||||
switch (propID)
|
||||
{
|
||||
@@ -2031,9 +2037,7 @@ STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *val
|
||||
if (offset != 0)
|
||||
{
|
||||
const Byte *p = _inodesData.Data + _nodesPos[item.Node] + offset;
|
||||
FILETIME ft;
|
||||
NWindows::NTime::UnixTimeToFileTime(Get32(p), ft);
|
||||
prop = ft;
|
||||
PropVariant_SetFrom_UnixTime(prop, Get32(p));
|
||||
}
|
||||
break;
|
||||
}
|
||||
@@ -2043,31 +2047,38 @@ STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *val
|
||||
prop = (UInt32)(node.Mode & 0xFFF) | k_TypeToMode[node.Type];
|
||||
break;
|
||||
}
|
||||
/*
|
||||
case kpidUser:
|
||||
case kpidUserId:
|
||||
{
|
||||
UInt32 offset = node.Uid * 4;
|
||||
const UInt32 offset = (UInt32)node.Uid * 4;
|
||||
if (offset < _uids.Size())
|
||||
prop = (UInt32)Get32(_uids + offset);
|
||||
break;
|
||||
}
|
||||
case kpidGroup:
|
||||
case kpidGroupId:
|
||||
{
|
||||
if (_h.Major == 4 || node.Gid == _h.GetSpecGuidIndex())
|
||||
if (_h.Major < 4)
|
||||
{
|
||||
UInt32 offset = node.Uid * 4;
|
||||
if (offset < _uids.Size())
|
||||
prop = (UInt32)Get32(_uids + offset);
|
||||
if (node.Gid == _h.GetSpecGuidIndex())
|
||||
{
|
||||
const UInt32 offset = (UInt32)node.Uid * 4;
|
||||
if (offset < _uids.Size())
|
||||
prop = (UInt32)Get32(_uids + offset);
|
||||
}
|
||||
else
|
||||
{
|
||||
const UInt32 offset = (UInt32)node.Gid * 4;
|
||||
if (offset < _gids.Size())
|
||||
prop = (UInt32)Get32(_gids + offset);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
UInt32 offset = node.Gid * 4;
|
||||
if (offset < _gids.Size())
|
||||
prop = (UInt32)Get32(_gids + offset);
|
||||
const UInt32 offset = (UInt32)node.Gid * 4;
|
||||
if (offset < _uids.Size())
|
||||
prop = (UInt32)Get32(_uids + offset);
|
||||
}
|
||||
break;
|
||||
}
|
||||
*/
|
||||
/*
|
||||
case kpidLinks:
|
||||
if (_h.Major >= 3 && node.Type != kType_FILE)
|
||||
@@ -2128,7 +2139,7 @@ HRESULT CHandler::ReadBlock(UInt64 blockIndex, Byte *dest, size_t blockSize)
|
||||
packBlockSize != _cachedPackBlockSize)
|
||||
{
|
||||
ClearCache();
|
||||
RINOK(_stream->Seek(blockOffset, STREAM_SEEK_SET, NULL));
|
||||
RINOK(Seek2(blockOffset));
|
||||
_limitedInStreamSpec->Init(packBlockSize);
|
||||
|
||||
if (compressed)
|
||||
|
||||
Reference in New Issue
Block a user