1 // Archive/IsoIn.h 2 3 #ifndef __ARCHIVE_ISO_IN_H 4 #define __ARCHIVE_ISO_IN_H 5 6 #include "../../../Common/MyCom.h" 7 8 #include "../../IStream.h" 9 10 #include "IsoHeader.h" 11 #include "IsoItem.h" 12 13 namespace NArchive { 14 namespace NIso { 15 16 struct CDir: public CDirRecord 17 { 18 CDir *Parent; 19 CObjectVector<CDir> _subItems; 20 ClearCDir21 void Clear() 22 { 23 Parent = 0; 24 _subItems.Clear(); 25 } 26 GetPathCDir27 AString GetPath(bool checkSusp, unsigned skipSize) const 28 { 29 AString s; 30 31 unsigned len = 0; 32 const CDir *cur = this; 33 34 for (;;) 35 { 36 unsigned curLen; 37 cur->GetNameCur(checkSusp, skipSize, curLen); 38 len += curLen; 39 cur = cur->Parent; 40 if (!cur || !cur->Parent) 41 break; 42 len++; 43 } 44 45 char *p = s.GetBuf_SetEnd(len) + len; 46 47 cur = this; 48 49 for (;;) 50 { 51 unsigned curLen; 52 const Byte *name = cur->GetNameCur(checkSusp, skipSize, curLen); 53 p -= curLen; 54 if (curLen != 0) 55 memcpy(p, name, curLen); 56 cur = cur->Parent; 57 if (!cur || !cur->Parent) 58 break; 59 p--; 60 *p = CHAR_PATH_SEPARATOR; 61 } 62 63 return s; 64 } 65 GetPathUCDir66 void GetPathU(UString &s) const 67 { 68 s.Empty(); 69 70 unsigned len = 0; 71 const CDir *cur = this; 72 73 for (;;) 74 { 75 unsigned curLen = (unsigned)(cur->FileId.Size() / 2); 76 const Byte *fid = cur->FileId; 77 78 unsigned i; 79 for (i = 0; i < curLen; i++) 80 if (fid[i * 2] == 0 && fid[i * 2 + 1] == 0) 81 break; 82 len += i; 83 cur = cur->Parent; 84 if (!cur || !cur->Parent) 85 break; 86 len++; 87 } 88 89 wchar_t *p = s.GetBuf_SetEnd(len) + len; 90 91 cur = this; 92 93 for (;;) 94 { 95 unsigned curLen = (unsigned)(cur->FileId.Size() / 2); 96 const Byte *fid = cur->FileId; 97 98 unsigned i; 99 for (i = 0; i < curLen; i++) 100 if (fid[i * 2] == 0 && fid[i * 2 + 1] == 0) 101 break; 102 curLen = i; 103 104 p -= curLen; 105 for (i = 0; i < curLen; i++) 106 p[i] = (wchar_t)(((wchar_t)fid[i * 2] << 8) | fid[i * 2 + 1]); 107 cur = cur->Parent; 108 if (!cur || !cur->Parent) 109 break; 110 p--; 111 *p = WCHAR_PATH_SEPARATOR; 112 } 113 } 114 }; 115 116 struct CDateTime 117 { 118 UInt16 Year; 119 Byte Month; 120 Byte Day; 121 Byte Hour; 122 Byte Minute; 123 Byte Second; 124 Byte Hundredths; 125 signed char GmtOffset; // min intervals from -48 (West) to +52 (East) recorded. 126 NotSpecifiedCDateTime127 bool NotSpecified() const { return Year == 0 && Month == 0 && Day == 0 && 128 Hour == 0 && Minute == 0 && Second == 0 && GmtOffset == 0; } 129 GetFileTimeCDateTime130 bool GetFileTime(FILETIME &ft) const 131 { 132 UInt64 value; 133 bool res = NWindows::NTime::GetSecondsSince1601(Year, Month, Day, Hour, Minute, Second, value); 134 if (res) 135 { 136 value -= (Int64)((Int32)GmtOffset * 15 * 60); 137 value *= 10000000; 138 } 139 ft.dwLowDateTime = (DWORD)value; 140 ft.dwHighDateTime = (DWORD)(value >> 32); 141 return res; 142 } 143 }; 144 145 struct CBootRecordDescriptor 146 { 147 Byte BootSystemId[32]; // a-characters 148 Byte BootId[32]; // a-characters 149 Byte BootSystemUse[1977]; 150 }; 151 152 struct CBootValidationEntry 153 { 154 Byte PlatformId; 155 Byte Id[24]; // to identify the manufacturer/developer of the CD-ROM. 156 }; 157 158 struct CBootInitialEntry 159 { 160 bool Bootable; 161 Byte BootMediaType; 162 UInt16 LoadSegment; 163 /* This is the load segment for the initial boot image. If this 164 value is 0 the system will use the traditional segment of 7C0. If this value 165 is non-zero the system will use the specified segment. This applies to x86 166 architectures only. For "flat" model architectures (such as Motorola) this 167 is the address divided by 10. */ 168 Byte SystemType; // This must be a copy of byte 5 (System Type) from the 169 // Partition Table found in the boot image. 170 UInt16 SectorCount; // This is the number of virtual/emulated sectors the system 171 // will store at Load Segment during the initial boot procedure. 172 UInt32 LoadRBA; // This is the start address of the virtual disk. CDs use 173 // Relative/Logical block addressing. 174 175 Byte VendorSpec[20]; 176 GetSizeCBootInitialEntry177 UInt32 GetSize() const 178 { 179 // if (BootMediaType == NBootMediaType::k1d44Floppy) (1440 << 10); 180 return (UInt32)SectorCount * 512; 181 } 182 183 bool Parse(const Byte *p); 184 AString GetName() const; 185 }; 186 187 struct CVolumeDescriptor 188 { 189 Byte VolFlags; 190 Byte SystemId[32]; // a-characters. An identification of a system 191 // which can recognize and act upon the content of the Logical 192 // Sectors with logical Sector Numbers 0 to 15 of the volume. 193 Byte VolumeId[32]; // d-characters. An identification of the volume. 194 UInt32 VolumeSpaceSize; // the number of Logical Blocks in which the Volume Space of the volume is recorded 195 Byte EscapeSequence[32]; 196 UInt16 VolumeSetSize; 197 UInt16 VolumeSequenceNumber; // the ordinal number of the volume in the Volume Set of which the volume is a member. 198 UInt16 LogicalBlockSize; 199 UInt32 PathTableSize; 200 UInt32 LPathTableLocation; 201 UInt32 LOptionalPathTableLocation; 202 UInt32 MPathTableLocation; 203 UInt32 MOptionalPathTableLocation; 204 CDirRecord RootDirRecord; 205 Byte VolumeSetId[128]; 206 Byte PublisherId[128]; 207 Byte DataPreparerId[128]; 208 Byte ApplicationId[128]; 209 Byte CopyrightFileId[37]; 210 Byte AbstractFileId[37]; 211 Byte BibFileId[37]; 212 CDateTime CTime; 213 CDateTime MTime; 214 CDateTime ExpirationTime; 215 CDateTime EffectiveTime; 216 Byte FileStructureVersion; // = 1; 217 Byte ApplicationUse[512]; 218 IsJolietCVolumeDescriptor219 bool IsJoliet() const 220 { 221 if ((VolFlags & 1) != 0) 222 return false; 223 Byte b = EscapeSequence[2]; 224 return (EscapeSequence[0] == 0x25 && EscapeSequence[1] == 0x2F && 225 (b == 0x40 || b == 0x43 || b == 0x45)); 226 } 227 }; 228 229 struct CRef 230 { 231 const CDir *Dir; 232 UInt32 Index; 233 UInt32 NumExtents; 234 UInt64 TotalSize; 235 }; 236 237 const UInt32 kBlockSize = 1 << 11; 238 239 class CInArchive 240 { 241 IInStream *_stream; 242 UInt64 _position; 243 244 UInt32 m_BufferPos; 245 246 CDir _rootDir; 247 bool _bootIsDefined; 248 CBootRecordDescriptor _bootDesc; 249 250 void Skip(size_t size); 251 void SkipZeros(size_t size); 252 Byte ReadByte(); 253 void ReadBytes(Byte *data, UInt32 size); 254 UInt16 ReadUInt16(); 255 UInt32 ReadUInt32Le(); 256 UInt32 ReadUInt32Be(); 257 UInt32 ReadUInt32(); 258 UInt64 ReadUInt64(); 259 UInt32 ReadDigits(int numDigits); 260 void ReadDateTime(CDateTime &d); 261 void ReadRecordingDateTime(CRecordingDateTime &t); 262 void ReadDirRecord2(CDirRecord &r, Byte len); 263 void ReadDirRecord(CDirRecord &r); 264 265 void ReadBootRecordDescriptor(CBootRecordDescriptor &d); 266 void ReadVolumeDescriptor(CVolumeDescriptor &d); 267 268 void SeekToBlock(UInt32 blockIndex); 269 void ReadDir(CDir &d, int level); 270 void CreateRefs(CDir &d); 271 272 void ReadBootInfo(); 273 HRESULT Open2(); 274 public: 275 HRESULT Open(IInStream *inStream); 276 void Clear(); 277 278 UInt64 _fileSize; 279 UInt64 PhySize; 280 281 CRecordVector<CRef> Refs; 282 CObjectVector<CVolumeDescriptor> VolDescs; 283 int MainVolDescIndex; 284 // UInt32 BlockSize; 285 CObjectVector<CBootInitialEntry> BootEntries; 286 287 bool IsArc; 288 bool UnexpectedEnd; 289 bool HeadersError; 290 bool IncorrectBigEndian; 291 bool TooDeepDirs; 292 bool SelfLinkedDirs; 293 CRecordVector<UInt32> UniqStartLocations; 294 295 Byte m_Buffer[kBlockSize]; 296 UpdatePhySize(UInt32 blockIndex,UInt64 size)297 void UpdatePhySize(UInt32 blockIndex, UInt64 size) 298 { 299 const UInt64 alignedSize = (size + kBlockSize - 1) & ~((UInt64)kBlockSize - 1); 300 const UInt64 end = (UInt64)blockIndex * kBlockSize + alignedSize; 301 if (PhySize < end) 302 PhySize = end; 303 } 304 IsJoliet()305 bool IsJoliet() const { return VolDescs[MainVolDescIndex].IsJoliet(); } 306 GetBootItemSize(int index)307 UInt64 GetBootItemSize(int index) const 308 { 309 const CBootInitialEntry &be = BootEntries[index]; 310 UInt64 size = be.GetSize(); 311 if (be.BootMediaType == NBootMediaType::k1d2Floppy) 312 size = (1200 << 10); 313 else if (be.BootMediaType == NBootMediaType::k1d44Floppy) 314 size = (1440 << 10); 315 else if (be.BootMediaType == NBootMediaType::k2d88Floppy) 316 size = (2880 << 10); 317 UInt64 startPos = (UInt64)be.LoadRBA * kBlockSize; 318 if (startPos < _fileSize) 319 { 320 if (_fileSize - startPos < size) 321 size = _fileSize - startPos; 322 } 323 return size; 324 } 325 326 bool IsSusp; 327 unsigned SuspSkipSize; 328 }; 329 330 }} 331 332 #endif 333