diff options
author | Igor Pavlov <ipavlov@users.sourceforge.net> | 2015-06-15 03:00:00 +0300 |
---|---|---|
committer | Kornel Lesiński <kornel@geekhood.net> | 2016-05-28 02:16:54 +0300 |
commit | 54490d51d5c6b0d794dcbad2d634d4c95fc25b6c (patch) | |
tree | c3c413656432c0ef87b2841c80e42b55ad17d4e8 /CPP/7zip/Archive/Iso | |
parent | 0713a3ab803e57401f18432148b4139e5fe6e5dd (diff) |
15.0515.05
Diffstat (limited to 'CPP/7zip/Archive/Iso')
-rw-r--r-- | CPP/7zip/Archive/Iso/IsoHandler.cpp | 37 | ||||
-rw-r--r-- | CPP/7zip/Archive/Iso/IsoHeader.cpp | 9 | ||||
-rw-r--r-- | CPP/7zip/Archive/Iso/IsoHeader.h | 8 | ||||
-rw-r--r-- | CPP/7zip/Archive/Iso/IsoIn.cpp | 193 | ||||
-rw-r--r-- | CPP/7zip/Archive/Iso/IsoIn.h | 132 | ||||
-rw-r--r-- | CPP/7zip/Archive/Iso/IsoItem.h | 33 | ||||
-rw-r--r-- | CPP/7zip/Archive/Iso/IsoRegister.cpp | 12 |
7 files changed, 263 insertions, 161 deletions
diff --git a/CPP/7zip/Archive/Iso/IsoHandler.cpp b/CPP/7zip/Archive/Iso/IsoHandler.cpp index aef920b0..713764d9 100644 --- a/CPP/7zip/Archive/Iso/IsoHandler.cpp +++ b/CPP/7zip/Archive/Iso/IsoHandler.cpp @@ -79,8 +79,7 @@ static void AddString(AString &s, const char *name, const Byte *p, unsigned size if (i != 0) { AString d; - memcpy(d.GetBuffer(i), p, i); - d.ReleaseBuffer(i); + d.SetFrom((const char *)p, i); s += '\n'; s += name; s += ": "; @@ -170,11 +169,14 @@ STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *val { case kpidPath: { - // char name[16]; - // ConvertUInt32ToString(index + 1, name); AString s = "[BOOT]" STRING_PATH_SEPARATOR; - // s += name; - // s += '-'; + if (_archive.BootEntries.Size() != 1) + { + char temp[16]; + ConvertUInt32ToString(index + 1, temp); + s += temp; + s += '-'; + } s += be.GetName(); prop = s; break; @@ -197,18 +199,18 @@ STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *val { UString s; if (_archive.IsJoliet()) - s = item.GetPathU(); + item.GetPathU(s); else s = MultiByteToUnicodeString(item.GetPath(_archive.IsSusp, _archive.SuspSkipSize), CP_OEMCP); - int pos = s.ReverseFind(L';'); - if (pos >= 0 && pos == (int)s.Len() - 2) - if (s.Back() == L'1') - s.DeleteFrom(pos); - if (!s.IsEmpty()) - if (s.Back() == L'.') - s.DeleteBack(); - prop = (const wchar_t *)NItemName::GetOSName2(s); + if (s.Len() >= 2 && s[s.Len() - 2] == ';' && s.Back() == '1') + s.DeleteFrom(s.Len() - 2); + + if (!s.IsEmpty() && s.Back() == L'.') + s.DeleteBack(); + + NItemName::ConvertToOSName2(s); + prop = s; } break; case kpidIsDir: prop = item.IsDir(); break; @@ -319,8 +321,7 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems, UInt64 offset = 0; for (UInt32 e = 0; e < ref.NumExtents; e++) { - if (e != 0) - lps->InSize = lps->OutSize = currentTotalSize + offset; + lps->InSize = lps->OutSize = currentTotalSize + offset; const CDir &item2 = ref.Dir->_subItems[ref.Index + e]; RINOK(_stream->Seek((UInt64)item2.ExtentLocation * _archive.BlockSize, STREAM_SEEK_SET, NULL)); streamSpec->Init(item2.Size); @@ -356,6 +357,7 @@ STDMETHODIMP CHandler::GetStream(UInt32 index, ISequentialInStream **stream) *stream = 0; UInt64 blockIndex; UInt64 currentItemSize; + if (index < (UInt32)_archive.Refs.Size()) { const CRef &ref = _archive.Refs[index]; @@ -402,6 +404,7 @@ STDMETHODIMP CHandler::GetStream(UInt32 index, ISequentialInStream **stream) currentItemSize = _archive.GetBootItemSize(bootIndex); blockIndex = be.LoadRBA; } + return CreateLimitedInStream(_stream, blockIndex * _archive.BlockSize, currentItemSize, stream); COM_TRY_END } diff --git a/CPP/7zip/Archive/Iso/IsoHeader.cpp b/CPP/7zip/Archive/Iso/IsoHeader.cpp index 1cd2516c..59c283c1 100644 --- a/CPP/7zip/Archive/Iso/IsoHeader.cpp +++ b/CPP/7zip/Archive/Iso/IsoHeader.cpp @@ -9,13 +9,4 @@ namespace NIso { const char *kElToritoSpec = "EL TORITO SPECIFICATION\0\0\0\0\0\0\0\0\0"; -const char *kMediaTypes[5] = -{ - "NoEmulation" - , "1.2M" - , "1.44M" - , "2.88M" - , "HardDisk" -}; - }} diff --git a/CPP/7zip/Archive/Iso/IsoHeader.h b/CPP/7zip/Archive/Iso/IsoHeader.h index ce21b0ff..db0b1df9 100644 --- a/CPP/7zip/Archive/Iso/IsoHeader.h +++ b/CPP/7zip/Archive/Iso/IsoHeader.h @@ -34,6 +34,11 @@ namespace NBootEntryId const Byte kValidationEntry = 1; const Byte kInitialEntryNotBootable = 0; const Byte kInitialEntryBootable = 0x88; + + const Byte kMoreHeaders = 0x90; + const Byte kFinalHeader = 0x91; + + const Byte kExtensionIndicator = 0x44; } namespace NBootPlatformId @@ -54,9 +59,6 @@ namespace NBootMediaType const Byte kHardDisk = 4; } -const unsigned kNumBootMediaTypes = 5; -extern const char *kMediaTypes[]; - }} #endif diff --git a/CPP/7zip/Archive/Iso/IsoIn.cpp b/CPP/7zip/Archive/Iso/IsoIn.cpp index ba12acae..b72e8687 100644 --- a/CPP/7zip/Archive/Iso/IsoIn.cpp +++ b/CPP/7zip/Archive/Iso/IsoIn.cpp @@ -2,6 +2,8 @@ #include "StdAfx.h" +#include "../../../../C/CpuArch.h" + #include "../../../Common/MyException.h" #include "../../Common/StreamUtils.h" @@ -10,11 +12,78 @@ namespace NArchive { namespace NIso { - + struct CUnexpectedEndException {}; struct CHeaderErrorException {}; struct CEndianErrorException {}; +static const char * const kMediaTypes[] = +{ + "NoEmul" + , "1.2M" + , "1.44M" + , "2.88M" + , "HardDisk" +}; + +bool CBootInitialEntry::Parse(const Byte *p) +{ + Bootable = (p[0] == NBootEntryId::kInitialEntryBootable); + BootMediaType = p[1]; + LoadSegment = GetUi16(p + 2); + SystemType = p[4]; + SectorCount = GetUi16(p + 6); + LoadRBA = GetUi32(p + 8); + memcpy(VendorSpec, p + 12, 20); + if (p[5] != 0) + return false; + if (p[0] != NBootEntryId::kInitialEntryBootable + && p[0] != NBootEntryId::kInitialEntryNotBootable) + return false; + return true; +} + +AString CBootInitialEntry::GetName() const +{ + AString s = (Bootable ? "Boot" : "NotBoot"); + s += '-'; + + if (BootMediaType < ARRAY_SIZE(kMediaTypes)) + s += kMediaTypes[BootMediaType]; + else + { + char name[16]; + ConvertUInt32ToString(BootMediaType, name); + s += name; + } + + if (VendorSpec[0] == 1) + { + // "Language and Version Information (IBM)" + + unsigned i; + for (i = 1; i < sizeof(VendorSpec); i++) + if (VendorSpec[i] > 0x7F) + break; + if (i == sizeof(VendorSpec)) + { + s += '-'; + for (i = 1; i < sizeof(VendorSpec); i++) + { + char c = VendorSpec[i]; + if (c == 0) + break; + if (c == '\\' || c == '/') + c = '_'; + s += c; + } + } + } + + s += ".img"; + return s; +} + Byte CInArchive::ReadByte() { if (m_BufferPos >= BlockSize) @@ -58,15 +127,6 @@ void CInArchive::SkipZeros(size_t size) } } -UInt16 CInArchive::ReadUInt16Spec() -{ - UInt16 val = 0; - for (int i = 0; i < 2; i++) - val |= ((UInt16)(ReadByte()) << (8 * i)); - return val; -} - - UInt16 CInArchive::ReadUInt16() { Byte b[4]; @@ -179,15 +239,15 @@ void CInArchive::ReadDirRecord2(CDirRecord &r, Byte len) Byte idLen = ReadByte(); r.FileId.Alloc(idLen); ReadBytes((Byte *)r.FileId, idLen); - int padSize = 1 - (idLen & 1); + unsigned padSize = 1 - (idLen & 1); - // SkipZeros(1 - (idLen & 1)); - Skip(1 - (idLen & 1)); // it's bug in some cd's. Must be zeros + // SkipZeros(padSize); + Skip(padSize); // it's bug in some cd's. Must be zeros - int curPos = 33 + idLen + padSize; + unsigned curPos = 33 + idLen + padSize; if (curPos > len) throw CHeaderErrorException(); - int rem = len - curPos; + unsigned rem = len - curPos; r.SystemUse.Alloc(rem); ReadBytes((Byte *)r.SystemUse, rem); } @@ -349,45 +409,94 @@ void CInArchive::ReadBootInfo() { if (!_bootIsDefined) return; + HeadersError = true; + 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); + UInt32 blockIndex = GetUi32(_bootDesc.BootSystemUse); SeekToBlock(blockIndex); - Byte b = ReadByte(); - if (b != NBootEntryId::kValidationEntry) + + Byte buf[32]; + ReadBytes(buf, 32); + + if (buf[0] != NBootEntryId::kValidationEntry + || buf[2] != 0 + || buf[3] != 0 + || buf[30] != 0x55 + || buf[31] != 0xAA) return; + { + UInt32 sum = 0; + for (unsigned i = 0; i < 32; i += 2) + sum += GetUi16(buf + i); + if ((sum & 0xFFFF) != 0) + return; + /* CBootValidationEntry e; - e.PlatformId = ReadByte(); - if (ReadUInt16Spec() != 0) - throw CHeaderErrorException(); - ReadBytes(e.Id, sizeof(e.Id)); - /* UInt16 checkSum = */ ReadUInt16Spec(); - if (ReadByte() != 0x55) - throw CHeaderErrorException(); - if (ReadByte() != 0xAA) - throw CHeaderErrorException(); + e.PlatformId = buf[1]; + memcpy(e.Id, buf + 4, sizeof(e.Id)); + // UInt16 checkSum = GetUi16(p + 28); + */ } - b = ReadByte(); - if (b == NBootEntryId::kInitialEntryBootable || b == NBootEntryId::kInitialEntryNotBootable) + + ReadBytes(buf, 32); { CBootInitialEntry e; - e.Bootable = (b == NBootEntryId::kInitialEntryBootable); - e.BootMediaType = ReadByte(); - e.LoadSegment = ReadUInt16Spec(); - e.SystemType = ReadByte(); - if (ReadByte() != 0) - throw CHeaderErrorException(); - e.SectorCount = ReadUInt16Spec(); - e.LoadRBA = ReadUInt32Le(); - if (ReadByte() != 0) - throw CHeaderErrorException(); + if (!e.Parse(buf)) + return; BootEntries.Add(e); } - else - return; + + bool error = false; + + for (;;) + { + ReadBytes(buf, 32); + Byte headerIndicator = buf[0]; + if (headerIndicator != NBootEntryId::kMoreHeaders + && headerIndicator != NBootEntryId::kFinalHeader) + break; + + // Section Header + // Byte platform = p[1]; + unsigned numEntries = GetUi16(buf + 2); + // id[28] + + for (unsigned i = 0; i < numEntries; i++) + { + ReadBytes(buf, 32); + CBootInitialEntry e; + if (!e.Parse(buf)) + { + error = true; + break; + } + if (e.BootMediaType & (1 << 5)) + { + // Section entry extension + for (unsigned j = 0;; j++) + { + ReadBytes(buf, 32); + if (j > 32 || buf[0] != NBootEntryId::kExtensionIndicator) + { + error = true; + break; + } + if ((buf[1] & (1 << 5)) == 0) + break; + // info += (buf + 2, 30) + } + } + BootEntries.Add(e); + } + + if (headerIndicator != NBootEntryId::kMoreHeaders) + break; + } + + HeadersError = error; } HRESULT CInArchive::Open2() diff --git a/CPP/7zip/Archive/Iso/IsoIn.h b/CPP/7zip/Archive/Iso/IsoIn.h index 614b3744..c2007bce 100644 --- a/CPP/7zip/Archive/Iso/IsoIn.h +++ b/CPP/7zip/Archive/Iso/IsoIn.h @@ -25,77 +25,92 @@ struct CDir: public CDirRecord _subItems.Clear(); } - unsigned GetLen(bool checkSusp, unsigned skipSize) const - { - unsigned len = GetLenCur(checkSusp, skipSize); - if (Parent != 0) - if (Parent->Parent != 0) - len += 1 + Parent->GetLen(checkSusp, skipSize); - return len; - } - - unsigned GetLenU() const - { - unsigned len = (unsigned)(FileId.Size() / 2); - if (Parent != 0) - if (Parent->Parent != 0) - len += 1 + Parent->GetLenU(); - return len; - } - AString GetPath(bool checkSusp, unsigned skipSize) const { AString s; - unsigned len = GetLen(checkSusp, skipSize); - char *p = s.GetBuffer(len); - p += len; - *p = 0; + + unsigned len = 0; const CDir *cur = this; + for (;;) { - unsigned curLen = cur->GetLenCur(checkSusp, skipSize); - p -= curLen; - memcpy(p, (const char *)(const Byte *)cur->GetNameCur(checkSusp, skipSize), curLen); + unsigned curLen; + cur->GetNameCur(checkSusp, skipSize, curLen); + len += curLen; cur = cur->Parent; - if (cur == 0) + if (!cur || !cur->Parent) break; - if (cur->Parent == 0) + len++; + } + + char *p = s.GetBuf_SetEnd(len) + len; + + cur = this; + + for (;;) + { + unsigned curLen; + const Byte *name = cur->GetNameCur(checkSusp, skipSize, curLen); + p -= curLen; + if (curLen != 0) + memcpy(p, name, curLen); + cur = cur->Parent; + if (!cur || !cur->Parent) break; p--; *p = CHAR_PATH_SEPARATOR; } - s.ReleaseBuffer(); + return s; } - UString GetPathU() const + void GetPathU(UString &s) const { - UString s; - unsigned len = GetLenU(); - wchar_t *p = s.GetBuffer(len); - p += len; - *p = 0; + s.Empty(); + + unsigned len = 0; const CDir *cur = this; + for (;;) { unsigned curLen = (unsigned)(cur->FileId.Size() / 2); - p -= curLen; - for (unsigned i = 0; i < curLen; i++) - { - Byte b0 = ((const Byte *)cur->FileId)[i * 2]; - Byte b1 = ((const Byte *)cur->FileId)[i * 2 + 1]; - p[i] = (wchar_t)(((wchar_t)b0 << 8) | b1); - } + const Byte *fid = cur->FileId; + + unsigned i; + for (i = 0; i < curLen; i++) + if (fid[i * 2] == 0 && fid[i * 2 + 1] == 0) + break; + len += i; cur = cur->Parent; - if (cur == 0) + if (!cur || !cur->Parent) break; - if (cur->Parent == 0) + len++; + } + + wchar_t *p = s.GetBuf_SetEnd(len) + len; + + cur = this; + + for (;;) + { + unsigned curLen = (unsigned)(cur->FileId.Size() / 2); + const Byte *fid = cur->FileId; + + unsigned i; + for (i = 0; i < curLen; i++) + if (fid[i * 2] == 0 && fid[i * 2 + 1] == 0) + break; + curLen = i; + + p -= curLen; + for (i = 0; i < curLen; i++) + p[i] = (wchar_t)(((wchar_t)fid[i * 2] << 8) | fid[i * 2 + 1]); + cur = cur->Parent; + if (!cur || !cur->Parent) break; p--; *p = WCHAR_PATH_SEPARATOR; } - s.ReleaseBuffer(); - return s; } }; @@ -109,6 +124,7 @@ struct CDateTime Byte Second; Byte Hundredths; signed char GmtOffset; // min intervals from -48 (West) to +52 (East) recorded. + bool NotSpecified() const { return Year == 0 && Month == 0 && Day == 0 && Hour == 0 && Minute == 0 && Second == 0 && GmtOffset == 0; } @@ -118,7 +134,7 @@ struct CDateTime bool res = NWindows::NTime::GetSecondsSince1601(Year, Month, Day, Hour, Minute, Second, value); if (res) { - value -= (UInt64)((Int64)GmtOffset * 15 * 60); + value -= (Int64)((Int32)GmtOffset * 15 * 60); value *= 10000000; } ft.dwLowDateTime = (DWORD)value; @@ -157,27 +173,16 @@ struct CBootInitialEntry UInt32 LoadRBA; // This is the start address of the virtual disk. CD’s use // Relative/Logical block addressing. - UInt64 GetSize() const + Byte VendorSpec[20]; + + UInt32 GetSize() const { // if (BootMediaType == NBootMediaType::k1d44Floppy) (1440 << 10); - return SectorCount * 512; + return (UInt32)SectorCount * 512; } - AString GetName() const - { - AString s = (Bootable ? "Bootable" : "NotBootable"); - s += '_'; - if (BootMediaType < kNumBootMediaTypes) - s += kMediaTypes[BootMediaType]; - else - { - char name[16]; - ConvertUInt32ToString(BootMediaType, name); - s += name; - } - s += ".img"; - return s; - } + bool Parse(const Byte *p); + AString GetName() const; }; struct CVolumeDescriptor @@ -247,7 +252,6 @@ class CInArchive void SkipZeros(size_t size); Byte ReadByte(); void ReadBytes(Byte *data, UInt32 size); - UInt16 ReadUInt16Spec(); UInt16 ReadUInt16(); UInt32 ReadUInt32Le(); UInt32 ReadUInt32Be(); diff --git a/CPP/7zip/Archive/Iso/IsoItem.h b/CPP/7zip/Archive/Iso/IsoItem.h index b6ae21b7..2603afdb 100644 --- a/CPP/7zip/Archive/Iso/IsoItem.h +++ b/CPP/7zip/Archive/Iso/IsoItem.h @@ -29,7 +29,7 @@ struct CRecordingDateTime bool res = NWindows::NTime::GetSecondsSince1601(Year + 1900, Month, Day, Hour, Minute, Second, value); if (res) { - value -= (UInt64)((Int64)GmtOffset * 15 * 60); + value -= (Int64)((Int32)GmtOffset * 15 * 60); value *= 10000000; } ft.dwLowDateTime = (DWORD)value; @@ -94,28 +94,23 @@ struct CDirRecord return 0; } - unsigned GetLenCur(bool checkSusp, int skipSize) const + const Byte* GetNameCur(bool checkSusp, int skipSize, unsigned &nameLenRes) const { + const Byte *res = NULL; + unsigned len = 0; if (checkSusp) + res = FindSuspName(skipSize, len); + if (!res) { - unsigned len; - const Byte *res = FindSuspName(skipSize, len); - if (res != 0) - return len; + res = (const Byte *)FileId; + len = (unsigned)FileId.Size(); } - return (unsigned)FileId.Size(); - } - - const Byte* GetNameCur(bool checkSusp, int skipSize) const - { - if (checkSusp) - { - unsigned len; - const Byte *res = FindSuspName(skipSize, len); - if (res != 0) - return res; - } - return (const Byte *)FileId; + unsigned i; + for (i = 0; i < len; i++) + if (res[i] == 0) + break; + nameLenRes = i; + return res; } diff --git a/CPP/7zip/Archive/Iso/IsoRegister.cpp b/CPP/7zip/Archive/Iso/IsoRegister.cpp index c6f4a521..0205238d 100644 --- a/CPP/7zip/Archive/Iso/IsoRegister.cpp +++ b/CPP/7zip/Archive/Iso/IsoRegister.cpp @@ -9,15 +9,13 @@ namespace NArchive { namespace NIso { -IMP_CreateArcIn +static const Byte k_Signature[] = { 'C', 'D', '0', '0', '1' }; -static CArcInfo g_ArcInfo = - { "Iso", "iso img", 0, 0xE7, - 5, { 'C', 'D', '0', '0', '1' }, +REGISTER_ARC_I( + "Iso", "iso img", 0, 0xE7, + k_Signature, NArchive::NIso::kStartPos + 1, 0, - CreateArc }; - -REGISTER_ARC(Iso) + NULL) }} |