// Archive/IsoIn.h #ifndef __ARCHIVE_ISO_IN_H #define __ARCHIVE_ISO_IN_H #include "../../../Common/IntToString.h" #include "../../../Common/MyCom.h" #include "../../IStream.h" #include "IsoHeader.h" #include "IsoItem.h" namespace NArchive { namespace NIso { struct CDir: public CDirRecord { CDir *Parent; CObjectVector _subItems; void Clear() { Parent = 0; _subItems.Clear(); } AString GetPath(bool checkSusp, unsigned skipSize) const { AString s; unsigned len = 0; const CDir *cur = this; for (;;) { unsigned curLen; cur->GetNameCur(checkSusp, skipSize, curLen); len += curLen; cur = cur->Parent; if (!cur || !cur->Parent) break; 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; } return s; } void GetPathU(UString &s) const { s.Empty(); unsigned len = 0; const CDir *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; len += i; cur = cur->Parent; if (!cur || !cur->Parent) break; 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; } } }; struct CDateTime { UInt16 Year; Byte Month; Byte Day; Byte Hour; Byte Minute; 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; } bool GetFileTime(FILETIME &ft) const { UInt64 value; bool res = NWindows::NTime::GetSecondsSince1601(Year, Month, Day, Hour, Minute, Second, value); if (res) { value -= (Int64)((Int32)GmtOffset * 15 * 60); value *= 10000000; } ft.dwLowDateTime = (DWORD)value; ft.dwHighDateTime = (DWORD)(value >> 32); return res; } }; struct CBootRecordDescriptor { Byte BootSystemId[32]; // a-characters Byte BootId[32]; // a-characters Byte BootSystemUse[1977]; }; struct CBootValidationEntry { Byte PlatformId; Byte Id[24]; // to identify the manufacturer/developer of the CD-ROM. }; struct CBootInitialEntry { bool Bootable; Byte BootMediaType; UInt16 LoadSegment; /* This is the load segment for the initial boot image. If this value is 0 the system will use the traditional segment of 7C0. If this value is non-zero the system will use the specified segment. This applies to x86 architectures only. For "flat" model architectures (such as Motorola) this is the address divided by 10. */ Byte SystemType; // This must be a copy of byte 5 (System Type) from the // Partition Table found in the boot image. UInt16 SectorCount; // This is the number of virtual/emulated sectors the system // will store at Load Segment during the initial boot procedure. UInt32 LoadRBA; // This is the start address of the virtual disk. CDs use // Relative/Logical block addressing. Byte VendorSpec[20]; UInt32 GetSize() const { // if (BootMediaType == NBootMediaType::k1d44Floppy) (1440 << 10); return (UInt32)SectorCount * 512; } bool Parse(const Byte *p); AString GetName() const; }; struct CVolumeDescriptor { Byte VolFlags; Byte SystemId[32]; // a-characters. An identification of a system // which can recognize and act upon the content of the Logical // Sectors with logical Sector Numbers 0 to 15 of the volume. Byte VolumeId[32]; // d-characters. An identification of the volume. UInt32 VolumeSpaceSize; // the number of Logical Blocks in which the Volume Space of the volume is recorded Byte EscapeSequence[32]; UInt16 VolumeSetSize; UInt16 VolumeSequenceNumber; // the ordinal number of the volume in the Volume Set of which the volume is a member. UInt16 LogicalBlockSize; UInt32 PathTableSize; UInt32 LPathTableLocation; UInt32 LOptionalPathTableLocation; UInt32 MPathTableLocation; UInt32 MOptionalPathTableLocation; CDirRecord RootDirRecord; Byte VolumeSetId[128]; Byte PublisherId[128]; Byte DataPreparerId[128]; Byte ApplicationId[128]; Byte CopyrightFileId[37]; Byte AbstractFileId[37]; Byte BibFileId[37]; CDateTime CTime; CDateTime MTime; CDateTime ExpirationTime; CDateTime EffectiveTime; Byte FileStructureVersion; // = 1; Byte ApplicationUse[512]; bool IsJoliet() const { if ((VolFlags & 1) != 0) return false; Byte b = EscapeSequence[2]; return (EscapeSequence[0] == 0x25 && EscapeSequence[1] == 0x2F && (b == 0x40 || b == 0x43 || b == 0x45)); } }; struct CRef { const CDir *Dir; UInt32 Index; UInt32 NumExtents; UInt64 TotalSize; }; const UInt32 kBlockSize = 1 << 11; class CInArchive { IInStream *_stream; UInt64 _position; UInt32 m_BufferPos; CDir _rootDir; bool _bootIsDefined; CBootRecordDescriptor _bootDesc; void Skip(size_t size); void SkipZeros(size_t size); Byte ReadByte(); void ReadBytes(Byte *data, UInt32 size); UInt16 ReadUInt16(); UInt32 ReadUInt32Le(); UInt32 ReadUInt32Be(); UInt32 ReadUInt32(); UInt64 ReadUInt64(); UInt32 ReadDigits(int numDigits); void ReadDateTime(CDateTime &d); void ReadRecordingDateTime(CRecordingDateTime &t); void ReadDirRecord2(CDirRecord &r, Byte len); void ReadDirRecord(CDirRecord &r); void ReadBootRecordDescriptor(CBootRecordDescriptor &d); void ReadVolumeDescriptor(CVolumeDescriptor &d); void SeekToBlock(UInt32 blockIndex); void ReadDir(CDir &d, int level); void CreateRefs(CDir &d); void ReadBootInfo(); HRESULT Open2(); public: HRESULT Open(IInStream *inStream); void Clear(); UInt64 _fileSize; UInt64 PhySize; CRecordVector Refs; CObjectVector VolDescs; int MainVolDescIndex; // UInt32 BlockSize; CObjectVector BootEntries; bool IsArc; bool UnexpectedEnd; bool HeadersError; bool IncorrectBigEndian; bool TooDeepDirs; bool SelfLinkedDirs; CRecordVector UniqStartLocations; Byte m_Buffer[kBlockSize]; void UpdatePhySize(UInt32 blockIndex, UInt64 size) { const UInt64 alignedSize = (size + kBlockSize - 1) & ~((UInt64)kBlockSize - 1); const UInt64 end = (UInt64)blockIndex * kBlockSize + alignedSize; if (PhySize < end) PhySize = end; } bool IsJoliet() const { return VolDescs[MainVolDescIndex].IsJoliet(); } UInt64 GetBootItemSize(int index) const { const CBootInitialEntry &be = BootEntries[index]; UInt64 size = be.GetSize(); if (be.BootMediaType == NBootMediaType::k1d2Floppy) size = (1200 << 10); else if (be.BootMediaType == NBootMediaType::k1d44Floppy) size = (1440 << 10); else if (be.BootMediaType == NBootMediaType::k2d88Floppy) size = (2880 << 10); UInt64 startPos = (UInt64)be.LoadRBA * kBlockSize; if (startPos < _fileSize) { if (_fileSize - startPos < size) size = _fileSize - startPos; } return size; } bool IsSusp; unsigned SuspSkipSize; }; }} #endif