xref: /aosp_15_r20/external/lzma/CPP/7zip/Archive/Iso/IsoIn.cpp (revision f6dc9357d832569d4d1f5d24eacdb3935a1ae8e6)
1*f6dc9357SAndroid Build Coastguard Worker // Archive/IsoIn.cpp
2*f6dc9357SAndroid Build Coastguard Worker 
3*f6dc9357SAndroid Build Coastguard Worker #include "StdAfx.h"
4*f6dc9357SAndroid Build Coastguard Worker 
5*f6dc9357SAndroid Build Coastguard Worker #include "../../../../C/CpuArch.h"
6*f6dc9357SAndroid Build Coastguard Worker 
7*f6dc9357SAndroid Build Coastguard Worker #include "../../../Common/MyException.h"
8*f6dc9357SAndroid Build Coastguard Worker 
9*f6dc9357SAndroid Build Coastguard Worker #include "../../Common/StreamUtils.h"
10*f6dc9357SAndroid Build Coastguard Worker 
11*f6dc9357SAndroid Build Coastguard Worker #include "../HandlerCont.h"
12*f6dc9357SAndroid Build Coastguard Worker 
13*f6dc9357SAndroid Build Coastguard Worker #include "IsoIn.h"
14*f6dc9357SAndroid Build Coastguard Worker 
15*f6dc9357SAndroid Build Coastguard Worker namespace NArchive {
16*f6dc9357SAndroid Build Coastguard Worker namespace NIso {
17*f6dc9357SAndroid Build Coastguard Worker 
18*f6dc9357SAndroid Build Coastguard Worker struct CUnexpectedEndException {};
19*f6dc9357SAndroid Build Coastguard Worker struct CHeaderErrorException {};
20*f6dc9357SAndroid Build Coastguard Worker struct CEndianErrorException {};
21*f6dc9357SAndroid Build Coastguard Worker 
22*f6dc9357SAndroid Build Coastguard Worker static const char * const kMediaTypes[] =
23*f6dc9357SAndroid Build Coastguard Worker {
24*f6dc9357SAndroid Build Coastguard Worker     "NoEmul"
25*f6dc9357SAndroid Build Coastguard Worker   , "1.2M"
26*f6dc9357SAndroid Build Coastguard Worker   , "1.44M"
27*f6dc9357SAndroid Build Coastguard Worker   , "2.88M"
28*f6dc9357SAndroid Build Coastguard Worker   , "HardDisk"
29*f6dc9357SAndroid Build Coastguard Worker };
30*f6dc9357SAndroid Build Coastguard Worker 
Parse(const Byte * p)31*f6dc9357SAndroid Build Coastguard Worker bool CBootInitialEntry::Parse(const Byte *p)
32*f6dc9357SAndroid Build Coastguard Worker {
33*f6dc9357SAndroid Build Coastguard Worker   Bootable = (p[0] == NBootEntryId::kInitialEntryBootable);
34*f6dc9357SAndroid Build Coastguard Worker   BootMediaType = p[1];
35*f6dc9357SAndroid Build Coastguard Worker   LoadSegment = GetUi16(p + 2);
36*f6dc9357SAndroid Build Coastguard Worker   SystemType = p[4];
37*f6dc9357SAndroid Build Coastguard Worker   SectorCount = GetUi16(p + 6);
38*f6dc9357SAndroid Build Coastguard Worker   LoadRBA = GetUi32(p + 8);
39*f6dc9357SAndroid Build Coastguard Worker   memcpy(VendorSpec, p + 12, 20);
40*f6dc9357SAndroid Build Coastguard Worker   if (p[5] != 0)
41*f6dc9357SAndroid Build Coastguard Worker     return false;
42*f6dc9357SAndroid Build Coastguard Worker   if (p[0] != NBootEntryId::kInitialEntryBootable
43*f6dc9357SAndroid Build Coastguard Worker       && p[0] != NBootEntryId::kInitialEntryNotBootable)
44*f6dc9357SAndroid Build Coastguard Worker     return false;
45*f6dc9357SAndroid Build Coastguard Worker   return true;
46*f6dc9357SAndroid Build Coastguard Worker }
47*f6dc9357SAndroid Build Coastguard Worker 
GetName() const48*f6dc9357SAndroid Build Coastguard Worker AString CBootInitialEntry::GetName() const
49*f6dc9357SAndroid Build Coastguard Worker {
50*f6dc9357SAndroid Build Coastguard Worker   AString s (Bootable ? "Boot" : "NotBoot");
51*f6dc9357SAndroid Build Coastguard Worker   s.Add_Minus();
52*f6dc9357SAndroid Build Coastguard Worker 
53*f6dc9357SAndroid Build Coastguard Worker   if (BootMediaType < Z7_ARRAY_SIZE(kMediaTypes))
54*f6dc9357SAndroid Build Coastguard Worker     s += kMediaTypes[BootMediaType];
55*f6dc9357SAndroid Build Coastguard Worker   else
56*f6dc9357SAndroid Build Coastguard Worker     s.Add_UInt32(BootMediaType);
57*f6dc9357SAndroid Build Coastguard Worker 
58*f6dc9357SAndroid Build Coastguard Worker   if (VendorSpec[0] == 1)
59*f6dc9357SAndroid Build Coastguard Worker   {
60*f6dc9357SAndroid Build Coastguard Worker     // "Language and Version Information (IBM)"
61*f6dc9357SAndroid Build Coastguard Worker 
62*f6dc9357SAndroid Build Coastguard Worker     unsigned i;
63*f6dc9357SAndroid Build Coastguard Worker     for (i = 1; i < sizeof(VendorSpec); i++)
64*f6dc9357SAndroid Build Coastguard Worker       if (VendorSpec[i] > 0x7F)
65*f6dc9357SAndroid Build Coastguard Worker         break;
66*f6dc9357SAndroid Build Coastguard Worker     if (i == sizeof(VendorSpec))
67*f6dc9357SAndroid Build Coastguard Worker     {
68*f6dc9357SAndroid Build Coastguard Worker       s.Add_Minus();
69*f6dc9357SAndroid Build Coastguard Worker       for (i = 1; i < sizeof(VendorSpec); i++)
70*f6dc9357SAndroid Build Coastguard Worker       {
71*f6dc9357SAndroid Build Coastguard Worker         char c = (char)VendorSpec[i];
72*f6dc9357SAndroid Build Coastguard Worker         if (c == 0)
73*f6dc9357SAndroid Build Coastguard Worker           break;
74*f6dc9357SAndroid Build Coastguard Worker         if (c == '\\' || c == '/')
75*f6dc9357SAndroid Build Coastguard Worker           c = '_';
76*f6dc9357SAndroid Build Coastguard Worker         s += c;
77*f6dc9357SAndroid Build Coastguard Worker       }
78*f6dc9357SAndroid Build Coastguard Worker     }
79*f6dc9357SAndroid Build Coastguard Worker   }
80*f6dc9357SAndroid Build Coastguard Worker 
81*f6dc9357SAndroid Build Coastguard Worker   s += ".img";
82*f6dc9357SAndroid Build Coastguard Worker   return s;
83*f6dc9357SAndroid Build Coastguard Worker }
84*f6dc9357SAndroid Build Coastguard Worker 
ReadByte()85*f6dc9357SAndroid Build Coastguard Worker Byte CInArchive::ReadByte()
86*f6dc9357SAndroid Build Coastguard Worker {
87*f6dc9357SAndroid Build Coastguard Worker   if (m_BufferPos >= kBlockSize)
88*f6dc9357SAndroid Build Coastguard Worker     m_BufferPos = 0;
89*f6dc9357SAndroid Build Coastguard Worker   if (m_BufferPos == 0)
90*f6dc9357SAndroid Build Coastguard Worker   {
91*f6dc9357SAndroid Build Coastguard Worker     size_t processed = kBlockSize;
92*f6dc9357SAndroid Build Coastguard Worker     HRESULT res = ReadStream(_stream, m_Buffer, &processed);
93*f6dc9357SAndroid Build Coastguard Worker     if (res != S_OK)
94*f6dc9357SAndroid Build Coastguard Worker       throw CSystemException(res);
95*f6dc9357SAndroid Build Coastguard Worker     if (processed != kBlockSize)
96*f6dc9357SAndroid Build Coastguard Worker       throw CUnexpectedEndException();
97*f6dc9357SAndroid Build Coastguard Worker     UInt64 end = _position + processed;
98*f6dc9357SAndroid Build Coastguard Worker     if (PhySize < end)
99*f6dc9357SAndroid Build Coastguard Worker       PhySize = end;
100*f6dc9357SAndroid Build Coastguard Worker   }
101*f6dc9357SAndroid Build Coastguard Worker   Byte b = m_Buffer[m_BufferPos++];
102*f6dc9357SAndroid Build Coastguard Worker   _position++;
103*f6dc9357SAndroid Build Coastguard Worker   return b;
104*f6dc9357SAndroid Build Coastguard Worker }
105*f6dc9357SAndroid Build Coastguard Worker 
ReadBytes(Byte * data,UInt32 size)106*f6dc9357SAndroid Build Coastguard Worker void CInArchive::ReadBytes(Byte *data, UInt32 size)
107*f6dc9357SAndroid Build Coastguard Worker {
108*f6dc9357SAndroid Build Coastguard Worker   for (UInt32 i = 0; i < size; i++)
109*f6dc9357SAndroid Build Coastguard Worker     data[i] = ReadByte();
110*f6dc9357SAndroid Build Coastguard Worker }
111*f6dc9357SAndroid Build Coastguard Worker 
Skip(size_t size)112*f6dc9357SAndroid Build Coastguard Worker void CInArchive::Skip(size_t size)
113*f6dc9357SAndroid Build Coastguard Worker {
114*f6dc9357SAndroid Build Coastguard Worker   while (size-- != 0)
115*f6dc9357SAndroid Build Coastguard Worker     ReadByte();
116*f6dc9357SAndroid Build Coastguard Worker }
117*f6dc9357SAndroid Build Coastguard Worker 
SkipZeros(size_t size)118*f6dc9357SAndroid Build Coastguard Worker void CInArchive::SkipZeros(size_t size)
119*f6dc9357SAndroid Build Coastguard Worker {
120*f6dc9357SAndroid Build Coastguard Worker   while (size-- != 0)
121*f6dc9357SAndroid Build Coastguard Worker   {
122*f6dc9357SAndroid Build Coastguard Worker     Byte b = ReadByte();
123*f6dc9357SAndroid Build Coastguard Worker     if (b != 0)
124*f6dc9357SAndroid Build Coastguard Worker       throw CHeaderErrorException();
125*f6dc9357SAndroid Build Coastguard Worker   }
126*f6dc9357SAndroid Build Coastguard Worker }
127*f6dc9357SAndroid Build Coastguard Worker 
ReadUInt16()128*f6dc9357SAndroid Build Coastguard Worker UInt16 CInArchive::ReadUInt16()
129*f6dc9357SAndroid Build Coastguard Worker {
130*f6dc9357SAndroid Build Coastguard Worker   Byte b[4];
131*f6dc9357SAndroid Build Coastguard Worker   ReadBytes(b, 4);
132*f6dc9357SAndroid Build Coastguard Worker   UInt32 val = 0;
133*f6dc9357SAndroid Build Coastguard Worker   for (int i = 0; i < 2; i++)
134*f6dc9357SAndroid Build Coastguard Worker   {
135*f6dc9357SAndroid Build Coastguard Worker     if (b[i] != b[3 - i])
136*f6dc9357SAndroid Build Coastguard Worker       IncorrectBigEndian = true;
137*f6dc9357SAndroid Build Coastguard Worker     val |= ((UInt32)(b[i]) << (8 * i));
138*f6dc9357SAndroid Build Coastguard Worker   }
139*f6dc9357SAndroid Build Coastguard Worker   return (UInt16)val;
140*f6dc9357SAndroid Build Coastguard Worker }
141*f6dc9357SAndroid Build Coastguard Worker 
ReadUInt32Le()142*f6dc9357SAndroid Build Coastguard Worker UInt32 CInArchive::ReadUInt32Le()
143*f6dc9357SAndroid Build Coastguard Worker {
144*f6dc9357SAndroid Build Coastguard Worker   UInt32 val = 0;
145*f6dc9357SAndroid Build Coastguard Worker   for (int i = 0; i < 4; i++)
146*f6dc9357SAndroid Build Coastguard Worker     val |= ((UInt32)(ReadByte()) << (8 * i));
147*f6dc9357SAndroid Build Coastguard Worker   return val;
148*f6dc9357SAndroid Build Coastguard Worker }
149*f6dc9357SAndroid Build Coastguard Worker 
ReadUInt32Be()150*f6dc9357SAndroid Build Coastguard Worker UInt32 CInArchive::ReadUInt32Be()
151*f6dc9357SAndroid Build Coastguard Worker {
152*f6dc9357SAndroid Build Coastguard Worker   UInt32 val = 0;
153*f6dc9357SAndroid Build Coastguard Worker   for (int i = 0; i < 4; i++)
154*f6dc9357SAndroid Build Coastguard Worker   {
155*f6dc9357SAndroid Build Coastguard Worker     val <<= 8;
156*f6dc9357SAndroid Build Coastguard Worker     val |= ReadByte();
157*f6dc9357SAndroid Build Coastguard Worker   }
158*f6dc9357SAndroid Build Coastguard Worker   return val;
159*f6dc9357SAndroid Build Coastguard Worker }
160*f6dc9357SAndroid Build Coastguard Worker 
ReadUInt32()161*f6dc9357SAndroid Build Coastguard Worker UInt32 CInArchive::ReadUInt32()
162*f6dc9357SAndroid Build Coastguard Worker {
163*f6dc9357SAndroid Build Coastguard Worker   Byte b[8];
164*f6dc9357SAndroid Build Coastguard Worker   ReadBytes(b, 8);
165*f6dc9357SAndroid Build Coastguard Worker   UInt32 val = 0;
166*f6dc9357SAndroid Build Coastguard Worker   for (int i = 0; i < 4; i++)
167*f6dc9357SAndroid Build Coastguard Worker   {
168*f6dc9357SAndroid Build Coastguard Worker     if (b[i] != b[7 - i])
169*f6dc9357SAndroid Build Coastguard Worker       throw CEndianErrorException();
170*f6dc9357SAndroid Build Coastguard Worker     val |= ((UInt32)(b[i]) << (8 * i));
171*f6dc9357SAndroid Build Coastguard Worker   }
172*f6dc9357SAndroid Build Coastguard Worker   return val;
173*f6dc9357SAndroid Build Coastguard Worker }
174*f6dc9357SAndroid Build Coastguard Worker 
ReadDigits(int numDigits)175*f6dc9357SAndroid Build Coastguard Worker UInt32 CInArchive::ReadDigits(int numDigits)
176*f6dc9357SAndroid Build Coastguard Worker {
177*f6dc9357SAndroid Build Coastguard Worker   UInt32 res = 0;
178*f6dc9357SAndroid Build Coastguard Worker   for (int i = 0; i < numDigits; i++)
179*f6dc9357SAndroid Build Coastguard Worker   {
180*f6dc9357SAndroid Build Coastguard Worker     Byte b = ReadByte();
181*f6dc9357SAndroid Build Coastguard Worker     if (b < '0' || b > '9')
182*f6dc9357SAndroid Build Coastguard Worker     {
183*f6dc9357SAndroid Build Coastguard Worker       if (b == 0 || b == ' ') // it's bug in some CD's
184*f6dc9357SAndroid Build Coastguard Worker         b = '0';
185*f6dc9357SAndroid Build Coastguard Worker       else
186*f6dc9357SAndroid Build Coastguard Worker         throw CHeaderErrorException();
187*f6dc9357SAndroid Build Coastguard Worker     }
188*f6dc9357SAndroid Build Coastguard Worker     UInt32 d = (UInt32)(b - '0');
189*f6dc9357SAndroid Build Coastguard Worker     res *= 10;
190*f6dc9357SAndroid Build Coastguard Worker     res += d;
191*f6dc9357SAndroid Build Coastguard Worker   }
192*f6dc9357SAndroid Build Coastguard Worker   return res;
193*f6dc9357SAndroid Build Coastguard Worker }
194*f6dc9357SAndroid Build Coastguard Worker 
ReadDateTime(CDateTime & d)195*f6dc9357SAndroid Build Coastguard Worker void CInArchive::ReadDateTime(CDateTime &d)
196*f6dc9357SAndroid Build Coastguard Worker {
197*f6dc9357SAndroid Build Coastguard Worker   d.Year = (UInt16)ReadDigits(4);
198*f6dc9357SAndroid Build Coastguard Worker   d.Month = (Byte)ReadDigits(2);
199*f6dc9357SAndroid Build Coastguard Worker   d.Day = (Byte)ReadDigits(2);
200*f6dc9357SAndroid Build Coastguard Worker   d.Hour = (Byte)ReadDigits(2);
201*f6dc9357SAndroid Build Coastguard Worker   d.Minute = (Byte)ReadDigits(2);
202*f6dc9357SAndroid Build Coastguard Worker   d.Second = (Byte)ReadDigits(2);
203*f6dc9357SAndroid Build Coastguard Worker   d.Hundredths = (Byte)ReadDigits(2);
204*f6dc9357SAndroid Build Coastguard Worker   d.GmtOffset = (signed char)ReadByte();
205*f6dc9357SAndroid Build Coastguard Worker }
206*f6dc9357SAndroid Build Coastguard Worker 
ReadBootRecordDescriptor(CBootRecordDescriptor & d)207*f6dc9357SAndroid Build Coastguard Worker void CInArchive::ReadBootRecordDescriptor(CBootRecordDescriptor &d)
208*f6dc9357SAndroid Build Coastguard Worker {
209*f6dc9357SAndroid Build Coastguard Worker   ReadBytes(d.BootSystemId, sizeof(d.BootSystemId));
210*f6dc9357SAndroid Build Coastguard Worker   ReadBytes(d.BootId, sizeof(d.BootId));
211*f6dc9357SAndroid Build Coastguard Worker   ReadBytes(d.BootSystemUse, sizeof(d.BootSystemUse));
212*f6dc9357SAndroid Build Coastguard Worker }
213*f6dc9357SAndroid Build Coastguard Worker 
ReadRecordingDateTime(CRecordingDateTime & t)214*f6dc9357SAndroid Build Coastguard Worker void CInArchive::ReadRecordingDateTime(CRecordingDateTime &t)
215*f6dc9357SAndroid Build Coastguard Worker {
216*f6dc9357SAndroid Build Coastguard Worker   t.Year = ReadByte();
217*f6dc9357SAndroid Build Coastguard Worker   t.Month = ReadByte();
218*f6dc9357SAndroid Build Coastguard Worker   t.Day = ReadByte();
219*f6dc9357SAndroid Build Coastguard Worker   t.Hour = ReadByte();
220*f6dc9357SAndroid Build Coastguard Worker   t.Minute = ReadByte();
221*f6dc9357SAndroid Build Coastguard Worker   t.Second = ReadByte();
222*f6dc9357SAndroid Build Coastguard Worker   t.GmtOffset = (signed char)ReadByte();
223*f6dc9357SAndroid Build Coastguard Worker }
224*f6dc9357SAndroid Build Coastguard Worker 
ReadDirRecord2(CDirRecord & r,Byte len)225*f6dc9357SAndroid Build Coastguard Worker void CInArchive::ReadDirRecord2(CDirRecord &r, Byte len)
226*f6dc9357SAndroid Build Coastguard Worker {
227*f6dc9357SAndroid Build Coastguard Worker   r.ExtendedAttributeRecordLen = ReadByte();
228*f6dc9357SAndroid Build Coastguard Worker   if (r.ExtendedAttributeRecordLen != 0)
229*f6dc9357SAndroid Build Coastguard Worker     throw CHeaderErrorException();
230*f6dc9357SAndroid Build Coastguard Worker   r.ExtentLocation = ReadUInt32();
231*f6dc9357SAndroid Build Coastguard Worker   r.Size = ReadUInt32();
232*f6dc9357SAndroid Build Coastguard Worker   ReadRecordingDateTime(r.DateTime);
233*f6dc9357SAndroid Build Coastguard Worker   r.FileFlags = ReadByte();
234*f6dc9357SAndroid Build Coastguard Worker   r.FileUnitSize = ReadByte();
235*f6dc9357SAndroid Build Coastguard Worker   r.InterleaveGapSize = ReadByte();
236*f6dc9357SAndroid Build Coastguard Worker   r.VolSequenceNumber = ReadUInt16();
237*f6dc9357SAndroid Build Coastguard Worker   Byte idLen = ReadByte();
238*f6dc9357SAndroid Build Coastguard Worker   r.FileId.Alloc(idLen);
239*f6dc9357SAndroid Build Coastguard Worker   ReadBytes((Byte *)r.FileId, idLen);
240*f6dc9357SAndroid Build Coastguard Worker   unsigned padSize = 1 - (idLen & 1);
241*f6dc9357SAndroid Build Coastguard Worker 
242*f6dc9357SAndroid Build Coastguard Worker   // SkipZeros(padSize);
243*f6dc9357SAndroid Build Coastguard Worker   Skip(padSize); // it's bug in some cd's. Must be zeros
244*f6dc9357SAndroid Build Coastguard Worker 
245*f6dc9357SAndroid Build Coastguard Worker   unsigned curPos = 33 + idLen + padSize;
246*f6dc9357SAndroid Build Coastguard Worker   if (curPos > len)
247*f6dc9357SAndroid Build Coastguard Worker     throw CHeaderErrorException();
248*f6dc9357SAndroid Build Coastguard Worker   unsigned rem = len - curPos;
249*f6dc9357SAndroid Build Coastguard Worker   r.SystemUse.Alloc(rem);
250*f6dc9357SAndroid Build Coastguard Worker   ReadBytes((Byte *)r.SystemUse, rem);
251*f6dc9357SAndroid Build Coastguard Worker }
252*f6dc9357SAndroid Build Coastguard Worker 
ReadDirRecord(CDirRecord & r)253*f6dc9357SAndroid Build Coastguard Worker void CInArchive::ReadDirRecord(CDirRecord &r)
254*f6dc9357SAndroid Build Coastguard Worker {
255*f6dc9357SAndroid Build Coastguard Worker   Byte len = ReadByte();
256*f6dc9357SAndroid Build Coastguard Worker   // Some CDs can have incorrect value len = 48 ('0') in VolumeDescriptor.
257*f6dc9357SAndroid Build Coastguard Worker   // But maybe we must use real "len" for other records.
258*f6dc9357SAndroid Build Coastguard Worker   len = 34;
259*f6dc9357SAndroid Build Coastguard Worker   ReadDirRecord2(r, len);
260*f6dc9357SAndroid Build Coastguard Worker }
261*f6dc9357SAndroid Build Coastguard Worker 
ReadVolumeDescriptor(CVolumeDescriptor & d)262*f6dc9357SAndroid Build Coastguard Worker void CInArchive::ReadVolumeDescriptor(CVolumeDescriptor &d)
263*f6dc9357SAndroid Build Coastguard Worker {
264*f6dc9357SAndroid Build Coastguard Worker   d.VolFlags = ReadByte();
265*f6dc9357SAndroid Build Coastguard Worker   ReadBytes(d.SystemId, sizeof(d.SystemId));
266*f6dc9357SAndroid Build Coastguard Worker   ReadBytes(d.VolumeId, sizeof(d.VolumeId));
267*f6dc9357SAndroid Build Coastguard Worker   SkipZeros(8);
268*f6dc9357SAndroid Build Coastguard Worker   d.VolumeSpaceSize = ReadUInt32();
269*f6dc9357SAndroid Build Coastguard Worker   ReadBytes(d.EscapeSequence, sizeof(d.EscapeSequence));
270*f6dc9357SAndroid Build Coastguard Worker   d.VolumeSetSize = ReadUInt16();
271*f6dc9357SAndroid Build Coastguard Worker   d.VolumeSequenceNumber = ReadUInt16();
272*f6dc9357SAndroid Build Coastguard Worker   d.LogicalBlockSize = ReadUInt16();
273*f6dc9357SAndroid Build Coastguard Worker   d.PathTableSize = ReadUInt32();
274*f6dc9357SAndroid Build Coastguard Worker   d.LPathTableLocation = ReadUInt32Le();
275*f6dc9357SAndroid Build Coastguard Worker   d.LOptionalPathTableLocation = ReadUInt32Le();
276*f6dc9357SAndroid Build Coastguard Worker   d.MPathTableLocation = ReadUInt32Be();
277*f6dc9357SAndroid Build Coastguard Worker   d.MOptionalPathTableLocation = ReadUInt32Be();
278*f6dc9357SAndroid Build Coastguard Worker   ReadDirRecord(d.RootDirRecord);
279*f6dc9357SAndroid Build Coastguard Worker   ReadBytes(d.VolumeSetId, sizeof(d.VolumeSetId));
280*f6dc9357SAndroid Build Coastguard Worker   ReadBytes(d.PublisherId, sizeof(d.PublisherId));
281*f6dc9357SAndroid Build Coastguard Worker   ReadBytes(d.DataPreparerId, sizeof(d.DataPreparerId));
282*f6dc9357SAndroid Build Coastguard Worker   ReadBytes(d.ApplicationId, sizeof(d.ApplicationId));
283*f6dc9357SAndroid Build Coastguard Worker   ReadBytes(d.CopyrightFileId, sizeof(d.CopyrightFileId));
284*f6dc9357SAndroid Build Coastguard Worker   ReadBytes(d.AbstractFileId, sizeof(d.AbstractFileId));
285*f6dc9357SAndroid Build Coastguard Worker   ReadBytes(d.BibFileId, sizeof(d.BibFileId));
286*f6dc9357SAndroid Build Coastguard Worker   ReadDateTime(d.CTime);
287*f6dc9357SAndroid Build Coastguard Worker   ReadDateTime(d.MTime);
288*f6dc9357SAndroid Build Coastguard Worker   ReadDateTime(d.ExpirationTime);
289*f6dc9357SAndroid Build Coastguard Worker   ReadDateTime(d.EffectiveTime);
290*f6dc9357SAndroid Build Coastguard Worker   const Byte fileStructureVersion = ReadByte();
291*f6dc9357SAndroid Build Coastguard Worker   // d.FileStructureVersion = fileStructureVersion;
292*f6dc9357SAndroid Build Coastguard Worker   if (fileStructureVersion != 1 &&  // ECMA-119
293*f6dc9357SAndroid Build Coastguard Worker       fileStructureVersion != 2)    // some ISO files have fileStructureVersion == 2.
294*f6dc9357SAndroid Build Coastguard Worker   {
295*f6dc9357SAndroid Build Coastguard Worker     // v24.05: we ignore that field, because we don't know what exact values are allowed there
296*f6dc9357SAndroid Build Coastguard Worker     // throw CHeaderErrorException();
297*f6dc9357SAndroid Build Coastguard Worker   }
298*f6dc9357SAndroid Build Coastguard Worker   SkipZeros(1); // (Reserved for future standardization)
299*f6dc9357SAndroid Build Coastguard Worker   ReadBytes(d.ApplicationUse, sizeof(d.ApplicationUse));
300*f6dc9357SAndroid Build Coastguard Worker   // Most ISO contain zeros in the following field (reserved for future standardization).
301*f6dc9357SAndroid Build Coastguard Worker   // But some ISO programs write some data to that area.
302*f6dc9357SAndroid Build Coastguard Worker   // So we disable check for zeros.
303*f6dc9357SAndroid Build Coastguard Worker   Skip(653); // SkipZeros(653);
304*f6dc9357SAndroid Build Coastguard Worker }
305*f6dc9357SAndroid Build Coastguard Worker 
306*f6dc9357SAndroid Build Coastguard Worker static const Byte kSig_CD001[5] = { 'C', 'D', '0', '0', '1' };
307*f6dc9357SAndroid Build Coastguard Worker 
308*f6dc9357SAndroid Build Coastguard Worker /*
309*f6dc9357SAndroid Build Coastguard Worker static const Byte kSig_NSR02[5] = { 'N', 'S', 'R', '0', '2' };
310*f6dc9357SAndroid Build Coastguard Worker static const Byte kSig_NSR03[5] = { 'N', 'S', 'R', '0', '3' };
311*f6dc9357SAndroid Build Coastguard Worker static const Byte kSig_BEA01[5] = { 'B', 'E', 'A', '0', '1' };
312*f6dc9357SAndroid Build Coastguard Worker static const Byte kSig_TEA01[5] = { 'T', 'E', 'A', '0', '1' };
313*f6dc9357SAndroid Build Coastguard Worker */
314*f6dc9357SAndroid Build Coastguard Worker 
CheckSignature(const Byte * sig,const Byte * data)315*f6dc9357SAndroid Build Coastguard Worker static inline bool CheckSignature(const Byte *sig, const Byte *data)
316*f6dc9357SAndroid Build Coastguard Worker {
317*f6dc9357SAndroid Build Coastguard Worker   for (int i = 0; i < 5; i++)
318*f6dc9357SAndroid Build Coastguard Worker     if (sig[i] != data[i])
319*f6dc9357SAndroid Build Coastguard Worker       return false;
320*f6dc9357SAndroid Build Coastguard Worker   return true;
321*f6dc9357SAndroid Build Coastguard Worker }
322*f6dc9357SAndroid Build Coastguard Worker 
SeekToBlock(UInt32 blockIndex)323*f6dc9357SAndroid Build Coastguard Worker void CInArchive::SeekToBlock(UInt32 blockIndex)
324*f6dc9357SAndroid Build Coastguard Worker {
325*f6dc9357SAndroid Build Coastguard Worker   const HRESULT res = _stream->Seek(
326*f6dc9357SAndroid Build Coastguard Worker       (Int64)((UInt64)blockIndex * VolDescs[MainVolDescIndex].LogicalBlockSize),
327*f6dc9357SAndroid Build Coastguard Worker       STREAM_SEEK_SET, &_position);
328*f6dc9357SAndroid Build Coastguard Worker   if (res != S_OK)
329*f6dc9357SAndroid Build Coastguard Worker     throw CSystemException(res);
330*f6dc9357SAndroid Build Coastguard Worker   m_BufferPos = 0;
331*f6dc9357SAndroid Build Coastguard Worker }
332*f6dc9357SAndroid Build Coastguard Worker 
333*f6dc9357SAndroid Build Coastguard Worker static const int kNumLevelsMax = 256;
334*f6dc9357SAndroid Build Coastguard Worker 
ReadDir(CDir & d,int level)335*f6dc9357SAndroid Build Coastguard Worker void CInArchive::ReadDir(CDir &d, int level)
336*f6dc9357SAndroid Build Coastguard Worker {
337*f6dc9357SAndroid Build Coastguard Worker   if (!d.IsDir())
338*f6dc9357SAndroid Build Coastguard Worker     return;
339*f6dc9357SAndroid Build Coastguard Worker   if (level > kNumLevelsMax)
340*f6dc9357SAndroid Build Coastguard Worker   {
341*f6dc9357SAndroid Build Coastguard Worker     TooDeepDirs = true;
342*f6dc9357SAndroid Build Coastguard Worker     return;
343*f6dc9357SAndroid Build Coastguard Worker   }
344*f6dc9357SAndroid Build Coastguard Worker 
345*f6dc9357SAndroid Build Coastguard Worker   {
346*f6dc9357SAndroid Build Coastguard Worker     FOR_VECTOR (i, UniqStartLocations)
347*f6dc9357SAndroid Build Coastguard Worker       if (UniqStartLocations[i] == d.ExtentLocation)
348*f6dc9357SAndroid Build Coastguard Worker       {
349*f6dc9357SAndroid Build Coastguard Worker         SelfLinkedDirs = true;
350*f6dc9357SAndroid Build Coastguard Worker         return;
351*f6dc9357SAndroid Build Coastguard Worker       }
352*f6dc9357SAndroid Build Coastguard Worker     UniqStartLocations.Add(d.ExtentLocation);
353*f6dc9357SAndroid Build Coastguard Worker   }
354*f6dc9357SAndroid Build Coastguard Worker 
355*f6dc9357SAndroid Build Coastguard Worker   SeekToBlock(d.ExtentLocation);
356*f6dc9357SAndroid Build Coastguard Worker   UInt64 startPos = _position;
357*f6dc9357SAndroid Build Coastguard Worker 
358*f6dc9357SAndroid Build Coastguard Worker   bool firstItem = true;
359*f6dc9357SAndroid Build Coastguard Worker   for (;;)
360*f6dc9357SAndroid Build Coastguard Worker   {
361*f6dc9357SAndroid Build Coastguard Worker     UInt64 offset = _position - startPos;
362*f6dc9357SAndroid Build Coastguard Worker     if (offset >= d.Size)
363*f6dc9357SAndroid Build Coastguard Worker       break;
364*f6dc9357SAndroid Build Coastguard Worker     Byte len = ReadByte();
365*f6dc9357SAndroid Build Coastguard Worker     if (len == 0)
366*f6dc9357SAndroid Build Coastguard Worker       continue;
367*f6dc9357SAndroid Build Coastguard Worker     CDir subItem;
368*f6dc9357SAndroid Build Coastguard Worker     ReadDirRecord2(subItem, len);
369*f6dc9357SAndroid Build Coastguard Worker     if (firstItem && level == 0)
370*f6dc9357SAndroid Build Coastguard Worker       IsSusp = subItem.CheckSusp(SuspSkipSize);
371*f6dc9357SAndroid Build Coastguard Worker 
372*f6dc9357SAndroid Build Coastguard Worker     if (!subItem.IsSystemItem())
373*f6dc9357SAndroid Build Coastguard Worker       d._subItems.Add(subItem);
374*f6dc9357SAndroid Build Coastguard Worker 
375*f6dc9357SAndroid Build Coastguard Worker     firstItem = false;
376*f6dc9357SAndroid Build Coastguard Worker   }
377*f6dc9357SAndroid Build Coastguard Worker   FOR_VECTOR (i, d._subItems)
378*f6dc9357SAndroid Build Coastguard Worker     ReadDir(d._subItems[i], level + 1);
379*f6dc9357SAndroid Build Coastguard Worker 
380*f6dc9357SAndroid Build Coastguard Worker   UniqStartLocations.DeleteBack();
381*f6dc9357SAndroid Build Coastguard Worker }
382*f6dc9357SAndroid Build Coastguard Worker 
CreateRefs(CDir & d)383*f6dc9357SAndroid Build Coastguard Worker void CInArchive::CreateRefs(CDir &d)
384*f6dc9357SAndroid Build Coastguard Worker {
385*f6dc9357SAndroid Build Coastguard Worker   if (!d.IsDir())
386*f6dc9357SAndroid Build Coastguard Worker     return;
387*f6dc9357SAndroid Build Coastguard Worker   for (unsigned i = 0; i < d._subItems.Size();)
388*f6dc9357SAndroid Build Coastguard Worker   {
389*f6dc9357SAndroid Build Coastguard Worker     CRef ref;
390*f6dc9357SAndroid Build Coastguard Worker     CDir &subItem = d._subItems[i];
391*f6dc9357SAndroid Build Coastguard Worker     subItem.Parent = &d;
392*f6dc9357SAndroid Build Coastguard Worker     ref.Dir = &d;
393*f6dc9357SAndroid Build Coastguard Worker     ref.Index = i++;
394*f6dc9357SAndroid Build Coastguard Worker     ref.NumExtents = 1;
395*f6dc9357SAndroid Build Coastguard Worker     ref.TotalSize = subItem.Size;
396*f6dc9357SAndroid Build Coastguard Worker     if (subItem.IsNonFinalExtent())
397*f6dc9357SAndroid Build Coastguard Worker     {
398*f6dc9357SAndroid Build Coastguard Worker       for (;;)
399*f6dc9357SAndroid Build Coastguard Worker       {
400*f6dc9357SAndroid Build Coastguard Worker         if (i == d._subItems.Size())
401*f6dc9357SAndroid Build Coastguard Worker         {
402*f6dc9357SAndroid Build Coastguard Worker           HeadersError = true;
403*f6dc9357SAndroid Build Coastguard Worker           break;
404*f6dc9357SAndroid Build Coastguard Worker         }
405*f6dc9357SAndroid Build Coastguard Worker         const CDir &next = d._subItems[i];
406*f6dc9357SAndroid Build Coastguard Worker         if (!subItem.AreMultiPartEqualWith(next))
407*f6dc9357SAndroid Build Coastguard Worker           break;
408*f6dc9357SAndroid Build Coastguard Worker         i++;
409*f6dc9357SAndroid Build Coastguard Worker         ref.NumExtents++;
410*f6dc9357SAndroid Build Coastguard Worker         ref.TotalSize += next.Size;
411*f6dc9357SAndroid Build Coastguard Worker         if (!next.IsNonFinalExtent())
412*f6dc9357SAndroid Build Coastguard Worker           break;
413*f6dc9357SAndroid Build Coastguard Worker       }
414*f6dc9357SAndroid Build Coastguard Worker     }
415*f6dc9357SAndroid Build Coastguard Worker     Refs.Add(ref);
416*f6dc9357SAndroid Build Coastguard Worker     CreateRefs(subItem);
417*f6dc9357SAndroid Build Coastguard Worker   }
418*f6dc9357SAndroid Build Coastguard Worker }
419*f6dc9357SAndroid Build Coastguard Worker 
ReadBootInfo()420*f6dc9357SAndroid Build Coastguard Worker void CInArchive::ReadBootInfo()
421*f6dc9357SAndroid Build Coastguard Worker {
422*f6dc9357SAndroid Build Coastguard Worker   if (!_bootIsDefined)
423*f6dc9357SAndroid Build Coastguard Worker     return;
424*f6dc9357SAndroid Build Coastguard Worker   HeadersError = true;
425*f6dc9357SAndroid Build Coastguard Worker 
426*f6dc9357SAndroid Build Coastguard Worker   if (memcmp(_bootDesc.BootSystemId, kElToritoSpec, sizeof(_bootDesc.BootSystemId)) != 0)
427*f6dc9357SAndroid Build Coastguard Worker     return;
428*f6dc9357SAndroid Build Coastguard Worker 
429*f6dc9357SAndroid Build Coastguard Worker   UInt32 blockIndex = GetUi32(_bootDesc.BootSystemUse);
430*f6dc9357SAndroid Build Coastguard Worker   SeekToBlock(blockIndex);
431*f6dc9357SAndroid Build Coastguard Worker 
432*f6dc9357SAndroid Build Coastguard Worker   Byte buf[32];
433*f6dc9357SAndroid Build Coastguard Worker   ReadBytes(buf, 32);
434*f6dc9357SAndroid Build Coastguard Worker 
435*f6dc9357SAndroid Build Coastguard Worker   if (buf[0] != NBootEntryId::kValidationEntry
436*f6dc9357SAndroid Build Coastguard Worker       || buf[2] != 0
437*f6dc9357SAndroid Build Coastguard Worker       || buf[3] != 0
438*f6dc9357SAndroid Build Coastguard Worker       || buf[30] != 0x55
439*f6dc9357SAndroid Build Coastguard Worker       || buf[31] != 0xAA)
440*f6dc9357SAndroid Build Coastguard Worker     return;
441*f6dc9357SAndroid Build Coastguard Worker 
442*f6dc9357SAndroid Build Coastguard Worker   {
443*f6dc9357SAndroid Build Coastguard Worker     UInt32 sum = 0;
444*f6dc9357SAndroid Build Coastguard Worker     for (unsigned i = 0; i < 32; i += 2)
445*f6dc9357SAndroid Build Coastguard Worker       sum += GetUi16(buf + i);
446*f6dc9357SAndroid Build Coastguard Worker     if ((sum & 0xFFFF) != 0)
447*f6dc9357SAndroid Build Coastguard Worker       return;
448*f6dc9357SAndroid Build Coastguard Worker     /*
449*f6dc9357SAndroid Build Coastguard Worker     CBootValidationEntry e;
450*f6dc9357SAndroid Build Coastguard Worker     e.PlatformId = buf[1];
451*f6dc9357SAndroid Build Coastguard Worker     memcpy(e.Id, buf + 4, sizeof(e.Id));
452*f6dc9357SAndroid Build Coastguard Worker     // UInt16 checkSum = GetUi16(p + 28);
453*f6dc9357SAndroid Build Coastguard Worker     */
454*f6dc9357SAndroid Build Coastguard Worker   }
455*f6dc9357SAndroid Build Coastguard Worker 
456*f6dc9357SAndroid Build Coastguard Worker   ReadBytes(buf, 32);
457*f6dc9357SAndroid Build Coastguard Worker   {
458*f6dc9357SAndroid Build Coastguard Worker     CBootInitialEntry e;
459*f6dc9357SAndroid Build Coastguard Worker     if (!e.Parse(buf))
460*f6dc9357SAndroid Build Coastguard Worker       return;
461*f6dc9357SAndroid Build Coastguard Worker     BootEntries.Add(e);
462*f6dc9357SAndroid Build Coastguard Worker   }
463*f6dc9357SAndroid Build Coastguard Worker 
464*f6dc9357SAndroid Build Coastguard Worker   bool error = false;
465*f6dc9357SAndroid Build Coastguard Worker 
466*f6dc9357SAndroid Build Coastguard Worker   for (;;)
467*f6dc9357SAndroid Build Coastguard Worker   {
468*f6dc9357SAndroid Build Coastguard Worker     ReadBytes(buf, 32);
469*f6dc9357SAndroid Build Coastguard Worker     Byte headerIndicator = buf[0];
470*f6dc9357SAndroid Build Coastguard Worker     if (headerIndicator != NBootEntryId::kMoreHeaders
471*f6dc9357SAndroid Build Coastguard Worker         && headerIndicator != NBootEntryId::kFinalHeader)
472*f6dc9357SAndroid Build Coastguard Worker       break;
473*f6dc9357SAndroid Build Coastguard Worker 
474*f6dc9357SAndroid Build Coastguard Worker     // Section Header
475*f6dc9357SAndroid Build Coastguard Worker     // Byte platform = p[1];
476*f6dc9357SAndroid Build Coastguard Worker     unsigned numEntries = GetUi16(buf + 2);
477*f6dc9357SAndroid Build Coastguard Worker     // id[28]
478*f6dc9357SAndroid Build Coastguard Worker 
479*f6dc9357SAndroid Build Coastguard Worker     for (unsigned i = 0; i < numEntries; i++)
480*f6dc9357SAndroid Build Coastguard Worker     {
481*f6dc9357SAndroid Build Coastguard Worker       ReadBytes(buf, 32);
482*f6dc9357SAndroid Build Coastguard Worker       CBootInitialEntry e;
483*f6dc9357SAndroid Build Coastguard Worker       if (!e.Parse(buf))
484*f6dc9357SAndroid Build Coastguard Worker       {
485*f6dc9357SAndroid Build Coastguard Worker         error = true;
486*f6dc9357SAndroid Build Coastguard Worker         break;
487*f6dc9357SAndroid Build Coastguard Worker       }
488*f6dc9357SAndroid Build Coastguard Worker       if (e.BootMediaType & (1 << 5))
489*f6dc9357SAndroid Build Coastguard Worker       {
490*f6dc9357SAndroid Build Coastguard Worker         // Section entry extension
491*f6dc9357SAndroid Build Coastguard Worker         for (unsigned j = 0;; j++)
492*f6dc9357SAndroid Build Coastguard Worker         {
493*f6dc9357SAndroid Build Coastguard Worker           ReadBytes(buf, 32);
494*f6dc9357SAndroid Build Coastguard Worker           if (j > 32 || buf[0] != NBootEntryId::kExtensionIndicator)
495*f6dc9357SAndroid Build Coastguard Worker           {
496*f6dc9357SAndroid Build Coastguard Worker             error = true;
497*f6dc9357SAndroid Build Coastguard Worker             break;
498*f6dc9357SAndroid Build Coastguard Worker           }
499*f6dc9357SAndroid Build Coastguard Worker           if ((buf[1] & (1 << 5)) == 0)
500*f6dc9357SAndroid Build Coastguard Worker             break;
501*f6dc9357SAndroid Build Coastguard Worker           // info += (buf + 2, 30)
502*f6dc9357SAndroid Build Coastguard Worker         }
503*f6dc9357SAndroid Build Coastguard Worker       }
504*f6dc9357SAndroid Build Coastguard Worker       BootEntries.Add(e);
505*f6dc9357SAndroid Build Coastguard Worker     }
506*f6dc9357SAndroid Build Coastguard Worker 
507*f6dc9357SAndroid Build Coastguard Worker     if (headerIndicator != NBootEntryId::kMoreHeaders)
508*f6dc9357SAndroid Build Coastguard Worker       break;
509*f6dc9357SAndroid Build Coastguard Worker   }
510*f6dc9357SAndroid Build Coastguard Worker 
511*f6dc9357SAndroid Build Coastguard Worker   HeadersError = error;
512*f6dc9357SAndroid Build Coastguard Worker }
513*f6dc9357SAndroid Build Coastguard Worker 
Open2()514*f6dc9357SAndroid Build Coastguard Worker HRESULT CInArchive::Open2()
515*f6dc9357SAndroid Build Coastguard Worker {
516*f6dc9357SAndroid Build Coastguard Worker   _position = 0;
517*f6dc9357SAndroid Build Coastguard Worker   RINOK(InStream_GetSize_SeekToEnd(_stream, _fileSize))
518*f6dc9357SAndroid Build Coastguard Worker   if (_fileSize < kStartPos)
519*f6dc9357SAndroid Build Coastguard Worker     return S_FALSE;
520*f6dc9357SAndroid Build Coastguard Worker   RINOK(_stream->Seek(kStartPos, STREAM_SEEK_SET, &_position))
521*f6dc9357SAndroid Build Coastguard Worker 
522*f6dc9357SAndroid Build Coastguard Worker   PhySize = _position;
523*f6dc9357SAndroid Build Coastguard Worker   m_BufferPos = 0;
524*f6dc9357SAndroid Build Coastguard Worker   // BlockSize = kBlockSize;
525*f6dc9357SAndroid Build Coastguard Worker 
526*f6dc9357SAndroid Build Coastguard Worker   for (;;)
527*f6dc9357SAndroid Build Coastguard Worker   {
528*f6dc9357SAndroid Build Coastguard Worker     Byte sig[7];
529*f6dc9357SAndroid Build Coastguard Worker     ReadBytes(sig, 7);
530*f6dc9357SAndroid Build Coastguard Worker     Byte ver = sig[6];
531*f6dc9357SAndroid Build Coastguard Worker 
532*f6dc9357SAndroid Build Coastguard Worker     if (!CheckSignature(kSig_CD001, sig + 1))
533*f6dc9357SAndroid Build Coastguard Worker     {
534*f6dc9357SAndroid Build Coastguard Worker       return S_FALSE;
535*f6dc9357SAndroid Build Coastguard Worker       /*
536*f6dc9357SAndroid Build Coastguard Worker       if (sig[0] != 0 || ver != 1)
537*f6dc9357SAndroid Build Coastguard Worker         break;
538*f6dc9357SAndroid Build Coastguard Worker       if (CheckSignature(kSig_BEA01, sig + 1))
539*f6dc9357SAndroid Build Coastguard Worker       {
540*f6dc9357SAndroid Build Coastguard Worker       }
541*f6dc9357SAndroid Build Coastguard Worker       else if (CheckSignature(kSig_TEA01, sig + 1))
542*f6dc9357SAndroid Build Coastguard Worker       {
543*f6dc9357SAndroid Build Coastguard Worker         break;
544*f6dc9357SAndroid Build Coastguard Worker       }
545*f6dc9357SAndroid Build Coastguard Worker       else if (CheckSignature(kSig_NSR02, sig + 1))
546*f6dc9357SAndroid Build Coastguard Worker       {
547*f6dc9357SAndroid Build Coastguard Worker       }
548*f6dc9357SAndroid Build Coastguard Worker       else
549*f6dc9357SAndroid Build Coastguard Worker         break;
550*f6dc9357SAndroid Build Coastguard Worker       SkipZeros(0x800 - 7);
551*f6dc9357SAndroid Build Coastguard Worker       continue;
552*f6dc9357SAndroid Build Coastguard Worker       */
553*f6dc9357SAndroid Build Coastguard Worker     }
554*f6dc9357SAndroid Build Coastguard Worker 
555*f6dc9357SAndroid Build Coastguard Worker     // version = 2 for ISO 9660:1999?
556*f6dc9357SAndroid Build Coastguard Worker     if (ver > 2)
557*f6dc9357SAndroid Build Coastguard Worker       return S_FALSE;
558*f6dc9357SAndroid Build Coastguard Worker 
559*f6dc9357SAndroid Build Coastguard Worker     if (sig[0] == NVolDescType::kTerminator)
560*f6dc9357SAndroid Build Coastguard Worker     {
561*f6dc9357SAndroid Build Coastguard Worker       break;
562*f6dc9357SAndroid Build Coastguard Worker       // Skip(0x800 - 7);
563*f6dc9357SAndroid Build Coastguard Worker       // continue;
564*f6dc9357SAndroid Build Coastguard Worker     }
565*f6dc9357SAndroid Build Coastguard Worker 
566*f6dc9357SAndroid Build Coastguard Worker     switch (sig[0])
567*f6dc9357SAndroid Build Coastguard Worker     {
568*f6dc9357SAndroid Build Coastguard Worker       case NVolDescType::kBootRecord:
569*f6dc9357SAndroid Build Coastguard Worker       {
570*f6dc9357SAndroid Build Coastguard Worker         _bootIsDefined = true;
571*f6dc9357SAndroid Build Coastguard Worker         ReadBootRecordDescriptor(_bootDesc);
572*f6dc9357SAndroid Build Coastguard Worker         break;
573*f6dc9357SAndroid Build Coastguard Worker       }
574*f6dc9357SAndroid Build Coastguard Worker       case NVolDescType::kPrimaryVol:
575*f6dc9357SAndroid Build Coastguard Worker       case NVolDescType::kSupplementaryVol:
576*f6dc9357SAndroid Build Coastguard Worker       {
577*f6dc9357SAndroid Build Coastguard Worker         // some ISOs have two PrimaryVols.
578*f6dc9357SAndroid Build Coastguard Worker         CVolumeDescriptor vd;
579*f6dc9357SAndroid Build Coastguard Worker         ReadVolumeDescriptor(vd);
580*f6dc9357SAndroid Build Coastguard Worker         if (sig[0] == NVolDescType::kPrimaryVol)
581*f6dc9357SAndroid Build Coastguard Worker         {
582*f6dc9357SAndroid Build Coastguard Worker           // some burners write "Joliet" Escape Sequence to primary volume
583*f6dc9357SAndroid Build Coastguard Worker           memset(vd.EscapeSequence, 0, sizeof(vd.EscapeSequence));
584*f6dc9357SAndroid Build Coastguard Worker         }
585*f6dc9357SAndroid Build Coastguard Worker         VolDescs.Add(vd);
586*f6dc9357SAndroid Build Coastguard Worker         break;
587*f6dc9357SAndroid Build Coastguard Worker       }
588*f6dc9357SAndroid Build Coastguard Worker       default:
589*f6dc9357SAndroid Build Coastguard Worker         break;
590*f6dc9357SAndroid Build Coastguard Worker     }
591*f6dc9357SAndroid Build Coastguard Worker   }
592*f6dc9357SAndroid Build Coastguard Worker 
593*f6dc9357SAndroid Build Coastguard Worker   if (VolDescs.IsEmpty())
594*f6dc9357SAndroid Build Coastguard Worker     return S_FALSE;
595*f6dc9357SAndroid Build Coastguard Worker   for (MainVolDescIndex = (int)VolDescs.Size() - 1; MainVolDescIndex > 0; MainVolDescIndex--)
596*f6dc9357SAndroid Build Coastguard Worker     if (VolDescs[MainVolDescIndex].IsJoliet())
597*f6dc9357SAndroid Build Coastguard Worker       break;
598*f6dc9357SAndroid Build Coastguard Worker   /* FIXME: some volume can contain Rock Ridge, that is better than
599*f6dc9357SAndroid Build Coastguard Worker      Joliet volume. So we need some way to detect such case */
600*f6dc9357SAndroid Build Coastguard Worker   // MainVolDescIndex = 0; // to read primary volume
601*f6dc9357SAndroid Build Coastguard Worker   const CVolumeDescriptor &vd = VolDescs[MainVolDescIndex];
602*f6dc9357SAndroid Build Coastguard Worker   if (vd.LogicalBlockSize != kBlockSize)
603*f6dc9357SAndroid Build Coastguard Worker     return S_FALSE;
604*f6dc9357SAndroid Build Coastguard Worker 
605*f6dc9357SAndroid Build Coastguard Worker   {
606*f6dc9357SAndroid Build Coastguard Worker     FOR_VECTOR (i, VolDescs)
607*f6dc9357SAndroid Build Coastguard Worker     {
608*f6dc9357SAndroid Build Coastguard Worker       const CVolumeDescriptor &vd2 = VolDescs[i];
609*f6dc9357SAndroid Build Coastguard Worker       UpdatePhySize(0, vd2.Get_VolumeSpaceSize_inBytes());
610*f6dc9357SAndroid Build Coastguard Worker     }
611*f6dc9357SAndroid Build Coastguard Worker   }
612*f6dc9357SAndroid Build Coastguard Worker 
613*f6dc9357SAndroid Build Coastguard Worker 
614*f6dc9357SAndroid Build Coastguard Worker   IsArc = true;
615*f6dc9357SAndroid Build Coastguard Worker 
616*f6dc9357SAndroid Build Coastguard Worker   (CDirRecord &)_rootDir = vd.RootDirRecord;
617*f6dc9357SAndroid Build Coastguard Worker   ReadDir(_rootDir, 0);
618*f6dc9357SAndroid Build Coastguard Worker   CreateRefs(_rootDir);
619*f6dc9357SAndroid Build Coastguard Worker   ReadBootInfo();
620*f6dc9357SAndroid Build Coastguard Worker 
621*f6dc9357SAndroid Build Coastguard Worker   {
622*f6dc9357SAndroid Build Coastguard Worker     FOR_VECTOR (i, Refs)
623*f6dc9357SAndroid Build Coastguard Worker     {
624*f6dc9357SAndroid Build Coastguard Worker       const CRef &ref = Refs[i];
625*f6dc9357SAndroid Build Coastguard Worker       for (UInt32 j = 0; j < ref.NumExtents; j++)
626*f6dc9357SAndroid Build Coastguard Worker       {
627*f6dc9357SAndroid Build Coastguard Worker         const CDir &item = ref.Dir->_subItems[ref.Index + j];
628*f6dc9357SAndroid Build Coastguard Worker         if (!item.IsDir() && item.Size != 0)
629*f6dc9357SAndroid Build Coastguard Worker           UpdatePhySize(item.ExtentLocation, item.Size);
630*f6dc9357SAndroid Build Coastguard Worker       }
631*f6dc9357SAndroid Build Coastguard Worker     }
632*f6dc9357SAndroid Build Coastguard Worker   }
633*f6dc9357SAndroid Build Coastguard Worker 
634*f6dc9357SAndroid Build Coastguard Worker   {
635*f6dc9357SAndroid Build Coastguard Worker     // find boot item for expand:
636*f6dc9357SAndroid Build Coastguard Worker     // UEFI Specification : 13.3.2.1. ISO-9660 and El Torito
637*f6dc9357SAndroid Build Coastguard Worker     _expand_BootEntries_index = -1;
638*f6dc9357SAndroid Build Coastguard Worker     FOR_VECTOR (i, BootEntries)
639*f6dc9357SAndroid Build Coastguard Worker     {
640*f6dc9357SAndroid Build Coastguard Worker       const CBootInitialEntry &be = BootEntries[i];
641*f6dc9357SAndroid Build Coastguard Worker       if (be.SectorCount <= 1 && be.BootMediaType == NBootMediaType::kNoEmulation)
642*f6dc9357SAndroid Build Coastguard Worker         if (_expand_BootEntries_index == -1
643*f6dc9357SAndroid Build Coastguard Worker           || be.LoadRBA >= BootEntries[_expand_BootEntries_index].LoadRBA)
644*f6dc9357SAndroid Build Coastguard Worker         _expand_BootEntries_index = (int)i;
645*f6dc9357SAndroid Build Coastguard Worker     }
646*f6dc9357SAndroid Build Coastguard Worker   }
647*f6dc9357SAndroid Build Coastguard Worker 
648*f6dc9357SAndroid Build Coastguard Worker   {
649*f6dc9357SAndroid Build Coastguard Worker     FOR_VECTOR (i, BootEntries)
650*f6dc9357SAndroid Build Coastguard Worker     {
651*f6dc9357SAndroid Build Coastguard Worker       const CBootInitialEntry &be = BootEntries[i];
652*f6dc9357SAndroid Build Coastguard Worker       UpdatePhySize(be.LoadRBA, GetBootItemSize(i));
653*f6dc9357SAndroid Build Coastguard Worker     }
654*f6dc9357SAndroid Build Coastguard Worker   }
655*f6dc9357SAndroid Build Coastguard Worker 
656*f6dc9357SAndroid Build Coastguard Worker   if (PhySize < _fileSize)
657*f6dc9357SAndroid Build Coastguard Worker   {
658*f6dc9357SAndroid Build Coastguard Worker     UInt64 rem = _fileSize - PhySize;
659*f6dc9357SAndroid Build Coastguard Worker     const UInt64 kRemMax = 1 << 21;
660*f6dc9357SAndroid Build Coastguard Worker     if (rem <= kRemMax)
661*f6dc9357SAndroid Build Coastguard Worker     {
662*f6dc9357SAndroid Build Coastguard Worker       RINOK(InStream_SeekSet(_stream, PhySize))
663*f6dc9357SAndroid Build Coastguard Worker       bool areThereNonZeros = false;
664*f6dc9357SAndroid Build Coastguard Worker       UInt64 numZeros = 0;
665*f6dc9357SAndroid Build Coastguard Worker       RINOK(ReadZeroTail(_stream, areThereNonZeros, numZeros, kRemMax))
666*f6dc9357SAndroid Build Coastguard Worker       if (!areThereNonZeros)
667*f6dc9357SAndroid Build Coastguard Worker         PhySize += numZeros;
668*f6dc9357SAndroid Build Coastguard Worker     }
669*f6dc9357SAndroid Build Coastguard Worker   }
670*f6dc9357SAndroid Build Coastguard Worker 
671*f6dc9357SAndroid Build Coastguard Worker   return S_OK;
672*f6dc9357SAndroid Build Coastguard Worker }
673*f6dc9357SAndroid Build Coastguard Worker 
Open(IInStream * inStream)674*f6dc9357SAndroid Build Coastguard Worker HRESULT CInArchive::Open(IInStream *inStream)
675*f6dc9357SAndroid Build Coastguard Worker {
676*f6dc9357SAndroid Build Coastguard Worker   Clear();
677*f6dc9357SAndroid Build Coastguard Worker   _stream = inStream;
678*f6dc9357SAndroid Build Coastguard Worker   try { return Open2(); }
679*f6dc9357SAndroid Build Coastguard Worker   catch(const CSystemException &e) { return e.ErrorCode; }
680*f6dc9357SAndroid Build Coastguard Worker   catch(CUnexpectedEndException &) { UnexpectedEnd = true; return S_FALSE; }
681*f6dc9357SAndroid Build Coastguard Worker   catch(CHeaderErrorException &) { HeadersError = true; return S_FALSE; }
682*f6dc9357SAndroid Build Coastguard Worker   catch(CEndianErrorException &) { IncorrectBigEndian = true; return S_FALSE; }
683*f6dc9357SAndroid Build Coastguard Worker }
684*f6dc9357SAndroid Build Coastguard Worker 
Clear()685*f6dc9357SAndroid Build Coastguard Worker void CInArchive::Clear()
686*f6dc9357SAndroid Build Coastguard Worker {
687*f6dc9357SAndroid Build Coastguard Worker   IsArc = false;
688*f6dc9357SAndroid Build Coastguard Worker   UnexpectedEnd = false;
689*f6dc9357SAndroid Build Coastguard Worker   HeadersError = false;
690*f6dc9357SAndroid Build Coastguard Worker   IncorrectBigEndian = false;
691*f6dc9357SAndroid Build Coastguard Worker   TooDeepDirs = false;
692*f6dc9357SAndroid Build Coastguard Worker   SelfLinkedDirs = false;
693*f6dc9357SAndroid Build Coastguard Worker 
694*f6dc9357SAndroid Build Coastguard Worker   UniqStartLocations.Clear();
695*f6dc9357SAndroid Build Coastguard Worker 
696*f6dc9357SAndroid Build Coastguard Worker   Refs.Clear();
697*f6dc9357SAndroid Build Coastguard Worker   _rootDir.Clear();
698*f6dc9357SAndroid Build Coastguard Worker   VolDescs.Clear();
699*f6dc9357SAndroid Build Coastguard Worker   _bootIsDefined = false;
700*f6dc9357SAndroid Build Coastguard Worker   BootEntries.Clear();
701*f6dc9357SAndroid Build Coastguard Worker   SuspSkipSize = 0;
702*f6dc9357SAndroid Build Coastguard Worker   IsSusp = false;
703*f6dc9357SAndroid Build Coastguard Worker 
704*f6dc9357SAndroid Build Coastguard Worker   _expand_BootEntries_index = -1;
705*f6dc9357SAndroid Build Coastguard Worker }
706*f6dc9357SAndroid Build Coastguard Worker 
707*f6dc9357SAndroid Build Coastguard Worker 
GetBootItemSize(unsigned index) const708*f6dc9357SAndroid Build Coastguard Worker UInt64 CInArchive::GetBootItemSize(unsigned index) const
709*f6dc9357SAndroid Build Coastguard Worker {
710*f6dc9357SAndroid Build Coastguard Worker   const CBootInitialEntry &be = BootEntries[index];
711*f6dc9357SAndroid Build Coastguard Worker   UInt64 size = be.GetSize();
712*f6dc9357SAndroid Build Coastguard Worker        if (be.BootMediaType == NBootMediaType::k1d2Floppy)  size = 1200 << 10;
713*f6dc9357SAndroid Build Coastguard Worker   else if (be.BootMediaType == NBootMediaType::k1d44Floppy) size = 1440 << 10;
714*f6dc9357SAndroid Build Coastguard Worker   else if (be.BootMediaType == NBootMediaType::k2d88Floppy) size = 2880 << 10;
715*f6dc9357SAndroid Build Coastguard Worker   const UInt64 startPos = (UInt64)be.LoadRBA * kBlockSize;
716*f6dc9357SAndroid Build Coastguard Worker   if (startPos < _fileSize)
717*f6dc9357SAndroid Build Coastguard Worker   {
718*f6dc9357SAndroid Build Coastguard Worker     const UInt64 rem = _fileSize - startPos;
719*f6dc9357SAndroid Build Coastguard Worker     /*
720*f6dc9357SAndroid Build Coastguard Worker        UEFI modification to ISO specification:
721*f6dc9357SAndroid Build Coastguard Worker        because SectorCount is 16-bit, size is limited by (32 MB).
722*f6dc9357SAndroid Build Coastguard Worker        UEFI Specification :
723*f6dc9357SAndroid Build Coastguard Worker         13.3.2.1. ISO-9660 and El Torito
724*f6dc9357SAndroid Build Coastguard Worker         If the value of Sector Count is set to 0 or 1,
725*f6dc9357SAndroid Build Coastguard Worker         EFI will assume the system partition consumes the space
726*f6dc9357SAndroid Build Coastguard Worker         from the beginning of the "no emulation" image to the end of the CD-ROM.
727*f6dc9357SAndroid Build Coastguard Worker     */
728*f6dc9357SAndroid Build Coastguard Worker     //
729*f6dc9357SAndroid Build Coastguard Worker     if ((int)index == _expand_BootEntries_index || rem < size)
730*f6dc9357SAndroid Build Coastguard Worker       size = rem;
731*f6dc9357SAndroid Build Coastguard Worker   }
732*f6dc9357SAndroid Build Coastguard Worker   return size;
733*f6dc9357SAndroid Build Coastguard Worker }
734*f6dc9357SAndroid Build Coastguard Worker 
735*f6dc9357SAndroid Build Coastguard Worker }}
736