1 // Archive/IsoIn.h 2 3 #ifndef ZIP7_INC_ARCHIVE_ISO_IN_H 4 #define ZIP7_INC_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 = NULL; 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(NWindows::NCOM::CPropVariant &prop) const 131 { 132 UInt64 v; 133 const bool res = NWindows::NTime::GetSecondsSince1601(Year, Month, Day, Hour, Minute, Second, v); 134 if (res) 135 { 136 v = (UInt64)((Int64)v - (Int64)((Int32)GmtOffset * 15 * 60)); 137 v *= 10000000; 138 if (Hundredths < 100) 139 v += (UInt32)Hundredths * 100000; 140 prop.SetAsTimeFrom_Ft64_Prec(v, k_PropVar_TimePrec_Base + 2); 141 } 142 return res; 143 } 144 }; 145 146 struct CBootRecordDescriptor 147 { 148 Byte BootSystemId[32]; // a-characters 149 Byte BootId[32]; // a-characters 150 Byte BootSystemUse[1977]; 151 }; 152 153 struct CBootValidationEntry 154 { 155 Byte PlatformId; 156 Byte Id[24]; // to identify the manufacturer/developer of the CD-ROM. 157 }; 158 159 struct CBootInitialEntry 160 { 161 bool Bootable; 162 Byte BootMediaType; 163 UInt16 LoadSegment; 164 /* This is the load segment for the initial boot image. If this 165 value is 0 the system will use the traditional segment of 7C0. If this value 166 is non-zero the system will use the specified segment. This applies to x86 167 architectures only. For "flat" model architectures (such as Motorola) this 168 is the address divided by 10. */ 169 Byte SystemType; // This must be a copy of byte 5 (System Type) from the 170 // Partition Table found in the boot image. 171 UInt16 SectorCount; // This is the number of virtual/emulated sectors the system 172 // will store at Load Segment during the initial boot procedure. 173 UInt32 LoadRBA; // This is the start address of the virtual disk. CDs use 174 // Relative/Logical block addressing. 175 176 Byte VendorSpec[20]; 177 GetSizeCBootInitialEntry178 UInt32 GetSize() const 179 { 180 // if (BootMediaType == NBootMediaType::k1d44Floppy) (1440 << 10); 181 return (UInt32)SectorCount * 512; 182 } 183 184 bool Parse(const Byte *p); 185 AString GetName() const; 186 }; 187 188 struct CVolumeDescriptor 189 { 190 Byte VolFlags; 191 Byte SystemId[32]; // a-characters. An identification of a system 192 // which can recognize and act upon the content of the Logical 193 // Sectors with logical Sector Numbers 0 to 15 of the volume. 194 Byte VolumeId[32]; // d-characters. An identification of the volume. 195 UInt32 VolumeSpaceSize; // the number of Logical Blocks in which the Volume Space of the volume is recorded 196 Byte EscapeSequence[32]; 197 UInt16 VolumeSetSize; 198 UInt16 VolumeSequenceNumber; // the ordinal number of the volume in the Volume Set of which the volume is a member. 199 UInt16 LogicalBlockSize; 200 UInt32 PathTableSize; 201 UInt32 LPathTableLocation; 202 UInt32 LOptionalPathTableLocation; 203 UInt32 MPathTableLocation; 204 UInt32 MOptionalPathTableLocation; 205 CDirRecord RootDirRecord; 206 Byte VolumeSetId[128]; 207 Byte PublisherId[128]; 208 Byte DataPreparerId[128]; 209 Byte ApplicationId[128]; 210 Byte CopyrightFileId[37]; 211 Byte AbstractFileId[37]; 212 Byte BibFileId[37]; 213 CDateTime CTime; 214 CDateTime MTime; 215 CDateTime ExpirationTime; 216 CDateTime EffectiveTime; 217 // Byte FileStructureVersion; // = 1; 218 Byte ApplicationUse[512]; 219 IsJolietCVolumeDescriptor220 bool IsJoliet() const 221 { 222 if ((VolFlags & 1) != 0) 223 return false; 224 const Byte b = EscapeSequence[2]; 225 return (EscapeSequence[0] == 0x25 && EscapeSequence[1] == 0x2F && 226 (b == 0x40 || b == 0x43 || b == 0x45)); 227 } 228 Get_VolumeSpaceSize_inBytesCVolumeDescriptor229 UInt64 Get_VolumeSpaceSize_inBytes() const { return (UInt64)VolumeSpaceSize * LogicalBlockSize; } 230 }; 231 232 struct CRef 233 { 234 const CDir *Dir; 235 UInt32 Index; 236 UInt32 NumExtents; 237 UInt64 TotalSize; 238 }; 239 240 const UInt32 kBlockSize = 1 << 11; 241 242 class CInArchive 243 { 244 IInStream *_stream; 245 UInt64 _position; 246 247 UInt32 m_BufferPos; 248 249 void Skip(size_t size); 250 void SkipZeros(size_t size); 251 Byte ReadByte(); 252 void ReadBytes(Byte *data, UInt32 size); 253 UInt16 ReadUInt16(); 254 UInt32 ReadUInt32Le(); 255 UInt32 ReadUInt32Be(); 256 UInt32 ReadUInt32(); 257 UInt64 ReadUInt64(); 258 UInt32 ReadDigits(int numDigits); 259 void ReadDateTime(CDateTime &d); 260 void ReadRecordingDateTime(CRecordingDateTime &t); 261 void ReadDirRecord2(CDirRecord &r, Byte len); 262 void ReadDirRecord(CDirRecord &r); 263 264 void ReadBootRecordDescriptor(CBootRecordDescriptor &d); 265 void ReadVolumeDescriptor(CVolumeDescriptor &d); 266 267 void SeekToBlock(UInt32 blockIndex); 268 void ReadDir(CDir &d, int level); 269 void CreateRefs(CDir &d); 270 271 void ReadBootInfo(); 272 HRESULT Open2(); 273 public: 274 HRESULT Open(IInStream *inStream); 275 void Clear(); 276 277 UInt64 _fileSize; 278 UInt64 PhySize; 279 280 CRecordVector<CRef> Refs; 281 CObjectVector<CVolumeDescriptor> VolDescs; 282 int MainVolDescIndex; 283 // UInt32 BlockSize; 284 CObjectVector<CBootInitialEntry> BootEntries; 285 286 private: 287 bool _bootIsDefined; 288 public: 289 bool IsArc; 290 bool UnexpectedEnd; 291 bool HeadersError; 292 bool IncorrectBigEndian; 293 bool TooDeepDirs; 294 bool SelfLinkedDirs; 295 bool IsSusp; 296 unsigned SuspSkipSize; 297 298 int _expand_BootEntries_index; 299 300 CRecordVector<UInt32> UniqStartLocations; 301 UpdatePhySize(const UInt32 blockIndex,const UInt64 size)302 void UpdatePhySize(const UInt32 blockIndex, const UInt64 size) 303 { 304 const UInt64 alignedSize = (size + kBlockSize - 1) & ~((UInt64)kBlockSize - 1); 305 const UInt64 end = (UInt64)blockIndex * kBlockSize + alignedSize; 306 if (PhySize < end) 307 PhySize = end; 308 } 309 IsJoliet()310 bool IsJoliet() const { return VolDescs[MainVolDescIndex].IsJoliet(); } 311 312 UInt64 GetBootItemSize(unsigned index) const; 313 314 private: 315 CDir _rootDir; 316 Byte m_Buffer[kBlockSize]; 317 CBootRecordDescriptor _bootDesc; 318 }; 319 320 }} 321 322 #endif 323