diff options
Diffstat (limited to 'src/libs/7zip/win/CPP/7zip/Archive/CpioHandler.cpp')
-rw-r--r-- | src/libs/7zip/win/CPP/7zip/Archive/CpioHandler.cpp | 624 |
1 files changed, 0 insertions, 624 deletions
diff --git a/src/libs/7zip/win/CPP/7zip/Archive/CpioHandler.cpp b/src/libs/7zip/win/CPP/7zip/Archive/CpioHandler.cpp deleted file mode 100644 index 0f32ef663..000000000 --- a/src/libs/7zip/win/CPP/7zip/Archive/CpioHandler.cpp +++ /dev/null @@ -1,624 +0,0 @@ -// CpioHandler.cpp - -#include "StdAfx.h" - -#include "Common/ComTry.h" -#include "Common/StringConvert.h" -#include "Common/StringToInt.h" - -#include "Windows/PropVariant.h" -#include "Windows/Time.h" - -#include "../Common/LimitedStreams.h" -#include "../Common/ProgressUtils.h" -#include "../Common/RegisterArc.h" -#include "../Common/StreamUtils.h" - -#include "../Compress/CopyCoder.h" - -#include "Common/ItemNameUtils.h" - -namespace NArchive { -namespace NCpio { - -namespace NFileHeader -{ - namespace NMagic - { - const char *kMagic1 = "070701"; - const char *kMagic2 = "070702"; - const char *kMagic3 = "070707"; - const char *kEndName = "TRAILER!!!"; - - const Byte kMagicForRecord2[2] = { 0xC7, 0x71 }; - } - - const UInt32 kRecord2Size = 26; - /* - struct CRecord2 - { - unsigned short c_magic; - short c_dev; - unsigned short c_ino; - unsigned short c_mode; - unsigned short c_uid; - unsigned short c_gid; - unsigned short c_nlink; - short c_rdev; - unsigned short c_mtimes[2]; - unsigned short c_namesize; - unsigned short c_filesizes[2]; - }; - */ - - const UInt32 kRecordSize = 110; - /* - struct CRecord - { - char Magic[6]; // "070701" for "new" portable format, "070702" for CRC format - char inode[8]; - char Mode[8]; - char UID[8]; - char GID[8]; - char nlink[8]; - char mtime[8]; - char Size[8]; // must be 0 for FIFOs and directories - char DevMajor[8]; - char DevMinor[8]; - char RDevMajor[8]; //only valid for chr and blk special files - char RDevMinor[8]; //only valid for chr and blk special files - char NameSize[8]; // count includes terminating NUL in pathname - char ChkSum[8]; // 0 for "new" portable format; for CRC format the sum of all the bytes in the file - bool CheckMagic() const - { return memcmp(Magic, NMagic::kMagic1, 6) == 0 || - memcmp(Magic, NMagic::kMagic2, 6) == 0; }; - }; - */ - - const UInt32 kOctRecordSize = 76; - -} - -struct CItem -{ - AString Name; - UInt32 inode; - UInt32 Mode; - UInt32 UID; - UInt32 GID; - UInt32 Size; - UInt32 MTime; - - // char LinkFlag; - // AString LinkName; ????? - char Magic[8]; - UInt32 NumLinks; - UInt32 DevMajor; - UInt32 DevMinor; - UInt32 RDevMajor; - UInt32 RDevMinor; - UInt32 ChkSum; - - UInt32 Align; - - bool IsDir() const { return (Mode & 0170000) == 0040000; } -}; - -class CItemEx: public CItem -{ -public: - UInt64 HeaderPosition; - UInt32 HeaderSize; - UInt64 GetDataPosition() const { return HeaderPosition + HeaderSize; }; -}; - -const UInt32 kMaxBlockSize = NFileHeader::kRecordSize; - -class CInArchive -{ - CMyComPtr<IInStream> m_Stream; - UInt64 m_Position; - - UInt16 _blockSize; - Byte _block[kMaxBlockSize]; - UInt32 _blockPos; - Byte ReadByte(); - UInt16 ReadUInt16(); - UInt32 ReadUInt32(); - - bool ReadNumber(UInt32 &resultValue); - bool ReadOctNumber(int size, UInt32 &resultValue); - - HRESULT ReadBytes(void *data, UInt32 size, UInt32 &processedSize); -public: - HRESULT Open(IInStream *inStream); - HRESULT GetNextItem(bool &filled, CItemEx &itemInfo); - HRESULT Skip(UInt64 numBytes); - HRESULT SkipDataRecords(UInt64 dataSize, UInt32 align); -}; - -HRESULT CInArchive::ReadBytes(void *data, UInt32 size, UInt32 &processedSize) -{ - size_t realProcessedSize = size; - RINOK(ReadStream(m_Stream, data, &realProcessedSize)); - processedSize = (UInt32)realProcessedSize; - m_Position += processedSize; - return S_OK; -} - -Byte CInArchive::ReadByte() -{ - if (_blockPos >= _blockSize) - throw "Incorrect cpio archive"; - return _block[_blockPos++]; -} - -UInt16 CInArchive::ReadUInt16() -{ - UInt16 value = 0; - for (int i = 0; i < 2; i++) - { - Byte b = ReadByte(); - value |= (UInt16(b) << (8 * i)); - } - return value; -} - -UInt32 CInArchive::ReadUInt32() -{ - UInt32 value = 0; - for (int i = 0; i < 4; i++) - { - Byte b = ReadByte(); - value |= (UInt32(b) << (8 * i)); - } - return value; -} - -HRESULT CInArchive::Open(IInStream *inStream) -{ - RINOK(inStream->Seek(0, STREAM_SEEK_CUR, &m_Position)); - m_Stream = inStream; - return S_OK; -} - -bool CInArchive::ReadNumber(UInt32 &resultValue) -{ - resultValue = 0; - for (int i = 0; i < 8; i++) - { - char c = char(ReadByte()); - int d; - if (c >= '0' && c <= '9') - d = c - '0'; - else if (c >= 'A' && c <= 'F') - d = 10 + c - 'A'; - else if (c >= 'a' && c <= 'f') - d = 10 + c - 'a'; - else - return false; - resultValue *= 0x10; - resultValue += d; - } - return true; -} - -static bool OctalToNumber(const char *s, UInt64 &res) -{ - const char *end; - res = ConvertOctStringToUInt64(s, &end); - return (*end == ' ' || *end == 0); -} - -static bool OctalToNumber32(const char *s, UInt32 &res) -{ - UInt64 res64; - if (!OctalToNumber(s, res64)) - return false; - res = (UInt32)res64; - return (res64 <= 0xFFFFFFFF); -} - -bool CInArchive::ReadOctNumber(int size, UInt32 &resultValue) -{ - char sz[32 + 4]; - int i; - for (i = 0; i < size && i < 32; i++) - sz[i] = (char)ReadByte(); - sz[i] = 0; - return OctalToNumber32(sz, resultValue); -} - -#define GetFromHex(y) { if (!ReadNumber(y)) return S_FALSE; } -#define GetFromOct6(y) { if (!ReadOctNumber(6, y)) return S_FALSE; } -#define GetFromOct11(y) { if (!ReadOctNumber(11, y)) return S_FALSE; } - -static unsigned short ConvertValue(unsigned short value, bool convert) -{ - if (!convert) - return value; - return (unsigned short)((((unsigned short)(value & 0xFF)) << 8) | (value >> 8)); -} - -static UInt32 GetAlignedSize(UInt32 size, UInt32 align) -{ - while ((size & (align - 1)) != 0) - size++; - return size; -} - - -HRESULT CInArchive::GetNextItem(bool &filled, CItemEx &item) -{ - filled = false; - - UInt32 processedSize; - item.HeaderPosition = m_Position; - - _blockSize = kMaxBlockSize; - RINOK(ReadBytes(_block, 2, processedSize)); - if (processedSize != 2) - return S_FALSE; - _blockPos = 0; - - UInt32 nameSize; - - bool oldBE = - _block[0] == NFileHeader::NMagic::kMagicForRecord2[1] && - _block[1] == NFileHeader::NMagic::kMagicForRecord2[0]; - - bool binMode = (_block[0] == NFileHeader::NMagic::kMagicForRecord2[0] && - _block[1] == NFileHeader::NMagic::kMagicForRecord2[1]) || - oldBE; - - if (binMode) - { - RINOK(ReadBytes(_block + 2, NFileHeader::kRecord2Size - 2, processedSize)); - if (processedSize != NFileHeader::kRecord2Size - 2) - return S_FALSE; - item.Align = 2; - _blockPos = 2; - item.DevMajor = 0; - item.DevMinor = ConvertValue(ReadUInt16(), oldBE); - item.inode = ConvertValue(ReadUInt16(), oldBE); - item.Mode = ConvertValue(ReadUInt16(), oldBE); - item.UID = ConvertValue(ReadUInt16(), oldBE); - item.GID = ConvertValue(ReadUInt16(), oldBE); - item.NumLinks = ConvertValue(ReadUInt16(), oldBE); - item.RDevMajor =0; - item.RDevMinor = ConvertValue(ReadUInt16(), oldBE); - UInt16 timeHigh = ConvertValue(ReadUInt16(), oldBE); - UInt16 timeLow = ConvertValue(ReadUInt16(), oldBE); - item.MTime = (UInt32(timeHigh) << 16) + timeLow; - nameSize = ConvertValue(ReadUInt16(), oldBE); - UInt16 sizeHigh = ConvertValue(ReadUInt16(), oldBE); - UInt16 sizeLow = ConvertValue(ReadUInt16(), oldBE); - item.Size = (UInt32(sizeHigh) << 16) + sizeLow; - - item.ChkSum = 0; - item.HeaderSize = GetAlignedSize( - nameSize + NFileHeader::kRecord2Size, item.Align); - nameSize = item.HeaderSize - NFileHeader::kRecord2Size; - } - else - { - RINOK(ReadBytes(_block + 2, 4, processedSize)); - if (processedSize != 4) - return S_FALSE; - - bool magicOK = - memcmp(_block, NFileHeader::NMagic::kMagic1, 6) == 0 || - memcmp(_block, NFileHeader::NMagic::kMagic2, 6) == 0; - _blockPos = 6; - if (magicOK) - { - RINOK(ReadBytes(_block + 6, NFileHeader::kRecordSize - 6, processedSize)); - if (processedSize != NFileHeader::kRecordSize - 6) - return S_FALSE; - item.Align = 4; - - GetFromHex(item.inode); - GetFromHex(item.Mode); - GetFromHex(item.UID); - GetFromHex(item.GID); - GetFromHex(item.NumLinks); - UInt32 mTime; - GetFromHex(mTime); - item.MTime = mTime; - GetFromHex(item.Size); - GetFromHex(item.DevMajor); - GetFromHex(item.DevMinor); - GetFromHex(item.RDevMajor); - GetFromHex(item.RDevMinor); - GetFromHex(nameSize); - GetFromHex(item.ChkSum); - item.HeaderSize = GetAlignedSize( - nameSize + NFileHeader::kRecordSize, item.Align); - nameSize = item.HeaderSize - NFileHeader::kRecordSize; - } - else - { - if (!memcmp(_block, NFileHeader::NMagic::kMagic3, 6) == 0) - return S_FALSE; - RINOK(ReadBytes(_block + 6, NFileHeader::kOctRecordSize - 6, processedSize)); - if (processedSize != NFileHeader::kOctRecordSize - 6) - return S_FALSE; - item.Align = 1; - item.DevMajor = 0; - GetFromOct6(item.DevMinor); - GetFromOct6(item.inode); - GetFromOct6(item.Mode); - GetFromOct6(item.UID); - GetFromOct6(item.GID); - GetFromOct6(item.NumLinks); - item.RDevMajor = 0; - GetFromOct6(item.RDevMinor); - UInt32 mTime; - GetFromOct11(mTime); - item.MTime = mTime; - GetFromOct6(nameSize); - GetFromOct11(item.Size); // ????? - item.HeaderSize = GetAlignedSize( - nameSize + NFileHeader::kOctRecordSize, item.Align); - nameSize = item.HeaderSize - NFileHeader::kOctRecordSize; - } - } - if (nameSize == 0 || nameSize >= (1 << 27)) - return E_FAIL; - RINOK(ReadBytes(item.Name.GetBuffer(nameSize), nameSize, processedSize)); - if (processedSize != nameSize) - return E_FAIL; - item.Name.ReleaseBuffer(); - if (strcmp(item.Name, NFileHeader::NMagic::kEndName) == 0) - return S_OK; - filled = true; - return S_OK; -} - -HRESULT CInArchive::Skip(UInt64 numBytes) -{ - UInt64 newPostion; - RINOK(m_Stream->Seek(numBytes, STREAM_SEEK_CUR, &newPostion)); - m_Position += numBytes; - if (m_Position != newPostion) - return E_FAIL; - return S_OK; -} - -HRESULT CInArchive::SkipDataRecords(UInt64 dataSize, UInt32 align) -{ - while ((dataSize & (align - 1)) != 0) - dataSize++; - return Skip(dataSize); -} - - -class CHandler: - public IInArchive, - public IInArchiveGetStream, - public CMyUnknownImp -{ - CObjectVector<CItemEx> _items; - CMyComPtr<IInStream> _stream; -public: - MY_UNKNOWN_IMP2(IInArchive, IInArchiveGetStream) - INTERFACE_IInArchive(;) - STDMETHOD(GetStream)(UInt32 index, ISequentialInStream **stream); -}; - -/* -enum -{ - kpidinode = kpidUserDefined, - kpidiChkSum -}; -*/ - -STATPROPSTG 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}, - // { L"inode", kpidinode, VT_UI4} - // { L"CheckSum", kpidiChkSum, VT_UI4} -}; - -IMP_IInArchive_Props -IMP_IInArchive_ArcProps_NO - -STDMETHODIMP CHandler::Open(IInStream *stream, const UInt64 *, IArchiveOpenCallback *callback) -{ - COM_TRY_BEGIN - // try - { - CInArchive archive; - - UInt64 endPos = 0; - bool needSetTotal = true; - - if (callback != NULL) - { - RINOK(stream->Seek(0, STREAM_SEEK_END, &endPos)); - RINOK(stream->Seek(0, STREAM_SEEK_SET, NULL)); - } - - RINOK(archive.Open(stream)); - - _items.Clear(); - - for (;;) - { - CItemEx item; - bool filled; - HRESULT result = archive.GetNextItem(filled, item); - if (result == S_FALSE) - return S_FALSE; - if (result != S_OK) - return S_FALSE; - if (!filled) - break; - _items.Add(item); - archive.SkipDataRecords(item.Size, item.Align); - if (callback != NULL) - { - if (needSetTotal) - { - RINOK(callback->SetTotal(NULL, &endPos)); - needSetTotal = false; - } - if (_items.Size() % 100 == 0) - { - UInt64 numFiles = _items.Size(); - UInt64 numBytes = item.HeaderPosition; - RINOK(callback->SetCompleted(&numFiles, &numBytes)); - } - } - } - if (_items.Size() == 0) - return S_FALSE; - - _stream = stream; - } - /* - catch(...) - { - return S_FALSE; - } - */ - return S_OK; - COM_TRY_END -} - -STDMETHODIMP CHandler::Close() -{ - _items.Clear(); - _stream.Release(); - return S_OK; -} - -STDMETHODIMP CHandler::GetNumberOfItems(UInt32 *numItems) -{ - *numItems = _items.Size(); - return S_OK; -} - -STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *value) -{ - COM_TRY_BEGIN - NWindows::NCOM::CPropVariant prop; - const CItemEx &item = _items[index]; - - switch(propID) - { - case kpidPath: prop = NItemName::GetOSName(MultiByteToUnicodeString(item.Name, CP_OEMCP)); break; - case kpidIsDir: prop = item.IsDir(); break; - case kpidSize: - case kpidPackSize: - prop = (UInt64)item.Size; - break; - case kpidMTime: - { - if (item.MTime != 0) - { - FILETIME utc; - NWindows::NTime::UnixTimeToFileTime(item.MTime, utc); - prop = utc; - } - break; - } - case kpidPosixAttrib: prop = item.Mode; break; - /* - case kpidinode: prop = item.inode; break; - case kpidiChkSum: prop = item.ChkSum; break; - */ - } - prop.Detach(value); - return S_OK; - COM_TRY_END -} - -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; - UInt64 totalSize = 0; - UInt32 i; - for (i = 0; i < numItems; i++) - totalSize += _items[allFilesMode ? i : indices[i]].Size; - extractCallback->SetTotal(totalSize); - - UInt64 currentTotalSize = 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 = lps->OutSize = currentTotalSize; - RINOK(lps->SetCur()); - CMyComPtr<ISequentialOutStream> outStream; - Int32 askMode = testMode ? - NExtract::NAskMode::kTest : - NExtract::NAskMode::kExtract; - Int32 index = allFilesMode ? i : indices[i]; - const CItemEx &item = _items[index]; - RINOK(extractCallback->GetStream(index, &outStream, askMode)); - currentTotalSize += item.Size; - if (item.IsDir()) - { - RINOK(extractCallback->PrepareOperation(askMode)); - RINOK(extractCallback->SetOperationResult(NExtract::NOperationResult::kOK)); - continue; - } - if (!testMode && !outStream) - continue; - RINOK(extractCallback->PrepareOperation(askMode)); - if (testMode) - { - RINOK(extractCallback->SetOperationResult(NExtract::NOperationResult::kOK)); - continue; - } - RINOK(_stream->Seek(item.GetDataPosition(), STREAM_SEEK_SET, NULL)); - streamSpec->Init(item.Size); - RINOK(copyCoder->Code(inStream, outStream, NULL, NULL, progress)); - outStream.Release(); - RINOK(extractCallback->SetOperationResult((copyCoderSpec->TotalSize == item.Size) ? - NExtract::NOperationResult::kOK: - NExtract::NOperationResult::kDataError)); - } - return S_OK; - COM_TRY_END -} - -STDMETHODIMP CHandler::GetStream(UInt32 index, ISequentialInStream **stream) -{ - COM_TRY_BEGIN - const CItemEx &item = _items[index]; - return CreateLimitedInStream(_stream, item.GetDataPosition(), item.Size, stream); - COM_TRY_END -} - -static IInArchive *CreateArc() { return new NArchive::NCpio::CHandler; } - -static CArcInfo g_ArcInfo = - { L"Cpio", L"cpio", 0, 0xED, { 0 }, 0, false, CreateArc, 0 }; - -REGISTER_ARC(Cpio) - -}} |