summaryrefslogtreecommitdiffstats
path: root/src/libs/7zip/unix/CPP/7zip/Archive/CramfsHandler.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/libs/7zip/unix/CPP/7zip/Archive/CramfsHandler.cpp')
-rw-r--r--src/libs/7zip/unix/CPP/7zip/Archive/CramfsHandler.cpp644
1 files changed, 0 insertions, 644 deletions
diff --git a/src/libs/7zip/unix/CPP/7zip/Archive/CramfsHandler.cpp b/src/libs/7zip/unix/CPP/7zip/Archive/CramfsHandler.cpp
deleted file mode 100644
index a55e3743d..000000000
--- a/src/libs/7zip/unix/CPP/7zip/Archive/CramfsHandler.cpp
+++ /dev/null
@@ -1,644 +0,0 @@
-// 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)
-
-}}