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/Iso/IsoIn.cpp')
-rw-r--r--[-rwxr-xr-x]CPP/7zip/Archive/Iso/IsoIn.cpp197
1 files changed, 143 insertions, 54 deletions
diff --git a/CPP/7zip/Archive/Iso/IsoIn.cpp b/CPP/7zip/Archive/Iso/IsoIn.cpp
index 7ed618d2..ba12acae 100755..100644
--- a/CPP/7zip/Archive/Iso/IsoIn.cpp
+++ b/CPP/7zip/Archive/Iso/IsoIn.cpp
@@ -2,24 +2,34 @@
#include "StdAfx.h"
-#include "IsoIn.h"
+#include "../../../Common/MyException.h"
#include "../../Common/StreamUtils.h"
+#include "IsoIn.h"
+
namespace NArchive {
namespace NIso {
+struct CUnexpectedEndException {};
+struct CHeaderErrorException {};
+struct CEndianErrorException {};
+
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;
+ size_t processed = BlockSize;
+ HRESULT res = ReadStream(_stream, m_Buffer, &processed);
+ if (res != S_OK)
+ throw CSystemException(res);
+ if (processed != BlockSize)
+ throw CUnexpectedEndException();
+ UInt64 end = _position + processed;
+ if (PhySize < end)
+ PhySize = end;
}
Byte b = m_Buffer[m_BufferPos++];
_position++;
@@ -44,16 +54,16 @@ void CInArchive::SkipZeros(size_t size)
{
Byte b = ReadByte();
if (b != 0)
- throw 1;
+ throw CHeaderErrorException();
}
}
UInt16 CInArchive::ReadUInt16Spec()
{
- UInt16 value = 0;
+ UInt16 val = 0;
for (int i = 0; i < 2; i++)
- value |= ((UInt16)(ReadByte()) << (8 * i));
- return value;
+ val |= ((UInt16)(ReadByte()) << (8 * i));
+ return val;
}
@@ -61,47 +71,47 @@ UInt16 CInArchive::ReadUInt16()
{
Byte b[4];
ReadBytes(b, 4);
- UInt32 value = 0;
+ UInt32 val = 0;
for (int i = 0; i < 2; i++)
{
if (b[i] != b[3 - i])
IncorrectBigEndian = true;
- value |= ((UInt16)(b[i]) << (8 * i));
+ val |= ((UInt16)(b[i]) << (8 * i));
}
- return (UInt16)value;
+ return (UInt16)val;
}
UInt32 CInArchive::ReadUInt32Le()
{
- UInt32 value = 0;
+ UInt32 val = 0;
for (int i = 0; i < 4; i++)
- value |= ((UInt32)(ReadByte()) << (8 * i));
- return value;
+ val |= ((UInt32)(ReadByte()) << (8 * i));
+ return val;
}
UInt32 CInArchive::ReadUInt32Be()
{
- UInt32 value = 0;
+ UInt32 val = 0;
for (int i = 0; i < 4; i++)
{
- value <<= 8;
- value |= ReadByte();
+ val <<= 8;
+ val |= ReadByte();
}
- return value;
+ return val;
}
UInt32 CInArchive::ReadUInt32()
{
Byte b[8];
ReadBytes(b, 8);
- UInt32 value = 0;
+ UInt32 val = 0;
for (int i = 0; i < 4; i++)
{
if (b[i] != b[7 - i])
- throw 1;
- value |= ((UInt32)(b[i]) << (8 * i));
+ throw CEndianErrorException();
+ val |= ((UInt32)(b[i]) << (8 * i));
}
- return value;
+ return val;
}
UInt32 CInArchive::ReadDigits(int numDigits)
@@ -115,7 +125,7 @@ UInt32 CInArchive::ReadDigits(int numDigits)
if (b == 0) // it's bug in some CD's
b = '0';
else
- throw 1;
+ throw CHeaderErrorException();
}
UInt32 d = (UInt32)(b - '0');
res *= 10;
@@ -158,16 +168,16 @@ void CInArchive::ReadDirRecord2(CDirRecord &r, Byte len)
{
r.ExtendedAttributeRecordLen = ReadByte();
if (r.ExtendedAttributeRecordLen != 0)
- throw 1;
+ throw CHeaderErrorException();
r.ExtentLocation = ReadUInt32();
- r.DataLength = ReadUInt32();
+ r.Size = ReadUInt32();
ReadRecordingDateTime(r.DateTime);
r.FileFlags = ReadByte();
r.FileUnitSize = ReadByte();
r.InterleaveGapSize = ReadByte();
r.VolSequenceNumber = ReadUInt16();
Byte idLen = ReadByte();
- r.FileId.SetCapacity(idLen);
+ r.FileId.Alloc(idLen);
ReadBytes((Byte *)r.FileId, idLen);
int padSize = 1 - (idLen & 1);
@@ -176,9 +186,9 @@ void CInArchive::ReadDirRecord2(CDirRecord &r, Byte len)
int curPos = 33 + idLen + padSize;
if (curPos > len)
- throw 1;
+ throw CHeaderErrorException();
int rem = len - curPos;
- r.SystemUse.SetCapacity(rem);
+ r.SystemUse.Alloc(rem);
ReadBytes((Byte *)r.SystemUse, rem);
}
@@ -242,15 +252,34 @@ static inline bool CheckSignature(const Byte *sig, const Byte *data)
void CInArchive::SeekToBlock(UInt32 blockIndex)
{
- if (_stream->Seek((UInt64)blockIndex * VolDescs[MainVolDescIndex].LogicalBlockSize, STREAM_SEEK_SET, &_position) != S_OK)
- throw 1;
+ HRESULT res = _stream->Seek((UInt64)blockIndex * VolDescs[MainVolDescIndex].LogicalBlockSize, STREAM_SEEK_SET, &_position);
+ if (res != S_OK)
+ throw CSystemException(res);
m_BufferPos = 0;
}
+static const int kNumLevelsMax = 256;
+
void CInArchive::ReadDir(CDir &d, int level)
{
if (!d.IsDir())
return;
+ if (level > kNumLevelsMax)
+ {
+ TooDeepDirs = true;
+ return;
+ }
+
+ {
+ FOR_VECTOR (i, UniqStartLocations)
+ if (UniqStartLocations[i] == d.ExtentLocation)
+ {
+ SelfLinkedDirs = true;
+ return;
+ }
+ UniqStartLocations.Add(d.ExtentLocation);
+ }
+
SeekToBlock(d.ExtentLocation);
UInt64 startPos = _position;
@@ -258,7 +287,7 @@ void CInArchive::ReadDir(CDir &d, int level)
for (;;)
{
UInt64 offset = _position - startPos;
- if (offset >= d.DataLength)
+ if (offset >= d.Size)
break;
Byte len = ReadByte();
if (len == 0)
@@ -273,21 +302,44 @@ void CInArchive::ReadDir(CDir &d, int level)
firstItem = false;
}
- for (int i = 0; i < d._subItems.Size(); i++)
+ FOR_VECTOR (i, d._subItems)
ReadDir(d._subItems[i], level + 1);
+
+ UniqStartLocations.DeleteBack();
}
void CInArchive::CreateRefs(CDir &d)
{
if (!d.IsDir())
return;
- for (int i = 0; i < d._subItems.Size(); i++)
+ for (unsigned i = 0; i < d._subItems.Size();)
{
CRef ref;
CDir &subItem = d._subItems[i];
subItem.Parent = &d;
ref.Dir = &d;
- ref.Index = i;
+ ref.Index = i++;
+ ref.NumExtents = 1;
+ ref.TotalSize = subItem.Size;
+ if (subItem.IsNonFinalExtent())
+ {
+ for (;;)
+ {
+ if (i == d._subItems.Size())
+ {
+ HeadersError = true;
+ break;
+ }
+ const CDir &next = d._subItems[i];
+ if (!subItem.AreMultiPartEqualWith(next))
+ break;
+ i++;
+ ref.NumExtents++;
+ ref.TotalSize += next.Size;
+ if (!next.IsNonFinalExtent())
+ break;
+ }
+ }
Refs.Add(ref);
CreateRefs(subItem);
}
@@ -310,13 +362,13 @@ void CInArchive::ReadBootInfo()
CBootValidationEntry e;
e.PlatformId = ReadByte();
if (ReadUInt16Spec() != 0)
- throw 1;
+ throw CHeaderErrorException();
ReadBytes(e.Id, sizeof(e.Id));
/* UInt16 checkSum = */ ReadUInt16Spec();
if (ReadByte() != 0x55)
- throw 1;
+ throw CHeaderErrorException();
if (ReadByte() != 0xAA)
- throw 1;
+ throw CHeaderErrorException();
}
b = ReadByte();
if (b == NBootEntryId::kInitialEntryBootable || b == NBootEntryId::kInitialEntryNotBootable)
@@ -327,11 +379,11 @@ void CInArchive::ReadBootInfo()
e.LoadSegment = ReadUInt16Spec();
e.SystemType = ReadByte();
if (ReadByte() != 0)
- throw 1;
+ throw CHeaderErrorException();
e.SectorCount = ReadUInt16Spec();
e.LoadRBA = ReadUInt32Le();
if (ReadByte() != 0)
- throw 1;
+ throw CHeaderErrorException();
BootEntries.Add(e);
}
else
@@ -340,16 +392,22 @@ void CInArchive::ReadBootInfo()
HRESULT CInArchive::Open2()
{
- Clear();
- RINOK(_stream->Seek(kStartPos, STREAM_SEEK_CUR, &_position));
+ _position = 0;
+ RINOK(_stream->Seek(0, STREAM_SEEK_END, &_fileSize));
+ if (_fileSize < kStartPos)
+ return S_FALSE;
+ RINOK(_stream->Seek(kStartPos, STREAM_SEEK_SET, &_position));
+ PhySize = _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;
@@ -372,9 +430,10 @@ HRESULT CInArchive::Open2()
continue;
*/
}
+
// version = 2 for ISO 9660:1999?
if (ver > 2)
- throw S_FALSE;
+ return S_FALSE;
if (sig[0] == NVolDescType::kTerminator)
{
@@ -382,7 +441,8 @@ HRESULT CInArchive::Open2()
// Skip(0x800 - 7);
// continue;
}
- switch(sig[0])
+
+ switch (sig[0])
{
case NVolDescType::kBootRecord:
{
@@ -408,6 +468,7 @@ HRESULT CInArchive::Open2()
break;
}
}
+
if (VolDescs.IsEmpty())
return S_FALSE;
for (MainVolDescIndex = VolDescs.Size() - 1; MainVolDescIndex > 0; MainVolDescIndex--)
@@ -417,30 +478,58 @@ HRESULT CInArchive::Open2()
const CVolumeDescriptor &vd = VolDescs[MainVolDescIndex];
if (vd.LogicalBlockSize != kBlockSize)
return S_FALSE;
+
+ IsArc = true;
+
(CDirRecord &)_rootDir = vd.RootDirRecord;
ReadDir(_rootDir, 0);
CreateRefs(_rootDir);
ReadBootInfo();
+
+ {
+ FOR_VECTOR(i, Refs)
+ {
+ const CRef &ref = Refs[i];
+ for (UInt32 j = 0; j < ref.NumExtents; j++)
+ {
+ const CDir &item = ref.Dir->_subItems[ref.Index + j];
+ if (!item.IsDir())
+ UpdatePhySize(item.ExtentLocation, item.Size);
+ }
+ }
+ }
+ {
+ FOR_VECTOR(i, BootEntries)
+ {
+ const CBootInitialEntry &be = BootEntries[i];
+ UpdatePhySize(be.LoadRBA, GetBootItemSize(i));
+ }
+ }
return S_OK;
}
HRESULT CInArchive::Open(IInStream *inStream)
{
+ Clear();
_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;
+ try { return Open2(); }
+ catch(const CSystemException &e) { return e.ErrorCode; }
+ catch(CUnexpectedEndException &) { UnexpectedEnd = true; return S_FALSE; }
+ catch(CHeaderErrorException &) { HeadersError = true; return S_FALSE; }
+ catch(CEndianErrorException &) { IncorrectBigEndian = true; return S_FALSE; }
}
void CInArchive::Clear()
{
+ IsArc = false;
+ UnexpectedEnd = false;
+ HeadersError = false;
IncorrectBigEndian = false;
+ TooDeepDirs = false;
+ SelfLinkedDirs = false;
+
+ UniqStartLocations.Clear();
+
Refs.Clear();
_rootDir.Clear();
VolDescs.Clear();