mirror of
https://github.com/Xevion/easy7zip.git
synced 2025-12-12 05:09:59 -06:00
9.34
This commit is contained in:
committed by
Kornel Lesiński
parent
83f8ddcc5b
commit
f08f4dcc3c
242
CPP/7zip/Archive/SquashfsHandler.cpp
Executable file → Normal file
242
CPP/7zip/Archive/SquashfsHandler.cpp
Executable file → Normal 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)
|
||||
|
||||
|
||||
Reference in New Issue
Block a user