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