Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/kornelski/7z.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'CPP/7zip/Archive/Cpio/CpioIn.cpp')
-rwxr-xr-xCPP/7zip/Archive/Cpio/CpioIn.cpp271
1 files changed, 271 insertions, 0 deletions
diff --git a/CPP/7zip/Archive/Cpio/CpioIn.cpp b/CPP/7zip/Archive/Cpio/CpioIn.cpp
new file mode 100755
index 00000000..91399362
--- /dev/null
+++ b/CPP/7zip/Archive/Cpio/CpioIn.cpp
@@ -0,0 +1,271 @@
+// Archive/cpioIn.cpp
+
+#include "StdAfx.h"
+
+#include "CpioIn.h"
+
+#include "Common/StringToInt.h"
+#include "Windows/Defs.h"
+
+#include "../../Common/StreamUtils.h"
+
+#include "CpioHeader.h"
+
+namespace NArchive {
+namespace NCpio {
+
+HRESULT CInArchive::ReadBytes(void *data, UInt32 size, UInt32 &processedSize)
+{
+ RINOK(ReadStream(m_Stream, data, size, &processedSize));
+ 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.ModificationTime = (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 modificationTime;
+ GetFromHex(modificationTime);
+ item.ModificationTime = modificationTime;
+ 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 modificationTime;
+ GetFromOct11(modificationTime);
+ item.ModificationTime = modificationTime;
+ 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::Skeep(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::SkeepDataRecords(UInt64 dataSize, UInt32 align)
+{
+ while ((dataSize & (align - 1)) != 0)
+ dataSize++;
+ return Skeep(dataSize);
+}
+
+}}