summaryrefslogtreecommitdiffstats
path: root/src/libs/7zip/win/CPP/7zip/Archive/Iso/IsoIn.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/libs/7zip/win/CPP/7zip/Archive/Iso/IsoIn.cpp')
-rw-r--r--src/libs/7zip/win/CPP/7zip/Archive/Iso/IsoIn.cpp453
1 files changed, 453 insertions, 0 deletions
diff --git a/src/libs/7zip/win/CPP/7zip/Archive/Iso/IsoIn.cpp b/src/libs/7zip/win/CPP/7zip/Archive/Iso/IsoIn.cpp
new file mode 100644
index 000000000..7ed618d29
--- /dev/null
+++ b/src/libs/7zip/win/CPP/7zip/Archive/Iso/IsoIn.cpp
@@ -0,0 +1,453 @@
+// Archive/IsoIn.cpp
+
+#include "StdAfx.h"
+
+#include "IsoIn.h"
+
+#include "../../Common/StreamUtils.h"
+
+namespace NArchive {
+namespace NIso {
+
+Byte CInArchive::ReadByte()
+{
+ if (m_BufferPos >= BlockSize)
+ m_BufferPos = 0;
+ if (m_BufferPos == 0)
+ {
+ size_t processedSize = BlockSize;
+ if (ReadStream(_stream, m_Buffer, &processedSize) != S_OK)
+ throw 1;
+ if (processedSize != BlockSize)
+ throw 1;
+ }
+ Byte b = m_Buffer[m_BufferPos++];
+ _position++;
+ return b;
+}
+
+void CInArchive::ReadBytes(Byte *data, UInt32 size)
+{
+ for (UInt32 i = 0; i < size; i++)
+ data[i] = ReadByte();
+}
+
+void CInArchive::Skip(size_t size)
+{
+ while (size-- != 0)
+ ReadByte();
+}
+
+void CInArchive::SkipZeros(size_t size)
+{
+ while (size-- != 0)
+ {
+ Byte b = ReadByte();
+ if (b != 0)
+ throw 1;
+ }
+}
+
+UInt16 CInArchive::ReadUInt16Spec()
+{
+ UInt16 value = 0;
+ for (int i = 0; i < 2; i++)
+ value |= ((UInt16)(ReadByte()) << (8 * i));
+ return value;
+}
+
+
+UInt16 CInArchive::ReadUInt16()
+{
+ Byte b[4];
+ ReadBytes(b, 4);
+ UInt32 value = 0;
+ for (int i = 0; i < 2; i++)
+ {
+ if (b[i] != b[3 - i])
+ IncorrectBigEndian = true;
+ value |= ((UInt16)(b[i]) << (8 * i));
+ }
+ return (UInt16)value;
+}
+
+UInt32 CInArchive::ReadUInt32Le()
+{
+ UInt32 value = 0;
+ for (int i = 0; i < 4; i++)
+ value |= ((UInt32)(ReadByte()) << (8 * i));
+ return value;
+}
+
+UInt32 CInArchive::ReadUInt32Be()
+{
+ UInt32 value = 0;
+ for (int i = 0; i < 4; i++)
+ {
+ value <<= 8;
+ value |= ReadByte();
+ }
+ return value;
+}
+
+UInt32 CInArchive::ReadUInt32()
+{
+ Byte b[8];
+ ReadBytes(b, 8);
+ UInt32 value = 0;
+ for (int i = 0; i < 4; i++)
+ {
+ if (b[i] != b[7 - i])
+ throw 1;
+ value |= ((UInt32)(b[i]) << (8 * i));
+ }
+ return value;
+}
+
+UInt32 CInArchive::ReadDigits(int numDigits)
+{
+ UInt32 res = 0;
+ for (int i = 0; i < numDigits; i++)
+ {
+ Byte b = ReadByte();
+ if (b < '0' || b > '9')
+ {
+ if (b == 0) // it's bug in some CD's
+ b = '0';
+ else
+ throw 1;
+ }
+ UInt32 d = (UInt32)(b - '0');
+ res *= 10;
+ res += d;
+ }
+ return res;
+}
+
+void CInArchive::ReadDateTime(CDateTime &d)
+{
+ d.Year = (UInt16)ReadDigits(4);
+ d.Month = (Byte)ReadDigits(2);
+ d.Day = (Byte)ReadDigits(2);
+ d.Hour = (Byte)ReadDigits(2);
+ d.Minute = (Byte)ReadDigits(2);
+ d.Second = (Byte)ReadDigits(2);
+ d.Hundredths = (Byte)ReadDigits(2);
+ d.GmtOffset = (signed char)ReadByte();
+}
+
+void CInArchive::ReadBootRecordDescriptor(CBootRecordDescriptor &d)
+{
+ ReadBytes(d.BootSystemId, sizeof(d.BootSystemId));
+ ReadBytes(d.BootId, sizeof(d.BootId));
+ ReadBytes(d.BootSystemUse, sizeof(d.BootSystemUse));
+}
+
+void CInArchive::ReadRecordingDateTime(CRecordingDateTime &t)
+{
+ t.Year = ReadByte();
+ t.Month = ReadByte();
+ t.Day = ReadByte();
+ t.Hour = ReadByte();
+ t.Minute = ReadByte();
+ t.Second = ReadByte();
+ t.GmtOffset = (signed char)ReadByte();
+}
+
+void CInArchive::ReadDirRecord2(CDirRecord &r, Byte len)
+{
+ r.ExtendedAttributeRecordLen = ReadByte();
+ if (r.ExtendedAttributeRecordLen != 0)
+ throw 1;
+ r.ExtentLocation = ReadUInt32();
+ r.DataLength = ReadUInt32();
+ ReadRecordingDateTime(r.DateTime);
+ r.FileFlags = ReadByte();
+ r.FileUnitSize = ReadByte();
+ r.InterleaveGapSize = ReadByte();
+ r.VolSequenceNumber = ReadUInt16();
+ Byte idLen = ReadByte();
+ r.FileId.SetCapacity(idLen);
+ ReadBytes((Byte *)r.FileId, idLen);
+ int padSize = 1 - (idLen & 1);
+
+ // SkipZeros(1 - (idLen & 1));
+ Skip(1 - (idLen & 1)); // it's bug in some cd's. Must be zeros
+
+ int curPos = 33 + idLen + padSize;
+ if (curPos > len)
+ throw 1;
+ int rem = len - curPos;
+ r.SystemUse.SetCapacity(rem);
+ ReadBytes((Byte *)r.SystemUse, rem);
+}
+
+void CInArchive::ReadDirRecord(CDirRecord &r)
+{
+ Byte len = ReadByte();
+ // Some CDs can have incorrect value len = 48 ('0') in VolumeDescriptor.
+ // But maybe we must use real "len" for other records.
+ len = 34;
+ ReadDirRecord2(r, len);
+}
+
+void CInArchive::ReadVolumeDescriptor(CVolumeDescriptor &d)
+{
+ d.VolFlags = ReadByte();
+ ReadBytes(d.SystemId, sizeof(d.SystemId));
+ ReadBytes(d.VolumeId, sizeof(d.VolumeId));
+ SkipZeros(8);
+ d.VolumeSpaceSize = ReadUInt32();
+ ReadBytes(d.EscapeSequence, sizeof(d.EscapeSequence));
+ d.VolumeSetSize = ReadUInt16();
+ d.VolumeSequenceNumber = ReadUInt16();
+ d.LogicalBlockSize = ReadUInt16();
+ d.PathTableSize = ReadUInt32();
+ d.LPathTableLocation = ReadUInt32Le();
+ d.LOptionalPathTableLocation = ReadUInt32Le();
+ d.MPathTableLocation = ReadUInt32Be();
+ d.MOptionalPathTableLocation = ReadUInt32Be();
+ ReadDirRecord(d.RootDirRecord);
+ ReadBytes(d.VolumeSetId, sizeof(d.VolumeSetId));
+ ReadBytes(d.PublisherId, sizeof(d.PublisherId));
+ ReadBytes(d.DataPreparerId, sizeof(d.DataPreparerId));
+ ReadBytes(d.ApplicationId, sizeof(d.ApplicationId));
+ ReadBytes(d.CopyrightFileId, sizeof(d.CopyrightFileId));
+ ReadBytes(d.AbstractFileId, sizeof(d.AbstractFileId));
+ ReadBytes(d.BibFileId, sizeof(d.BibFileId));
+ ReadDateTime(d.CTime);
+ ReadDateTime(d.MTime);
+ ReadDateTime(d.ExpirationTime);
+ ReadDateTime(d.EffectiveTime);
+ d.FileStructureVersion = ReadByte(); // = 1
+ SkipZeros(1);
+ ReadBytes(d.ApplicationUse, sizeof(d.ApplicationUse));
+ SkipZeros(653);
+}
+
+static const Byte kSig_CD001[5] = { 'C', 'D', '0', '0', '1' };
+
+static const Byte kSig_NSR02[5] = { 'N', 'S', 'R', '0', '2' };
+static const Byte kSig_NSR03[5] = { 'N', 'S', 'R', '0', '3' };
+static const Byte kSig_BEA01[5] = { 'B', 'E', 'A', '0', '1' };
+static const Byte kSig_TEA01[5] = { 'T', 'E', 'A', '0', '1' };
+
+static inline bool CheckSignature(const Byte *sig, const Byte *data)
+{
+ for (int i = 0; i < 5; i++)
+ if (sig[i] != data[i])
+ return false;
+ return true;
+}
+
+void CInArchive::SeekToBlock(UInt32 blockIndex)
+{
+ if (_stream->Seek((UInt64)blockIndex * VolDescs[MainVolDescIndex].LogicalBlockSize, STREAM_SEEK_SET, &_position) != S_OK)
+ throw 1;
+ m_BufferPos = 0;
+}
+
+void CInArchive::ReadDir(CDir &d, int level)
+{
+ if (!d.IsDir())
+ return;
+ SeekToBlock(d.ExtentLocation);
+ UInt64 startPos = _position;
+
+ bool firstItem = true;
+ for (;;)
+ {
+ UInt64 offset = _position - startPos;
+ if (offset >= d.DataLength)
+ break;
+ Byte len = ReadByte();
+ if (len == 0)
+ continue;
+ CDir subItem;
+ ReadDirRecord2(subItem, len);
+ if (firstItem && level == 0)
+ IsSusp = subItem.CheckSusp(SuspSkipSize);
+
+ if (!subItem.IsSystemItem())
+ d._subItems.Add(subItem);
+
+ firstItem = false;
+ }
+ for (int i = 0; i < d._subItems.Size(); i++)
+ ReadDir(d._subItems[i], level + 1);
+}
+
+void CInArchive::CreateRefs(CDir &d)
+{
+ if (!d.IsDir())
+ return;
+ for (int i = 0; i < d._subItems.Size(); i++)
+ {
+ CRef ref;
+ CDir &subItem = d._subItems[i];
+ subItem.Parent = &d;
+ ref.Dir = &d;
+ ref.Index = i;
+ Refs.Add(ref);
+ CreateRefs(subItem);
+ }
+}
+
+void CInArchive::ReadBootInfo()
+{
+ if (!_bootIsDefined)
+ return;
+ if (memcmp(_bootDesc.BootSystemId, kElToritoSpec, sizeof(_bootDesc.BootSystemId)) != 0)
+ return;
+
+ const Byte *p = (const Byte *)_bootDesc.BootSystemUse;
+ UInt32 blockIndex = p[0] | ((UInt32)p[1] << 8) | ((UInt32)p[2] << 16) | ((UInt32)p[3] << 24);
+ SeekToBlock(blockIndex);
+ Byte b = ReadByte();
+ if (b != NBootEntryId::kValidationEntry)
+ return;
+ {
+ CBootValidationEntry e;
+ e.PlatformId = ReadByte();
+ if (ReadUInt16Spec() != 0)
+ throw 1;
+ ReadBytes(e.Id, sizeof(e.Id));
+ /* UInt16 checkSum = */ ReadUInt16Spec();
+ if (ReadByte() != 0x55)
+ throw 1;
+ if (ReadByte() != 0xAA)
+ throw 1;
+ }
+ b = ReadByte();
+ if (b == NBootEntryId::kInitialEntryBootable || b == NBootEntryId::kInitialEntryNotBootable)
+ {
+ CBootInitialEntry e;
+ e.Bootable = (b == NBootEntryId::kInitialEntryBootable);
+ e.BootMediaType = ReadByte();
+ e.LoadSegment = ReadUInt16Spec();
+ e.SystemType = ReadByte();
+ if (ReadByte() != 0)
+ throw 1;
+ e.SectorCount = ReadUInt16Spec();
+ e.LoadRBA = ReadUInt32Le();
+ if (ReadByte() != 0)
+ throw 1;
+ BootEntries.Add(e);
+ }
+ else
+ return;
+}
+
+HRESULT CInArchive::Open2()
+{
+ Clear();
+ RINOK(_stream->Seek(kStartPos, STREAM_SEEK_CUR, &_position));
+
+ m_BufferPos = 0;
+ BlockSize = kBlockSize;
+ for (;;)
+ {
+ Byte sig[7];
+ ReadBytes(sig, 7);
+ Byte ver = sig[6];
+ if (!CheckSignature(kSig_CD001, sig + 1))
+ {
+ return S_FALSE;
+ /*
+ if (sig[0] != 0 || ver != 1)
+ break;
+ if (CheckSignature(kSig_BEA01, sig + 1))
+ {
+ }
+ else if (CheckSignature(kSig_TEA01, sig + 1))
+ {
+ break;
+ }
+ else if (CheckSignature(kSig_NSR02, sig + 1))
+ {
+ }
+ else
+ break;
+ SkipZeros(0x800 - 7);
+ continue;
+ */
+ }
+ // version = 2 for ISO 9660:1999?
+ if (ver > 2)
+ throw S_FALSE;
+
+ if (sig[0] == NVolDescType::kTerminator)
+ {
+ break;
+ // Skip(0x800 - 7);
+ // continue;
+ }
+ switch(sig[0])
+ {
+ case NVolDescType::kBootRecord:
+ {
+ _bootIsDefined = true;
+ ReadBootRecordDescriptor(_bootDesc);
+ break;
+ }
+ case NVolDescType::kPrimaryVol:
+ case NVolDescType::kSupplementaryVol:
+ {
+ // some ISOs have two PrimaryVols.
+ CVolumeDescriptor vd;
+ ReadVolumeDescriptor(vd);
+ if (sig[0] == NVolDescType::kPrimaryVol)
+ {
+ // some burners write "Joliet" Escape Sequence to primary volume
+ memset(vd.EscapeSequence, 0, sizeof(vd.EscapeSequence));
+ }
+ VolDescs.Add(vd);
+ break;
+ }
+ default:
+ break;
+ }
+ }
+ if (VolDescs.IsEmpty())
+ return S_FALSE;
+ for (MainVolDescIndex = VolDescs.Size() - 1; MainVolDescIndex > 0; MainVolDescIndex--)
+ if (VolDescs[MainVolDescIndex].IsJoliet())
+ break;
+ // MainVolDescIndex = 0; // to read primary volume
+ const CVolumeDescriptor &vd = VolDescs[MainVolDescIndex];
+ if (vd.LogicalBlockSize != kBlockSize)
+ return S_FALSE;
+ (CDirRecord &)_rootDir = vd.RootDirRecord;
+ ReadDir(_rootDir, 0);
+ CreateRefs(_rootDir);
+ ReadBootInfo();
+ return S_OK;
+}
+
+HRESULT CInArchive::Open(IInStream *inStream)
+{
+ _stream = inStream;
+ UInt64 pos;
+ RINOK(_stream->Seek(0, STREAM_SEEK_CUR, &pos));
+ RINOK(_stream->Seek(0, STREAM_SEEK_END, &_archiveSize));
+ RINOK(_stream->Seek(pos, STREAM_SEEK_SET, &_position));
+ HRESULT res = S_FALSE;
+ try { res = Open2(); }
+ catch(...) { Clear(); res = S_FALSE; }
+ _stream.Release();
+ return res;
+}
+
+void CInArchive::Clear()
+{
+ IncorrectBigEndian = false;
+ Refs.Clear();
+ _rootDir.Clear();
+ VolDescs.Clear();
+ _bootIsDefined = false;
+ BootEntries.Clear();
+ SuspSkipSize = 0;
+ IsSusp = false;
+}
+
+}}