1*f6dc9357SAndroid Build Coastguard Worker // VmdkHandler.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 <stdio.h>
6*f6dc9357SAndroid Build Coastguard Worker
7*f6dc9357SAndroid Build Coastguard Worker #include "../../../C/CpuArch.h"
8*f6dc9357SAndroid Build Coastguard Worker
9*f6dc9357SAndroid Build Coastguard Worker #include "../../Common/ComTry.h"
10*f6dc9357SAndroid Build Coastguard Worker #include "../../Common/IntToString.h"
11*f6dc9357SAndroid Build Coastguard Worker #include "../../Common/StringConvert.h"
12*f6dc9357SAndroid Build Coastguard Worker #include "../../Common/StringToInt.h"
13*f6dc9357SAndroid Build Coastguard Worker #include "../../Common/UTFConvert.h"
14*f6dc9357SAndroid Build Coastguard Worker
15*f6dc9357SAndroid Build Coastguard Worker #include "../../Windows/PropVariant.h"
16*f6dc9357SAndroid Build Coastguard Worker
17*f6dc9357SAndroid Build Coastguard Worker #include "../Common/RegisterArc.h"
18*f6dc9357SAndroid Build Coastguard Worker #include "../Common/StreamObjects.h"
19*f6dc9357SAndroid Build Coastguard Worker #include "../Common/StreamUtils.h"
20*f6dc9357SAndroid Build Coastguard Worker
21*f6dc9357SAndroid Build Coastguard Worker #include "../Compress/ZlibDecoder.h"
22*f6dc9357SAndroid Build Coastguard Worker
23*f6dc9357SAndroid Build Coastguard Worker #include "HandlerCont.h"
24*f6dc9357SAndroid Build Coastguard Worker
25*f6dc9357SAndroid Build Coastguard Worker using namespace NWindows;
26*f6dc9357SAndroid Build Coastguard Worker
27*f6dc9357SAndroid Build Coastguard Worker namespace NArchive {
28*f6dc9357SAndroid Build Coastguard Worker namespace NVmdk {
29*f6dc9357SAndroid Build Coastguard Worker
30*f6dc9357SAndroid Build Coastguard Worker #define Get16(p) GetUi16(p)
31*f6dc9357SAndroid Build Coastguard Worker #define Get32(p) GetUi32(p)
32*f6dc9357SAndroid Build Coastguard Worker #define Get64(p) GetUi64(p)
33*f6dc9357SAndroid Build Coastguard Worker
34*f6dc9357SAndroid Build Coastguard Worker #define LE_16(offs, dest) dest = Get16(p + (offs))
35*f6dc9357SAndroid Build Coastguard Worker #define LE_32(offs, dest) dest = Get32(p + (offs))
36*f6dc9357SAndroid Build Coastguard Worker #define LE_64(offs, dest) dest = Get64(p + (offs))
37*f6dc9357SAndroid Build Coastguard Worker
38*f6dc9357SAndroid Build Coastguard Worker
39*f6dc9357SAndroid Build Coastguard Worker static const Byte k_Signature[] = { 'K', 'D', 'M', 'V' };
40*f6dc9357SAndroid Build Coastguard Worker
41*f6dc9357SAndroid Build Coastguard Worker static const UInt32 k_Flags_NL = (UInt32)1 << 0;
42*f6dc9357SAndroid Build Coastguard Worker // static const UInt32 k_Flags_RGD = (UInt32)1 << 1;
43*f6dc9357SAndroid Build Coastguard Worker static const UInt32 k_Flags_ZeroGrain = (UInt32)1 << 2;
44*f6dc9357SAndroid Build Coastguard Worker static const UInt32 k_Flags_Compressed = (UInt32)1 << 16;
45*f6dc9357SAndroid Build Coastguard Worker static const UInt32 k_Flags_Marker = (UInt32)1 << 17;
46*f6dc9357SAndroid Build Coastguard Worker
47*f6dc9357SAndroid Build Coastguard Worker static const unsigned k_NumMidBits = 9; // num bits for index in Grain Table
48*f6dc9357SAndroid Build Coastguard Worker
49*f6dc9357SAndroid Build Coastguard Worker struct CHeader
50*f6dc9357SAndroid Build Coastguard Worker {
51*f6dc9357SAndroid Build Coastguard Worker UInt32 flags;
52*f6dc9357SAndroid Build Coastguard Worker UInt32 version;
53*f6dc9357SAndroid Build Coastguard Worker
54*f6dc9357SAndroid Build Coastguard Worker UInt64 capacity;
55*f6dc9357SAndroid Build Coastguard Worker UInt64 grainSize;
56*f6dc9357SAndroid Build Coastguard Worker UInt64 descriptorOffset;
57*f6dc9357SAndroid Build Coastguard Worker UInt64 descriptorSize;
58*f6dc9357SAndroid Build Coastguard Worker
59*f6dc9357SAndroid Build Coastguard Worker UInt32 numGTEsPerGT;
60*f6dc9357SAndroid Build Coastguard Worker UInt16 algo;
61*f6dc9357SAndroid Build Coastguard Worker // Byte uncleanShutdown;
62*f6dc9357SAndroid Build Coastguard Worker // UInt64 rgdOffset;
63*f6dc9357SAndroid Build Coastguard Worker UInt64 gdOffset;
64*f6dc9357SAndroid Build Coastguard Worker UInt64 overHead;
65*f6dc9357SAndroid Build Coastguard Worker
Is_NLNArchive::NVmdk::CHeader66*f6dc9357SAndroid Build Coastguard Worker bool Is_NL() const { return (flags & k_Flags_NL) != 0; }
Is_ZeroGrainNArchive::NVmdk::CHeader67*f6dc9357SAndroid Build Coastguard Worker bool Is_ZeroGrain() const { return (flags & k_Flags_ZeroGrain) != 0; }
Is_CompressedNArchive::NVmdk::CHeader68*f6dc9357SAndroid Build Coastguard Worker bool Is_Compressed() const { return (flags & k_Flags_Compressed) != 0; }
Is_MarkerNArchive::NVmdk::CHeader69*f6dc9357SAndroid Build Coastguard Worker bool Is_Marker() const { return (flags & k_Flags_Marker) != 0; }
70*f6dc9357SAndroid Build Coastguard Worker
71*f6dc9357SAndroid Build Coastguard Worker bool Parse(const Byte *p);
72*f6dc9357SAndroid Build Coastguard Worker
IsSameImageForNArchive::NVmdk::CHeader73*f6dc9357SAndroid Build Coastguard Worker bool IsSameImageFor(const CHeader &h) const
74*f6dc9357SAndroid Build Coastguard Worker {
75*f6dc9357SAndroid Build Coastguard Worker return flags == h.flags
76*f6dc9357SAndroid Build Coastguard Worker && version == h.version
77*f6dc9357SAndroid Build Coastguard Worker && capacity == h.capacity
78*f6dc9357SAndroid Build Coastguard Worker && grainSize == h.grainSize
79*f6dc9357SAndroid Build Coastguard Worker && algo == h.algo;
80*f6dc9357SAndroid Build Coastguard Worker }
81*f6dc9357SAndroid Build Coastguard Worker };
82*f6dc9357SAndroid Build Coastguard Worker
Parse(const Byte * p)83*f6dc9357SAndroid Build Coastguard Worker bool CHeader::Parse(const Byte *p)
84*f6dc9357SAndroid Build Coastguard Worker {
85*f6dc9357SAndroid Build Coastguard Worker if (memcmp(p, k_Signature, sizeof(k_Signature)) != 0)
86*f6dc9357SAndroid Build Coastguard Worker return false;
87*f6dc9357SAndroid Build Coastguard Worker
88*f6dc9357SAndroid Build Coastguard Worker LE_32 (0x04, version);
89*f6dc9357SAndroid Build Coastguard Worker LE_32 (0x08, flags);
90*f6dc9357SAndroid Build Coastguard Worker LE_64 (0x0C, capacity);
91*f6dc9357SAndroid Build Coastguard Worker LE_64 (0x14, grainSize);
92*f6dc9357SAndroid Build Coastguard Worker LE_64 (0x1C, descriptorOffset);
93*f6dc9357SAndroid Build Coastguard Worker LE_64 (0x24, descriptorSize);
94*f6dc9357SAndroid Build Coastguard Worker LE_32 (0x2C, numGTEsPerGT);
95*f6dc9357SAndroid Build Coastguard Worker // LE_64 (0x30, rgdOffset);
96*f6dc9357SAndroid Build Coastguard Worker LE_64 (0x38, gdOffset);
97*f6dc9357SAndroid Build Coastguard Worker LE_64 (0x40, overHead);
98*f6dc9357SAndroid Build Coastguard Worker // uncleanShutdown = buf[0x48];
99*f6dc9357SAndroid Build Coastguard Worker LE_16(0x4D, algo);
100*f6dc9357SAndroid Build Coastguard Worker
101*f6dc9357SAndroid Build Coastguard Worker if (Is_NL() && Get32(p + 0x49) != 0x0A0D200A) // do we need Is_NL() check here?
102*f6dc9357SAndroid Build Coastguard Worker return false;
103*f6dc9357SAndroid Build Coastguard Worker
104*f6dc9357SAndroid Build Coastguard Worker return (numGTEsPerGT == (1 << k_NumMidBits)) && (version <= 3);
105*f6dc9357SAndroid Build Coastguard Worker }
106*f6dc9357SAndroid Build Coastguard Worker
107*f6dc9357SAndroid Build Coastguard Worker
108*f6dc9357SAndroid Build Coastguard Worker enum
109*f6dc9357SAndroid Build Coastguard Worker {
110*f6dc9357SAndroid Build Coastguard Worker k_Marker_END_OF_STREAM = 0,
111*f6dc9357SAndroid Build Coastguard Worker k_Marker_GRAIN_TABLE = 1,
112*f6dc9357SAndroid Build Coastguard Worker k_Marker_GRAIN_DIR = 2,
113*f6dc9357SAndroid Build Coastguard Worker k_Marker_FOOTER = 3
114*f6dc9357SAndroid Build Coastguard Worker };
115*f6dc9357SAndroid Build Coastguard Worker
116*f6dc9357SAndroid Build Coastguard Worker struct CMarker
117*f6dc9357SAndroid Build Coastguard Worker {
118*f6dc9357SAndroid Build Coastguard Worker UInt64 NumSectors;
119*f6dc9357SAndroid Build Coastguard Worker UInt32 SpecSize; // = 0 for metadata sectors
120*f6dc9357SAndroid Build Coastguard Worker UInt32 Type;
121*f6dc9357SAndroid Build Coastguard Worker
ParseNArchive::NVmdk::CMarker122*f6dc9357SAndroid Build Coastguard Worker void Parse(const Byte *p)
123*f6dc9357SAndroid Build Coastguard Worker {
124*f6dc9357SAndroid Build Coastguard Worker LE_64 (0, NumSectors);
125*f6dc9357SAndroid Build Coastguard Worker LE_32 (8, SpecSize);
126*f6dc9357SAndroid Build Coastguard Worker LE_32 (12, Type);
127*f6dc9357SAndroid Build Coastguard Worker }
128*f6dc9357SAndroid Build Coastguard Worker };
129*f6dc9357SAndroid Build Coastguard Worker
130*f6dc9357SAndroid Build Coastguard Worker
Str_to_ValName(const AString & s,AString & name,AString & val)131*f6dc9357SAndroid Build Coastguard Worker static bool Str_to_ValName(const AString &s, AString &name, AString &val)
132*f6dc9357SAndroid Build Coastguard Worker {
133*f6dc9357SAndroid Build Coastguard Worker name.Empty();
134*f6dc9357SAndroid Build Coastguard Worker val.Empty();
135*f6dc9357SAndroid Build Coastguard Worker int qu = s.Find('"');
136*f6dc9357SAndroid Build Coastguard Worker int eq = s.Find('=');
137*f6dc9357SAndroid Build Coastguard Worker if (eq < 0 || (qu >= 0 && eq > qu))
138*f6dc9357SAndroid Build Coastguard Worker return false;
139*f6dc9357SAndroid Build Coastguard Worker name.SetFrom(s.Ptr(), eq);
140*f6dc9357SAndroid Build Coastguard Worker name.Trim();
141*f6dc9357SAndroid Build Coastguard Worker val = s.Ptr(eq + 1);
142*f6dc9357SAndroid Build Coastguard Worker val.Trim();
143*f6dc9357SAndroid Build Coastguard Worker return true;
144*f6dc9357SAndroid Build Coastguard Worker }
145*f6dc9357SAndroid Build Coastguard Worker
IsSpaceChar(char c)146*f6dc9357SAndroid Build Coastguard Worker static inline bool IsSpaceChar(char c)
147*f6dc9357SAndroid Build Coastguard Worker {
148*f6dc9357SAndroid Build Coastguard Worker return (c == ' ' || c == '\t');
149*f6dc9357SAndroid Build Coastguard Worker }
150*f6dc9357SAndroid Build Coastguard Worker
SkipSpaces(const char * s)151*f6dc9357SAndroid Build Coastguard Worker static const char *SkipSpaces(const char *s)
152*f6dc9357SAndroid Build Coastguard Worker {
153*f6dc9357SAndroid Build Coastguard Worker for (;; s++)
154*f6dc9357SAndroid Build Coastguard Worker {
155*f6dc9357SAndroid Build Coastguard Worker char c = *s;
156*f6dc9357SAndroid Build Coastguard Worker if (c == 0 || !IsSpaceChar(c))
157*f6dc9357SAndroid Build Coastguard Worker return s;
158*f6dc9357SAndroid Build Coastguard Worker }
159*f6dc9357SAndroid Build Coastguard Worker }
160*f6dc9357SAndroid Build Coastguard Worker
161*f6dc9357SAndroid Build Coastguard Worker #define SKIP_SPACES(s) s = SkipSpaces(s);
162*f6dc9357SAndroid Build Coastguard Worker
GetNextWord(const char * s,AString & dest)163*f6dc9357SAndroid Build Coastguard Worker static const char *GetNextWord(const char *s, AString &dest)
164*f6dc9357SAndroid Build Coastguard Worker {
165*f6dc9357SAndroid Build Coastguard Worker dest.Empty();
166*f6dc9357SAndroid Build Coastguard Worker SKIP_SPACES(s)
167*f6dc9357SAndroid Build Coastguard Worker const char *start = s;
168*f6dc9357SAndroid Build Coastguard Worker for (;; s++)
169*f6dc9357SAndroid Build Coastguard Worker {
170*f6dc9357SAndroid Build Coastguard Worker char c = *s;
171*f6dc9357SAndroid Build Coastguard Worker if (c == 0 || IsSpaceChar(c))
172*f6dc9357SAndroid Build Coastguard Worker {
173*f6dc9357SAndroid Build Coastguard Worker dest.SetFrom(start, (unsigned)(s - start));
174*f6dc9357SAndroid Build Coastguard Worker return s;
175*f6dc9357SAndroid Build Coastguard Worker }
176*f6dc9357SAndroid Build Coastguard Worker }
177*f6dc9357SAndroid Build Coastguard Worker }
178*f6dc9357SAndroid Build Coastguard Worker
GetNextNumber(const char * s,UInt64 & val)179*f6dc9357SAndroid Build Coastguard Worker static const char *GetNextNumber(const char *s, UInt64 &val)
180*f6dc9357SAndroid Build Coastguard Worker {
181*f6dc9357SAndroid Build Coastguard Worker SKIP_SPACES(s)
182*f6dc9357SAndroid Build Coastguard Worker if (*s == 0)
183*f6dc9357SAndroid Build Coastguard Worker return s;
184*f6dc9357SAndroid Build Coastguard Worker const char *end;
185*f6dc9357SAndroid Build Coastguard Worker val = ConvertStringToUInt64(s, &end);
186*f6dc9357SAndroid Build Coastguard Worker char c = *end;
187*f6dc9357SAndroid Build Coastguard Worker if (c != 0 && !IsSpaceChar(c))
188*f6dc9357SAndroid Build Coastguard Worker return NULL;
189*f6dc9357SAndroid Build Coastguard Worker return end;
190*f6dc9357SAndroid Build Coastguard Worker }
191*f6dc9357SAndroid Build Coastguard Worker
192*f6dc9357SAndroid Build Coastguard Worker
193*f6dc9357SAndroid Build Coastguard Worker struct CExtentInfo
194*f6dc9357SAndroid Build Coastguard Worker {
195*f6dc9357SAndroid Build Coastguard Worker AString Access; // RW, RDONLY, or NOACCESS
196*f6dc9357SAndroid Build Coastguard Worker UInt64 NumSectors; // 512 bytes sectors
197*f6dc9357SAndroid Build Coastguard Worker AString Type; // FLAT, SPARSE, ZERO, VMFS, VMFSSPARSE, VMFSRDM, VMFSRAW
198*f6dc9357SAndroid Build Coastguard Worker AString FileName;
199*f6dc9357SAndroid Build Coastguard Worker UInt64 StartSector; // used for FLAT
200*f6dc9357SAndroid Build Coastguard Worker
201*f6dc9357SAndroid Build Coastguard Worker // for VMWare Player 9:
202*f6dc9357SAndroid Build Coastguard Worker // PartitionUUID
203*f6dc9357SAndroid Build Coastguard Worker // DeviceIdentifier
204*f6dc9357SAndroid Build Coastguard Worker
IsType_ZERONArchive::NVmdk::CExtentInfo205*f6dc9357SAndroid Build Coastguard Worker bool IsType_ZERO() const { return Type == "ZERO"; }
206*f6dc9357SAndroid Build Coastguard Worker // bool IsType_FLAT() const { return Type == "FLAT"; }
IsType_FlatNArchive::NVmdk::CExtentInfo207*f6dc9357SAndroid Build Coastguard Worker bool IsType_Flat() const { return Type == "FLAT" || Type == "VMFS" || Type == "VMFSRAW"; }
208*f6dc9357SAndroid Build Coastguard Worker
209*f6dc9357SAndroid Build Coastguard Worker bool Parse(const char *s);
210*f6dc9357SAndroid Build Coastguard Worker };
211*f6dc9357SAndroid Build Coastguard Worker
Parse(const char * s)212*f6dc9357SAndroid Build Coastguard Worker bool CExtentInfo::Parse(const char *s)
213*f6dc9357SAndroid Build Coastguard Worker {
214*f6dc9357SAndroid Build Coastguard Worker NumSectors = 0;
215*f6dc9357SAndroid Build Coastguard Worker StartSector = 0;
216*f6dc9357SAndroid Build Coastguard Worker Access.Empty();
217*f6dc9357SAndroid Build Coastguard Worker Type.Empty();
218*f6dc9357SAndroid Build Coastguard Worker FileName.Empty();
219*f6dc9357SAndroid Build Coastguard Worker
220*f6dc9357SAndroid Build Coastguard Worker s = GetNextWord(s, Access);
221*f6dc9357SAndroid Build Coastguard Worker s = GetNextNumber(s, NumSectors);
222*f6dc9357SAndroid Build Coastguard Worker if (!s)
223*f6dc9357SAndroid Build Coastguard Worker return false;
224*f6dc9357SAndroid Build Coastguard Worker s = GetNextWord(s, Type);
225*f6dc9357SAndroid Build Coastguard Worker
226*f6dc9357SAndroid Build Coastguard Worker if (Type.IsEmpty())
227*f6dc9357SAndroid Build Coastguard Worker return false;
228*f6dc9357SAndroid Build Coastguard Worker
229*f6dc9357SAndroid Build Coastguard Worker SKIP_SPACES(s)
230*f6dc9357SAndroid Build Coastguard Worker
231*f6dc9357SAndroid Build Coastguard Worker if (IsType_ZERO())
232*f6dc9357SAndroid Build Coastguard Worker return (*s == 0);
233*f6dc9357SAndroid Build Coastguard Worker
234*f6dc9357SAndroid Build Coastguard Worker if (*s != '\"')
235*f6dc9357SAndroid Build Coastguard Worker return false;
236*f6dc9357SAndroid Build Coastguard Worker s++;
237*f6dc9357SAndroid Build Coastguard Worker {
238*f6dc9357SAndroid Build Coastguard Worker const char *s2 = strchr(s, '\"');
239*f6dc9357SAndroid Build Coastguard Worker if (!s2)
240*f6dc9357SAndroid Build Coastguard Worker return false;
241*f6dc9357SAndroid Build Coastguard Worker FileName.SetFrom(s, (unsigned)(s2 - s));
242*f6dc9357SAndroid Build Coastguard Worker s = s2 + 1;
243*f6dc9357SAndroid Build Coastguard Worker }
244*f6dc9357SAndroid Build Coastguard Worker SKIP_SPACES(s)
245*f6dc9357SAndroid Build Coastguard Worker if (*s == 0)
246*f6dc9357SAndroid Build Coastguard Worker return true;
247*f6dc9357SAndroid Build Coastguard Worker
248*f6dc9357SAndroid Build Coastguard Worker s = GetNextNumber(s, StartSector);
249*f6dc9357SAndroid Build Coastguard Worker if (!s)
250*f6dc9357SAndroid Build Coastguard Worker return false;
251*f6dc9357SAndroid Build Coastguard Worker return true;
252*f6dc9357SAndroid Build Coastguard Worker // SKIP_SPACES(s);
253*f6dc9357SAndroid Build Coastguard Worker // return (*s == 0);
254*f6dc9357SAndroid Build Coastguard Worker }
255*f6dc9357SAndroid Build Coastguard Worker
256*f6dc9357SAndroid Build Coastguard Worker
257*f6dc9357SAndroid Build Coastguard Worker struct CDescriptor
258*f6dc9357SAndroid Build Coastguard Worker {
259*f6dc9357SAndroid Build Coastguard Worker AString CID;
260*f6dc9357SAndroid Build Coastguard Worker AString parentCID;
261*f6dc9357SAndroid Build Coastguard Worker AString createType;
262*f6dc9357SAndroid Build Coastguard Worker // AString encoding; // UTF-8, windows-1252 - default is UTF-8
263*f6dc9357SAndroid Build Coastguard Worker
264*f6dc9357SAndroid Build Coastguard Worker CObjectVector<CExtentInfo> Extents;
265*f6dc9357SAndroid Build Coastguard Worker
GetUnicodeNameNArchive::NVmdk::CDescriptor266*f6dc9357SAndroid Build Coastguard Worker static void GetUnicodeName(const AString &s, UString &res)
267*f6dc9357SAndroid Build Coastguard Worker {
268*f6dc9357SAndroid Build Coastguard Worker if (!ConvertUTF8ToUnicode(s, res))
269*f6dc9357SAndroid Build Coastguard Worker MultiByteToUnicodeString2(res, s);
270*f6dc9357SAndroid Build Coastguard Worker }
271*f6dc9357SAndroid Build Coastguard Worker
ClearNArchive::NVmdk::CDescriptor272*f6dc9357SAndroid Build Coastguard Worker void Clear()
273*f6dc9357SAndroid Build Coastguard Worker {
274*f6dc9357SAndroid Build Coastguard Worker CID.Empty();
275*f6dc9357SAndroid Build Coastguard Worker parentCID.Empty();
276*f6dc9357SAndroid Build Coastguard Worker createType.Empty();
277*f6dc9357SAndroid Build Coastguard Worker Extents.Clear();
278*f6dc9357SAndroid Build Coastguard Worker }
279*f6dc9357SAndroid Build Coastguard Worker
IsThere_ParentNArchive::NVmdk::CDescriptor280*f6dc9357SAndroid Build Coastguard Worker bool IsThere_Parent() const
281*f6dc9357SAndroid Build Coastguard Worker {
282*f6dc9357SAndroid Build Coastguard Worker return !parentCID.IsEmpty() && !parentCID.IsEqualTo_Ascii_NoCase("ffffffff");
283*f6dc9357SAndroid Build Coastguard Worker }
284*f6dc9357SAndroid Build Coastguard Worker
285*f6dc9357SAndroid Build Coastguard Worker bool Parse(const Byte *p, size_t size);
286*f6dc9357SAndroid Build Coastguard Worker };
287*f6dc9357SAndroid Build Coastguard Worker
288*f6dc9357SAndroid Build Coastguard Worker
Parse(const Byte * p,size_t size)289*f6dc9357SAndroid Build Coastguard Worker bool CDescriptor::Parse(const Byte *p, size_t size)
290*f6dc9357SAndroid Build Coastguard Worker {
291*f6dc9357SAndroid Build Coastguard Worker Clear();
292*f6dc9357SAndroid Build Coastguard Worker
293*f6dc9357SAndroid Build Coastguard Worker AString s;
294*f6dc9357SAndroid Build Coastguard Worker AString name;
295*f6dc9357SAndroid Build Coastguard Worker AString val;
296*f6dc9357SAndroid Build Coastguard Worker
297*f6dc9357SAndroid Build Coastguard Worker for (;;)
298*f6dc9357SAndroid Build Coastguard Worker {
299*f6dc9357SAndroid Build Coastguard Worker Byte c = 0;
300*f6dc9357SAndroid Build Coastguard Worker if (size != 0)
301*f6dc9357SAndroid Build Coastguard Worker {
302*f6dc9357SAndroid Build Coastguard Worker size--;
303*f6dc9357SAndroid Build Coastguard Worker c = *p++;
304*f6dc9357SAndroid Build Coastguard Worker }
305*f6dc9357SAndroid Build Coastguard Worker if (c == 0 || c == 0xA || c == 0xD)
306*f6dc9357SAndroid Build Coastguard Worker {
307*f6dc9357SAndroid Build Coastguard Worker if (!s.IsEmpty() && s[0] != '#')
308*f6dc9357SAndroid Build Coastguard Worker {
309*f6dc9357SAndroid Build Coastguard Worker if (Str_to_ValName(s, name, val))
310*f6dc9357SAndroid Build Coastguard Worker {
311*f6dc9357SAndroid Build Coastguard Worker if (name.IsEqualTo_Ascii_NoCase("CID"))
312*f6dc9357SAndroid Build Coastguard Worker CID = val;
313*f6dc9357SAndroid Build Coastguard Worker else if (name.IsEqualTo_Ascii_NoCase("parentCID"))
314*f6dc9357SAndroid Build Coastguard Worker parentCID = val;
315*f6dc9357SAndroid Build Coastguard Worker else if (name.IsEqualTo_Ascii_NoCase("createType"))
316*f6dc9357SAndroid Build Coastguard Worker createType = val;
317*f6dc9357SAndroid Build Coastguard Worker }
318*f6dc9357SAndroid Build Coastguard Worker else
319*f6dc9357SAndroid Build Coastguard Worker {
320*f6dc9357SAndroid Build Coastguard Worker CExtentInfo ei;
321*f6dc9357SAndroid Build Coastguard Worker if (!ei.Parse(s))
322*f6dc9357SAndroid Build Coastguard Worker return false;
323*f6dc9357SAndroid Build Coastguard Worker Extents.Add(ei);
324*f6dc9357SAndroid Build Coastguard Worker }
325*f6dc9357SAndroid Build Coastguard Worker }
326*f6dc9357SAndroid Build Coastguard Worker
327*f6dc9357SAndroid Build Coastguard Worker s.Empty();
328*f6dc9357SAndroid Build Coastguard Worker if (c == 0)
329*f6dc9357SAndroid Build Coastguard Worker return true;
330*f6dc9357SAndroid Build Coastguard Worker }
331*f6dc9357SAndroid Build Coastguard Worker else
332*f6dc9357SAndroid Build Coastguard Worker s += (char)c;
333*f6dc9357SAndroid Build Coastguard Worker }
334*f6dc9357SAndroid Build Coastguard Worker }
335*f6dc9357SAndroid Build Coastguard Worker
336*f6dc9357SAndroid Build Coastguard Worker
337*f6dc9357SAndroid Build Coastguard Worker struct CExtent
338*f6dc9357SAndroid Build Coastguard Worker {
339*f6dc9357SAndroid Build Coastguard Worker bool IsOK;
340*f6dc9357SAndroid Build Coastguard Worker bool IsArc;
341*f6dc9357SAndroid Build Coastguard Worker bool NeedDeflate;
342*f6dc9357SAndroid Build Coastguard Worker bool Unsupported;
343*f6dc9357SAndroid Build Coastguard Worker bool IsZero;
344*f6dc9357SAndroid Build Coastguard Worker bool IsFlat;
345*f6dc9357SAndroid Build Coastguard Worker bool DescriptorOK;
346*f6dc9357SAndroid Build Coastguard Worker bool HeadersError;
347*f6dc9357SAndroid Build Coastguard Worker
348*f6dc9357SAndroid Build Coastguard Worker unsigned ClusterBits;
349*f6dc9357SAndroid Build Coastguard Worker UInt32 ZeroSector;
350*f6dc9357SAndroid Build Coastguard Worker
351*f6dc9357SAndroid Build Coastguard Worker CObjectVector<CByteBuffer> Tables;
352*f6dc9357SAndroid Build Coastguard Worker
353*f6dc9357SAndroid Build Coastguard Worker CMyComPtr<IInStream> Stream;
354*f6dc9357SAndroid Build Coastguard Worker UInt64 PosInArc;
355*f6dc9357SAndroid Build Coastguard Worker
356*f6dc9357SAndroid Build Coastguard Worker UInt64 PhySize;
357*f6dc9357SAndroid Build Coastguard Worker UInt64 VirtSize; // from vmdk header of volume
358*f6dc9357SAndroid Build Coastguard Worker
359*f6dc9357SAndroid Build Coastguard Worker UInt64 StartOffset; // virtual offset of this extent
360*f6dc9357SAndroid Build Coastguard Worker UInt64 NumBytes; // from main descriptor, if multi-vol
361*f6dc9357SAndroid Build Coastguard Worker UInt64 FlatOffset; // in Stream
362*f6dc9357SAndroid Build Coastguard Worker
363*f6dc9357SAndroid Build Coastguard Worker CByteBuffer DescriptorBuf;
364*f6dc9357SAndroid Build Coastguard Worker CDescriptor Descriptor;
365*f6dc9357SAndroid Build Coastguard Worker
366*f6dc9357SAndroid Build Coastguard Worker CHeader h;
367*f6dc9357SAndroid Build Coastguard Worker
GetEndOffsetNArchive::NVmdk::CExtent368*f6dc9357SAndroid Build Coastguard Worker UInt64 GetEndOffset() const { return StartOffset + NumBytes; }
369*f6dc9357SAndroid Build Coastguard Worker
IsVmdkNArchive::NVmdk::CExtent370*f6dc9357SAndroid Build Coastguard Worker bool IsVmdk() const { return !IsZero && !IsFlat; }
371*f6dc9357SAndroid Build Coastguard Worker // if (IsOK && IsVmdk()), then VMDK header of this extent was read
372*f6dc9357SAndroid Build Coastguard Worker
CExtentNArchive::NVmdk::CExtent373*f6dc9357SAndroid Build Coastguard Worker CExtent():
374*f6dc9357SAndroid Build Coastguard Worker IsOK(false),
375*f6dc9357SAndroid Build Coastguard Worker IsArc(false),
376*f6dc9357SAndroid Build Coastguard Worker NeedDeflate(false),
377*f6dc9357SAndroid Build Coastguard Worker Unsupported(false),
378*f6dc9357SAndroid Build Coastguard Worker IsZero(false),
379*f6dc9357SAndroid Build Coastguard Worker IsFlat(false),
380*f6dc9357SAndroid Build Coastguard Worker DescriptorOK(false),
381*f6dc9357SAndroid Build Coastguard Worker HeadersError(false),
382*f6dc9357SAndroid Build Coastguard Worker
383*f6dc9357SAndroid Build Coastguard Worker ClusterBits(0),
384*f6dc9357SAndroid Build Coastguard Worker ZeroSector(0),
385*f6dc9357SAndroid Build Coastguard Worker
386*f6dc9357SAndroid Build Coastguard Worker PosInArc(0),
387*f6dc9357SAndroid Build Coastguard Worker
388*f6dc9357SAndroid Build Coastguard Worker PhySize(0),
389*f6dc9357SAndroid Build Coastguard Worker VirtSize(0),
390*f6dc9357SAndroid Build Coastguard Worker
391*f6dc9357SAndroid Build Coastguard Worker StartOffset(0),
392*f6dc9357SAndroid Build Coastguard Worker NumBytes(0),
393*f6dc9357SAndroid Build Coastguard Worker FlatOffset(0)
394*f6dc9357SAndroid Build Coastguard Worker {}
395*f6dc9357SAndroid Build Coastguard Worker
396*f6dc9357SAndroid Build Coastguard Worker
397*f6dc9357SAndroid Build Coastguard Worker HRESULT ReadForHeader(IInStream *stream, UInt64 sector, void *data, size_t numSectors);
398*f6dc9357SAndroid Build Coastguard Worker HRESULT Open3(IInStream *stream, IArchiveOpenCallback *openCallback,
399*f6dc9357SAndroid Build Coastguard Worker unsigned numVols, unsigned volIndex, UInt64 &complexity);
400*f6dc9357SAndroid Build Coastguard Worker
SeekNArchive::NVmdk::CExtent401*f6dc9357SAndroid Build Coastguard Worker HRESULT Seek(UInt64 offset)
402*f6dc9357SAndroid Build Coastguard Worker {
403*f6dc9357SAndroid Build Coastguard Worker PosInArc = offset;
404*f6dc9357SAndroid Build Coastguard Worker return InStream_SeekSet(Stream, offset);
405*f6dc9357SAndroid Build Coastguard Worker }
406*f6dc9357SAndroid Build Coastguard Worker
InitAndSeekNArchive::NVmdk::CExtent407*f6dc9357SAndroid Build Coastguard Worker HRESULT InitAndSeek()
408*f6dc9357SAndroid Build Coastguard Worker {
409*f6dc9357SAndroid Build Coastguard Worker if (Stream)
410*f6dc9357SAndroid Build Coastguard Worker return Seek(0);
411*f6dc9357SAndroid Build Coastguard Worker return S_OK;
412*f6dc9357SAndroid Build Coastguard Worker }
413*f6dc9357SAndroid Build Coastguard Worker
ReadNArchive::NVmdk::CExtent414*f6dc9357SAndroid Build Coastguard Worker HRESULT Read(void *data, size_t *size)
415*f6dc9357SAndroid Build Coastguard Worker {
416*f6dc9357SAndroid Build Coastguard Worker HRESULT res = ReadStream(Stream, data, size);
417*f6dc9357SAndroid Build Coastguard Worker PosInArc += *size;
418*f6dc9357SAndroid Build Coastguard Worker return res;
419*f6dc9357SAndroid Build Coastguard Worker }
420*f6dc9357SAndroid Build Coastguard Worker };
421*f6dc9357SAndroid Build Coastguard Worker
422*f6dc9357SAndroid Build Coastguard Worker
423*f6dc9357SAndroid Build Coastguard Worker Z7_class_CHandler_final: public CHandlerImg
424*f6dc9357SAndroid Build Coastguard Worker {
425*f6dc9357SAndroid Build Coastguard Worker bool _isArc;
426*f6dc9357SAndroid Build Coastguard Worker bool _unsupported;
427*f6dc9357SAndroid Build Coastguard Worker bool _unsupportedSome;
428*f6dc9357SAndroid Build Coastguard Worker bool _headerError;
429*f6dc9357SAndroid Build Coastguard Worker bool _missingVol;
430*f6dc9357SAndroid Build Coastguard Worker bool _isMultiVol;
431*f6dc9357SAndroid Build Coastguard Worker bool _needDeflate;
432*f6dc9357SAndroid Build Coastguard Worker
433*f6dc9357SAndroid Build Coastguard Worker UInt64 _cacheCluster;
434*f6dc9357SAndroid Build Coastguard Worker unsigned _cacheExtent;
435*f6dc9357SAndroid Build Coastguard Worker CByteBuffer _cache;
436*f6dc9357SAndroid Build Coastguard Worker CByteBuffer _cacheCompressed;
437*f6dc9357SAndroid Build Coastguard Worker
438*f6dc9357SAndroid Build Coastguard Worker unsigned _clusterBitsMax;
439*f6dc9357SAndroid Build Coastguard Worker UInt64 _phySize;
440*f6dc9357SAndroid Build Coastguard Worker
441*f6dc9357SAndroid Build Coastguard Worker CObjectVector<CExtent> _extents;
442*f6dc9357SAndroid Build Coastguard Worker
443*f6dc9357SAndroid Build Coastguard Worker CBufInStream *_bufInStreamSpec;
444*f6dc9357SAndroid Build Coastguard Worker CMyComPtr<ISequentialInStream> _bufInStream;
445*f6dc9357SAndroid Build Coastguard Worker
446*f6dc9357SAndroid Build Coastguard Worker CBufPtrSeqOutStream *_bufOutStreamSpec;
447*f6dc9357SAndroid Build Coastguard Worker CMyComPtr<ISequentialOutStream> _bufOutStream;
448*f6dc9357SAndroid Build Coastguard Worker
449*f6dc9357SAndroid Build Coastguard Worker NCompress::NZlib::CDecoder *_zlibDecoderSpec;
450*f6dc9357SAndroid Build Coastguard Worker CMyComPtr<ICompressCoder> _zlibDecoder;
451*f6dc9357SAndroid Build Coastguard Worker
452*f6dc9357SAndroid Build Coastguard Worker CByteBuffer _descriptorBuf;
453*f6dc9357SAndroid Build Coastguard Worker CDescriptor _descriptor;
454*f6dc9357SAndroid Build Coastguard Worker
455*f6dc9357SAndroid Build Coastguard Worker UString _missingVolName;
456*f6dc9357SAndroid Build Coastguard Worker
457*f6dc9357SAndroid Build Coastguard Worker void InitAndSeekMain()
458*f6dc9357SAndroid Build Coastguard Worker {
459*f6dc9357SAndroid Build Coastguard Worker _virtPos = 0;
460*f6dc9357SAndroid Build Coastguard Worker }
461*f6dc9357SAndroid Build Coastguard Worker
462*f6dc9357SAndroid Build Coastguard Worker virtual HRESULT Open2(IInStream *stream, IArchiveOpenCallback *openCallback) Z7_override;
463*f6dc9357SAndroid Build Coastguard Worker virtual void CloseAtError() Z7_override;
464*f6dc9357SAndroid Build Coastguard Worker public:
465*f6dc9357SAndroid Build Coastguard Worker Z7_IFACE_COM7_IMP(IInArchive_Img)
466*f6dc9357SAndroid Build Coastguard Worker
467*f6dc9357SAndroid Build Coastguard Worker Z7_IFACE_COM7_IMP(IInArchiveGetStream)
468*f6dc9357SAndroid Build Coastguard Worker Z7_IFACE_COM7_IMP(ISequentialInStream)
469*f6dc9357SAndroid Build Coastguard Worker };
470*f6dc9357SAndroid Build Coastguard Worker
471*f6dc9357SAndroid Build Coastguard Worker
472*f6dc9357SAndroid Build Coastguard Worker Z7_COM7F_IMF(CHandler::Read(void *data, UInt32 size, UInt32 *processedSize))
473*f6dc9357SAndroid Build Coastguard Worker {
474*f6dc9357SAndroid Build Coastguard Worker if (processedSize)
475*f6dc9357SAndroid Build Coastguard Worker *processedSize = 0;
476*f6dc9357SAndroid Build Coastguard Worker if (_virtPos >= _size)
477*f6dc9357SAndroid Build Coastguard Worker return S_OK;
478*f6dc9357SAndroid Build Coastguard Worker {
479*f6dc9357SAndroid Build Coastguard Worker UInt64 rem = _size - _virtPos;
480*f6dc9357SAndroid Build Coastguard Worker if (size > rem)
481*f6dc9357SAndroid Build Coastguard Worker size = (UInt32)rem;
482*f6dc9357SAndroid Build Coastguard Worker if (size == 0)
483*f6dc9357SAndroid Build Coastguard Worker return S_OK;
484*f6dc9357SAndroid Build Coastguard Worker }
485*f6dc9357SAndroid Build Coastguard Worker
486*f6dc9357SAndroid Build Coastguard Worker unsigned extentIndex;
487*f6dc9357SAndroid Build Coastguard Worker {
488*f6dc9357SAndroid Build Coastguard Worker unsigned left = 0, right = _extents.Size();
489*f6dc9357SAndroid Build Coastguard Worker for (;;)
490*f6dc9357SAndroid Build Coastguard Worker {
491*f6dc9357SAndroid Build Coastguard Worker unsigned mid = (left + right) / 2;
492*f6dc9357SAndroid Build Coastguard Worker if (mid == left)
493*f6dc9357SAndroid Build Coastguard Worker break;
494*f6dc9357SAndroid Build Coastguard Worker if (_virtPos < _extents[mid].StartOffset)
495*f6dc9357SAndroid Build Coastguard Worker right = mid;
496*f6dc9357SAndroid Build Coastguard Worker else
497*f6dc9357SAndroid Build Coastguard Worker left = mid;
498*f6dc9357SAndroid Build Coastguard Worker }
499*f6dc9357SAndroid Build Coastguard Worker extentIndex = left;
500*f6dc9357SAndroid Build Coastguard Worker }
501*f6dc9357SAndroid Build Coastguard Worker
502*f6dc9357SAndroid Build Coastguard Worker CExtent &extent = _extents[extentIndex];
503*f6dc9357SAndroid Build Coastguard Worker
504*f6dc9357SAndroid Build Coastguard Worker {
505*f6dc9357SAndroid Build Coastguard Worker const UInt64 vir = _virtPos - extent.StartOffset;
506*f6dc9357SAndroid Build Coastguard Worker if (vir >= extent.NumBytes)
507*f6dc9357SAndroid Build Coastguard Worker {
508*f6dc9357SAndroid Build Coastguard Worker return E_FAIL;
509*f6dc9357SAndroid Build Coastguard Worker /*
510*f6dc9357SAndroid Build Coastguard Worker if (vir > extent.NumBytes)
511*f6dc9357SAndroid Build Coastguard Worker _stream_dataError = true;
512*f6dc9357SAndroid Build Coastguard Worker memset(data, 0, size);
513*f6dc9357SAndroid Build Coastguard Worker _virtPos += size;
514*f6dc9357SAndroid Build Coastguard Worker if (processedSize)
515*f6dc9357SAndroid Build Coastguard Worker *processedSize = size;
516*f6dc9357SAndroid Build Coastguard Worker return S_OK;
517*f6dc9357SAndroid Build Coastguard Worker */
518*f6dc9357SAndroid Build Coastguard Worker }
519*f6dc9357SAndroid Build Coastguard Worker
520*f6dc9357SAndroid Build Coastguard Worker {
521*f6dc9357SAndroid Build Coastguard Worker const UInt64 rem = extent.NumBytes - vir;
522*f6dc9357SAndroid Build Coastguard Worker if (size > rem)
523*f6dc9357SAndroid Build Coastguard Worker size = (UInt32)rem;
524*f6dc9357SAndroid Build Coastguard Worker }
525*f6dc9357SAndroid Build Coastguard Worker
526*f6dc9357SAndroid Build Coastguard Worker if (vir >= extent.VirtSize)
527*f6dc9357SAndroid Build Coastguard Worker {
528*f6dc9357SAndroid Build Coastguard Worker // if vmdk's VirtSize is smaller than VirtSize from main multi-volume descriptor
529*f6dc9357SAndroid Build Coastguard Worker _stream_dataError = true;
530*f6dc9357SAndroid Build Coastguard Worker return S_FALSE;
531*f6dc9357SAndroid Build Coastguard Worker /*
532*f6dc9357SAndroid Build Coastguard Worker memset(data, 0, size);
533*f6dc9357SAndroid Build Coastguard Worker _virtPos += size;
534*f6dc9357SAndroid Build Coastguard Worker if (processedSize)
535*f6dc9357SAndroid Build Coastguard Worker *processedSize = size;
536*f6dc9357SAndroid Build Coastguard Worker return S_OK;
537*f6dc9357SAndroid Build Coastguard Worker */
538*f6dc9357SAndroid Build Coastguard Worker }
539*f6dc9357SAndroid Build Coastguard Worker
540*f6dc9357SAndroid Build Coastguard Worker {
541*f6dc9357SAndroid Build Coastguard Worker const UInt64 rem = extent.VirtSize - vir;
542*f6dc9357SAndroid Build Coastguard Worker if (size > rem)
543*f6dc9357SAndroid Build Coastguard Worker size = (UInt32)rem;
544*f6dc9357SAndroid Build Coastguard Worker }
545*f6dc9357SAndroid Build Coastguard Worker
546*f6dc9357SAndroid Build Coastguard Worker if (extent.IsZero || !extent.IsOK || !extent.Stream || extent.Unsupported)
547*f6dc9357SAndroid Build Coastguard Worker {
548*f6dc9357SAndroid Build Coastguard Worker if (extent.Unsupported)
549*f6dc9357SAndroid Build Coastguard Worker {
550*f6dc9357SAndroid Build Coastguard Worker _stream_unsupportedMethod = true;
551*f6dc9357SAndroid Build Coastguard Worker return S_FALSE;
552*f6dc9357SAndroid Build Coastguard Worker }
553*f6dc9357SAndroid Build Coastguard Worker if (!extent.IsOK || !extent.Stream)
554*f6dc9357SAndroid Build Coastguard Worker {
555*f6dc9357SAndroid Build Coastguard Worker _stream_unavailData = true;
556*f6dc9357SAndroid Build Coastguard Worker return S_FALSE;
557*f6dc9357SAndroid Build Coastguard Worker }
558*f6dc9357SAndroid Build Coastguard Worker memset(data, 0, size);
559*f6dc9357SAndroid Build Coastguard Worker _virtPos += size;
560*f6dc9357SAndroid Build Coastguard Worker if (processedSize)
561*f6dc9357SAndroid Build Coastguard Worker *processedSize = size;
562*f6dc9357SAndroid Build Coastguard Worker return S_OK;
563*f6dc9357SAndroid Build Coastguard Worker }
564*f6dc9357SAndroid Build Coastguard Worker
565*f6dc9357SAndroid Build Coastguard Worker if (extent.IsFlat)
566*f6dc9357SAndroid Build Coastguard Worker {
567*f6dc9357SAndroid Build Coastguard Worker UInt64 offset = extent.FlatOffset + vir;
568*f6dc9357SAndroid Build Coastguard Worker if (offset != extent.PosInArc)
569*f6dc9357SAndroid Build Coastguard Worker {
570*f6dc9357SAndroid Build Coastguard Worker RINOK(extent.Seek(offset))
571*f6dc9357SAndroid Build Coastguard Worker }
572*f6dc9357SAndroid Build Coastguard Worker UInt32 size2 = 0;
573*f6dc9357SAndroid Build Coastguard Worker HRESULT res = extent.Stream->Read(data, size, &size2);
574*f6dc9357SAndroid Build Coastguard Worker if (res == S_OK && size2 == 0)
575*f6dc9357SAndroid Build Coastguard Worker {
576*f6dc9357SAndroid Build Coastguard Worker _stream_unavailData = true;
577*f6dc9357SAndroid Build Coastguard Worker /*
578*f6dc9357SAndroid Build Coastguard Worker memset(data, 0, size);
579*f6dc9357SAndroid Build Coastguard Worker _virtPos += size;
580*f6dc9357SAndroid Build Coastguard Worker if (processedSize)
581*f6dc9357SAndroid Build Coastguard Worker *processedSize = size;
582*f6dc9357SAndroid Build Coastguard Worker return S_OK;
583*f6dc9357SAndroid Build Coastguard Worker */
584*f6dc9357SAndroid Build Coastguard Worker }
585*f6dc9357SAndroid Build Coastguard Worker // _stream_PackSize += size2;
586*f6dc9357SAndroid Build Coastguard Worker extent.PosInArc += size2;
587*f6dc9357SAndroid Build Coastguard Worker _virtPos += size2;
588*f6dc9357SAndroid Build Coastguard Worker if (processedSize)
589*f6dc9357SAndroid Build Coastguard Worker *processedSize = size2;
590*f6dc9357SAndroid Build Coastguard Worker return res;
591*f6dc9357SAndroid Build Coastguard Worker }
592*f6dc9357SAndroid Build Coastguard Worker }
593*f6dc9357SAndroid Build Coastguard Worker
594*f6dc9357SAndroid Build Coastguard Worker
595*f6dc9357SAndroid Build Coastguard Worker for (;;)
596*f6dc9357SAndroid Build Coastguard Worker {
597*f6dc9357SAndroid Build Coastguard Worker const UInt64 vir = _virtPos - extent.StartOffset;
598*f6dc9357SAndroid Build Coastguard Worker const unsigned clusterBits = extent.ClusterBits;
599*f6dc9357SAndroid Build Coastguard Worker const UInt64 cluster = vir >> clusterBits;
600*f6dc9357SAndroid Build Coastguard Worker const size_t clusterSize = (size_t)1 << clusterBits;
601*f6dc9357SAndroid Build Coastguard Worker const size_t lowBits = (size_t)vir & (clusterSize - 1);
602*f6dc9357SAndroid Build Coastguard Worker {
603*f6dc9357SAndroid Build Coastguard Worker size_t rem = clusterSize - lowBits;
604*f6dc9357SAndroid Build Coastguard Worker if (size > rem)
605*f6dc9357SAndroid Build Coastguard Worker size = (UInt32)rem;
606*f6dc9357SAndroid Build Coastguard Worker }
607*f6dc9357SAndroid Build Coastguard Worker
608*f6dc9357SAndroid Build Coastguard Worker if (extentIndex == _cacheExtent && cluster == _cacheCluster)
609*f6dc9357SAndroid Build Coastguard Worker {
610*f6dc9357SAndroid Build Coastguard Worker memcpy(data, _cache + lowBits, size);
611*f6dc9357SAndroid Build Coastguard Worker _virtPos += size;
612*f6dc9357SAndroid Build Coastguard Worker if (processedSize)
613*f6dc9357SAndroid Build Coastguard Worker *processedSize = size;
614*f6dc9357SAndroid Build Coastguard Worker return S_OK;
615*f6dc9357SAndroid Build Coastguard Worker }
616*f6dc9357SAndroid Build Coastguard Worker
617*f6dc9357SAndroid Build Coastguard Worker const UInt64 high = cluster >> k_NumMidBits;
618*f6dc9357SAndroid Build Coastguard Worker
619*f6dc9357SAndroid Build Coastguard Worker if (high < extent.Tables.Size())
620*f6dc9357SAndroid Build Coastguard Worker {
621*f6dc9357SAndroid Build Coastguard Worker const CByteBuffer &table = extent.Tables[(unsigned)high];
622*f6dc9357SAndroid Build Coastguard Worker
623*f6dc9357SAndroid Build Coastguard Worker if (table.Size() != 0)
624*f6dc9357SAndroid Build Coastguard Worker {
625*f6dc9357SAndroid Build Coastguard Worker const size_t midBits = (size_t)cluster & ((1 << k_NumMidBits) - 1);
626*f6dc9357SAndroid Build Coastguard Worker const Byte *p = (const Byte *)table + (midBits << 2);
627*f6dc9357SAndroid Build Coastguard Worker const UInt32 v = Get32(p);
628*f6dc9357SAndroid Build Coastguard Worker
629*f6dc9357SAndroid Build Coastguard Worker if (v != 0 && v != extent.ZeroSector)
630*f6dc9357SAndroid Build Coastguard Worker {
631*f6dc9357SAndroid Build Coastguard Worker UInt64 offset = (UInt64)v << 9;
632*f6dc9357SAndroid Build Coastguard Worker if (extent.NeedDeflate)
633*f6dc9357SAndroid Build Coastguard Worker {
634*f6dc9357SAndroid Build Coastguard Worker if (offset != extent.PosInArc)
635*f6dc9357SAndroid Build Coastguard Worker {
636*f6dc9357SAndroid Build Coastguard Worker // printf("\n%12x %12x\n", (unsigned)offset, (unsigned)(offset - extent.PosInArc));
637*f6dc9357SAndroid Build Coastguard Worker RINOK(extent.Seek(offset))
638*f6dc9357SAndroid Build Coastguard Worker }
639*f6dc9357SAndroid Build Coastguard Worker
640*f6dc9357SAndroid Build Coastguard Worker const size_t kStartSize = 1 << 9;
641*f6dc9357SAndroid Build Coastguard Worker {
642*f6dc9357SAndroid Build Coastguard Worker size_t curSize = kStartSize;
643*f6dc9357SAndroid Build Coastguard Worker RINOK(extent.Read(_cacheCompressed, &curSize))
644*f6dc9357SAndroid Build Coastguard Worker // _stream_PackSize += curSize;
645*f6dc9357SAndroid Build Coastguard Worker if (curSize != kStartSize)
646*f6dc9357SAndroid Build Coastguard Worker return S_FALSE;
647*f6dc9357SAndroid Build Coastguard Worker }
648*f6dc9357SAndroid Build Coastguard Worker
649*f6dc9357SAndroid Build Coastguard Worker if (Get64(_cacheCompressed) != (cluster << (clusterBits - 9)))
650*f6dc9357SAndroid Build Coastguard Worker return S_FALSE;
651*f6dc9357SAndroid Build Coastguard Worker
652*f6dc9357SAndroid Build Coastguard Worker UInt32 dataSize = Get32(_cacheCompressed + 8);
653*f6dc9357SAndroid Build Coastguard Worker if (dataSize > ((UInt32)1 << 31))
654*f6dc9357SAndroid Build Coastguard Worker return S_FALSE;
655*f6dc9357SAndroid Build Coastguard Worker
656*f6dc9357SAndroid Build Coastguard Worker size_t dataSize2 = (size_t)dataSize + 12;
657*f6dc9357SAndroid Build Coastguard Worker
658*f6dc9357SAndroid Build Coastguard Worker if (dataSize2 > kStartSize)
659*f6dc9357SAndroid Build Coastguard Worker {
660*f6dc9357SAndroid Build Coastguard Worker dataSize2 = (dataSize2 + 511) & ~(size_t)511;
661*f6dc9357SAndroid Build Coastguard Worker if (dataSize2 > _cacheCompressed.Size())
662*f6dc9357SAndroid Build Coastguard Worker return S_FALSE;
663*f6dc9357SAndroid Build Coastguard Worker size_t curSize = dataSize2 - kStartSize;
664*f6dc9357SAndroid Build Coastguard Worker const size_t curSize2 = curSize;
665*f6dc9357SAndroid Build Coastguard Worker RINOK(extent.Read(_cacheCompressed + kStartSize, &curSize))
666*f6dc9357SAndroid Build Coastguard Worker // _stream_PackSize += curSize;
667*f6dc9357SAndroid Build Coastguard Worker if (curSize != curSize2)
668*f6dc9357SAndroid Build Coastguard Worker return S_FALSE;
669*f6dc9357SAndroid Build Coastguard Worker }
670*f6dc9357SAndroid Build Coastguard Worker
671*f6dc9357SAndroid Build Coastguard Worker _bufInStreamSpec->Init(_cacheCompressed + 12, dataSize);
672*f6dc9357SAndroid Build Coastguard Worker
673*f6dc9357SAndroid Build Coastguard Worker _cacheCluster = (UInt64)(Int64)-1;
674*f6dc9357SAndroid Build Coastguard Worker _cacheExtent = (unsigned)(int)-1;
675*f6dc9357SAndroid Build Coastguard Worker
676*f6dc9357SAndroid Build Coastguard Worker if (_cache.Size() < clusterSize)
677*f6dc9357SAndroid Build Coastguard Worker return E_FAIL;
678*f6dc9357SAndroid Build Coastguard Worker _bufOutStreamSpec->Init(_cache, clusterSize);
679*f6dc9357SAndroid Build Coastguard Worker
680*f6dc9357SAndroid Build Coastguard Worker // Do we need to use smaller block than clusterSize for last cluster?
681*f6dc9357SAndroid Build Coastguard Worker const UInt64 blockSize64 = clusterSize;
682*f6dc9357SAndroid Build Coastguard Worker HRESULT res = _zlibDecoder->Code(_bufInStream, _bufOutStream, NULL, &blockSize64, NULL);
683*f6dc9357SAndroid Build Coastguard Worker
684*f6dc9357SAndroid Build Coastguard Worker /*
685*f6dc9357SAndroid Build Coastguard Worker if (_bufOutStreamSpec->GetPos() != clusterSize)
686*f6dc9357SAndroid Build Coastguard Worker {
687*f6dc9357SAndroid Build Coastguard Worker _stream_dataError = true;
688*f6dc9357SAndroid Build Coastguard Worker memset(_cache + _bufOutStreamSpec->GetPos(), 0, clusterSize - _bufOutStreamSpec->GetPos());
689*f6dc9357SAndroid Build Coastguard Worker }
690*f6dc9357SAndroid Build Coastguard Worker */
691*f6dc9357SAndroid Build Coastguard Worker
692*f6dc9357SAndroid Build Coastguard Worker if (_bufOutStreamSpec->GetPos() != clusterSize
693*f6dc9357SAndroid Build Coastguard Worker || _zlibDecoderSpec->GetInputProcessedSize() != dataSize)
694*f6dc9357SAndroid Build Coastguard Worker {
695*f6dc9357SAndroid Build Coastguard Worker _stream_dataError = true;
696*f6dc9357SAndroid Build Coastguard Worker if (res == S_OK)
697*f6dc9357SAndroid Build Coastguard Worker res = S_FALSE;
698*f6dc9357SAndroid Build Coastguard Worker }
699*f6dc9357SAndroid Build Coastguard Worker
700*f6dc9357SAndroid Build Coastguard Worker RINOK(res)
701*f6dc9357SAndroid Build Coastguard Worker
702*f6dc9357SAndroid Build Coastguard Worker _cacheCluster = cluster;
703*f6dc9357SAndroid Build Coastguard Worker _cacheExtent = extentIndex;
704*f6dc9357SAndroid Build Coastguard Worker
705*f6dc9357SAndroid Build Coastguard Worker continue;
706*f6dc9357SAndroid Build Coastguard Worker /*
707*f6dc9357SAndroid Build Coastguard Worker memcpy(data, _cache + lowBits, size);
708*f6dc9357SAndroid Build Coastguard Worker _virtPos += size;
709*f6dc9357SAndroid Build Coastguard Worker if (processedSize)
710*f6dc9357SAndroid Build Coastguard Worker *processedSize = size;
711*f6dc9357SAndroid Build Coastguard Worker return S_OK;
712*f6dc9357SAndroid Build Coastguard Worker */
713*f6dc9357SAndroid Build Coastguard Worker }
714*f6dc9357SAndroid Build Coastguard Worker {
715*f6dc9357SAndroid Build Coastguard Worker offset += lowBits;
716*f6dc9357SAndroid Build Coastguard Worker if (offset != extent.PosInArc)
717*f6dc9357SAndroid Build Coastguard Worker {
718*f6dc9357SAndroid Build Coastguard Worker // printf("\n%12x %12x\n", (unsigned)offset, (unsigned)(offset - extent.PosInArc));
719*f6dc9357SAndroid Build Coastguard Worker RINOK(extent.Seek(offset))
720*f6dc9357SAndroid Build Coastguard Worker }
721*f6dc9357SAndroid Build Coastguard Worker UInt32 size2 = 0;
722*f6dc9357SAndroid Build Coastguard Worker HRESULT res = extent.Stream->Read(data, size, &size2);
723*f6dc9357SAndroid Build Coastguard Worker if (res == S_OK && size2 == 0)
724*f6dc9357SAndroid Build Coastguard Worker {
725*f6dc9357SAndroid Build Coastguard Worker _stream_unavailData = true;
726*f6dc9357SAndroid Build Coastguard Worker /*
727*f6dc9357SAndroid Build Coastguard Worker memset(data, 0, size);
728*f6dc9357SAndroid Build Coastguard Worker _virtPos += size;
729*f6dc9357SAndroid Build Coastguard Worker if (processedSize)
730*f6dc9357SAndroid Build Coastguard Worker *processedSize = size;
731*f6dc9357SAndroid Build Coastguard Worker return S_OK;
732*f6dc9357SAndroid Build Coastguard Worker */
733*f6dc9357SAndroid Build Coastguard Worker }
734*f6dc9357SAndroid Build Coastguard Worker extent.PosInArc += size2;
735*f6dc9357SAndroid Build Coastguard Worker // _stream_PackSize += size2;
736*f6dc9357SAndroid Build Coastguard Worker _virtPos += size2;
737*f6dc9357SAndroid Build Coastguard Worker if (processedSize)
738*f6dc9357SAndroid Build Coastguard Worker *processedSize = size2;
739*f6dc9357SAndroid Build Coastguard Worker return res;
740*f6dc9357SAndroid Build Coastguard Worker }
741*f6dc9357SAndroid Build Coastguard Worker }
742*f6dc9357SAndroid Build Coastguard Worker }
743*f6dc9357SAndroid Build Coastguard Worker }
744*f6dc9357SAndroid Build Coastguard Worker
745*f6dc9357SAndroid Build Coastguard Worker memset(data, 0, size);
746*f6dc9357SAndroid Build Coastguard Worker _virtPos += size;
747*f6dc9357SAndroid Build Coastguard Worker if (processedSize)
748*f6dc9357SAndroid Build Coastguard Worker *processedSize = size;
749*f6dc9357SAndroid Build Coastguard Worker return S_OK;
750*f6dc9357SAndroid Build Coastguard Worker }
751*f6dc9357SAndroid Build Coastguard Worker }
752*f6dc9357SAndroid Build Coastguard Worker
753*f6dc9357SAndroid Build Coastguard Worker
754*f6dc9357SAndroid Build Coastguard Worker static const Byte kProps[] =
755*f6dc9357SAndroid Build Coastguard Worker {
756*f6dc9357SAndroid Build Coastguard Worker kpidSize,
757*f6dc9357SAndroid Build Coastguard Worker kpidPackSize
758*f6dc9357SAndroid Build Coastguard Worker };
759*f6dc9357SAndroid Build Coastguard Worker
760*f6dc9357SAndroid Build Coastguard Worker static const Byte kArcProps[] =
761*f6dc9357SAndroid Build Coastguard Worker {
762*f6dc9357SAndroid Build Coastguard Worker kpidNumVolumes,
763*f6dc9357SAndroid Build Coastguard Worker kpidTotalPhySize,
764*f6dc9357SAndroid Build Coastguard Worker kpidMethod,
765*f6dc9357SAndroid Build Coastguard Worker kpidClusterSize,
766*f6dc9357SAndroid Build Coastguard Worker kpidHeadersSize,
767*f6dc9357SAndroid Build Coastguard Worker kpidId,
768*f6dc9357SAndroid Build Coastguard Worker kpidName,
769*f6dc9357SAndroid Build Coastguard Worker kpidComment
770*f6dc9357SAndroid Build Coastguard Worker };
771*f6dc9357SAndroid Build Coastguard Worker
772*f6dc9357SAndroid Build Coastguard Worker IMP_IInArchive_Props
773*f6dc9357SAndroid Build Coastguard Worker IMP_IInArchive_ArcProps
774*f6dc9357SAndroid Build Coastguard Worker
775*f6dc9357SAndroid Build Coastguard Worker
776*f6dc9357SAndroid Build Coastguard Worker Z7_COM7F_IMF(CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value))
777*f6dc9357SAndroid Build Coastguard Worker {
778*f6dc9357SAndroid Build Coastguard Worker COM_TRY_BEGIN
779*f6dc9357SAndroid Build Coastguard Worker NCOM::CPropVariant prop;
780*f6dc9357SAndroid Build Coastguard Worker
781*f6dc9357SAndroid Build Coastguard Worker const CExtent *e = NULL;
782*f6dc9357SAndroid Build Coastguard Worker const CDescriptor *desc = NULL;
783*f6dc9357SAndroid Build Coastguard Worker
784*f6dc9357SAndroid Build Coastguard Worker if (_isMultiVol)
785*f6dc9357SAndroid Build Coastguard Worker desc = &_descriptor;
786*f6dc9357SAndroid Build Coastguard Worker else if (_extents.Size() == 1)
787*f6dc9357SAndroid Build Coastguard Worker {
788*f6dc9357SAndroid Build Coastguard Worker e = &_extents[0];
789*f6dc9357SAndroid Build Coastguard Worker desc = &e->Descriptor;
790*f6dc9357SAndroid Build Coastguard Worker }
791*f6dc9357SAndroid Build Coastguard Worker
792*f6dc9357SAndroid Build Coastguard Worker switch (propID)
793*f6dc9357SAndroid Build Coastguard Worker {
794*f6dc9357SAndroid Build Coastguard Worker case kpidMainSubfile: prop = (UInt32)0; break;
795*f6dc9357SAndroid Build Coastguard Worker case kpidPhySize: if (_phySize != 0) prop = _phySize; break;
796*f6dc9357SAndroid Build Coastguard Worker case kpidTotalPhySize:
797*f6dc9357SAndroid Build Coastguard Worker {
798*f6dc9357SAndroid Build Coastguard Worker UInt64 sum = _phySize;
799*f6dc9357SAndroid Build Coastguard Worker if (_isMultiVol)
800*f6dc9357SAndroid Build Coastguard Worker {
801*f6dc9357SAndroid Build Coastguard Worker FOR_VECTOR (i, _extents)
802*f6dc9357SAndroid Build Coastguard Worker sum += _extents[i].PhySize;
803*f6dc9357SAndroid Build Coastguard Worker }
804*f6dc9357SAndroid Build Coastguard Worker prop = sum;
805*f6dc9357SAndroid Build Coastguard Worker break;
806*f6dc9357SAndroid Build Coastguard Worker }
807*f6dc9357SAndroid Build Coastguard Worker case kpidClusterSize: prop = (UInt32)((UInt32)1 << _clusterBitsMax); break;
808*f6dc9357SAndroid Build Coastguard Worker case kpidHeadersSize: if (e) prop = (e->h.overHead << 9); break;
809*f6dc9357SAndroid Build Coastguard Worker case kpidMethod:
810*f6dc9357SAndroid Build Coastguard Worker {
811*f6dc9357SAndroid Build Coastguard Worker AString s;
812*f6dc9357SAndroid Build Coastguard Worker
813*f6dc9357SAndroid Build Coastguard Worker if (desc && !desc->createType.IsEmpty())
814*f6dc9357SAndroid Build Coastguard Worker s = desc->createType;
815*f6dc9357SAndroid Build Coastguard Worker
816*f6dc9357SAndroid Build Coastguard Worker bool zlib = false;
817*f6dc9357SAndroid Build Coastguard Worker bool marker = false;
818*f6dc9357SAndroid Build Coastguard Worker Int32 algo = -1;
819*f6dc9357SAndroid Build Coastguard Worker
820*f6dc9357SAndroid Build Coastguard Worker FOR_VECTOR (i, _extents)
821*f6dc9357SAndroid Build Coastguard Worker {
822*f6dc9357SAndroid Build Coastguard Worker const CExtent &extent = _extents[i];
823*f6dc9357SAndroid Build Coastguard Worker if (!extent.IsOK || !extent.IsVmdk())
824*f6dc9357SAndroid Build Coastguard Worker continue;
825*f6dc9357SAndroid Build Coastguard Worker
826*f6dc9357SAndroid Build Coastguard Worker const CHeader &h = extent.h;
827*f6dc9357SAndroid Build Coastguard Worker
828*f6dc9357SAndroid Build Coastguard Worker if (h.algo != 0)
829*f6dc9357SAndroid Build Coastguard Worker {
830*f6dc9357SAndroid Build Coastguard Worker if (h.algo == 1)
831*f6dc9357SAndroid Build Coastguard Worker zlib = true;
832*f6dc9357SAndroid Build Coastguard Worker else if (algo != h.algo)
833*f6dc9357SAndroid Build Coastguard Worker {
834*f6dc9357SAndroid Build Coastguard Worker s.Add_Space_if_NotEmpty();
835*f6dc9357SAndroid Build Coastguard Worker s.Add_UInt32(h.algo);
836*f6dc9357SAndroid Build Coastguard Worker algo = h.algo;
837*f6dc9357SAndroid Build Coastguard Worker }
838*f6dc9357SAndroid Build Coastguard Worker }
839*f6dc9357SAndroid Build Coastguard Worker
840*f6dc9357SAndroid Build Coastguard Worker if (h.Is_Marker())
841*f6dc9357SAndroid Build Coastguard Worker marker = true;
842*f6dc9357SAndroid Build Coastguard Worker }
843*f6dc9357SAndroid Build Coastguard Worker
844*f6dc9357SAndroid Build Coastguard Worker if (zlib)
845*f6dc9357SAndroid Build Coastguard Worker s.Add_OptSpaced("zlib");
846*f6dc9357SAndroid Build Coastguard Worker
847*f6dc9357SAndroid Build Coastguard Worker if (marker)
848*f6dc9357SAndroid Build Coastguard Worker s.Add_OptSpaced("Marker");
849*f6dc9357SAndroid Build Coastguard Worker
850*f6dc9357SAndroid Build Coastguard Worker if (!s.IsEmpty())
851*f6dc9357SAndroid Build Coastguard Worker prop = s;
852*f6dc9357SAndroid Build Coastguard Worker break;
853*f6dc9357SAndroid Build Coastguard Worker }
854*f6dc9357SAndroid Build Coastguard Worker
855*f6dc9357SAndroid Build Coastguard Worker case kpidComment:
856*f6dc9357SAndroid Build Coastguard Worker {
857*f6dc9357SAndroid Build Coastguard Worker if (e && e->DescriptorBuf.Size() != 0)
858*f6dc9357SAndroid Build Coastguard Worker {
859*f6dc9357SAndroid Build Coastguard Worker AString s;
860*f6dc9357SAndroid Build Coastguard Worker s.SetFrom_CalcLen((const char *)(const Byte *)e->DescriptorBuf, (unsigned)e->DescriptorBuf.Size());
861*f6dc9357SAndroid Build Coastguard Worker if (!s.IsEmpty() && s.Len() <= (1 << 16))
862*f6dc9357SAndroid Build Coastguard Worker prop = s;
863*f6dc9357SAndroid Build Coastguard Worker }
864*f6dc9357SAndroid Build Coastguard Worker break;
865*f6dc9357SAndroid Build Coastguard Worker }
866*f6dc9357SAndroid Build Coastguard Worker
867*f6dc9357SAndroid Build Coastguard Worker case kpidId:
868*f6dc9357SAndroid Build Coastguard Worker {
869*f6dc9357SAndroid Build Coastguard Worker if (desc && !desc->CID.IsEmpty())
870*f6dc9357SAndroid Build Coastguard Worker {
871*f6dc9357SAndroid Build Coastguard Worker prop = desc->CID;
872*f6dc9357SAndroid Build Coastguard Worker }
873*f6dc9357SAndroid Build Coastguard Worker break;
874*f6dc9357SAndroid Build Coastguard Worker }
875*f6dc9357SAndroid Build Coastguard Worker
876*f6dc9357SAndroid Build Coastguard Worker case kpidName:
877*f6dc9357SAndroid Build Coastguard Worker {
878*f6dc9357SAndroid Build Coastguard Worker if (!_isMultiVol && desc && desc->Extents.Size() == 1)
879*f6dc9357SAndroid Build Coastguard Worker {
880*f6dc9357SAndroid Build Coastguard Worker const CExtentInfo &ei = desc->Extents[0];
881*f6dc9357SAndroid Build Coastguard Worker if (!ei.FileName.IsEmpty())
882*f6dc9357SAndroid Build Coastguard Worker {
883*f6dc9357SAndroid Build Coastguard Worker UString u;
884*f6dc9357SAndroid Build Coastguard Worker CDescriptor::GetUnicodeName(ei.FileName, u);
885*f6dc9357SAndroid Build Coastguard Worker if (!u.IsEmpty())
886*f6dc9357SAndroid Build Coastguard Worker prop = u;
887*f6dc9357SAndroid Build Coastguard Worker }
888*f6dc9357SAndroid Build Coastguard Worker }
889*f6dc9357SAndroid Build Coastguard Worker break;
890*f6dc9357SAndroid Build Coastguard Worker }
891*f6dc9357SAndroid Build Coastguard Worker
892*f6dc9357SAndroid Build Coastguard Worker case kpidNumVolumes: if (_isMultiVol) prop = (UInt32)_extents.Size(); break;
893*f6dc9357SAndroid Build Coastguard Worker
894*f6dc9357SAndroid Build Coastguard Worker case kpidError:
895*f6dc9357SAndroid Build Coastguard Worker {
896*f6dc9357SAndroid Build Coastguard Worker if (_missingVol || !_missingVolName.IsEmpty())
897*f6dc9357SAndroid Build Coastguard Worker {
898*f6dc9357SAndroid Build Coastguard Worker UString s ("Missing volume : ");
899*f6dc9357SAndroid Build Coastguard Worker if (!_missingVolName.IsEmpty())
900*f6dc9357SAndroid Build Coastguard Worker s += _missingVolName;
901*f6dc9357SAndroid Build Coastguard Worker prop = s;
902*f6dc9357SAndroid Build Coastguard Worker }
903*f6dc9357SAndroid Build Coastguard Worker break;
904*f6dc9357SAndroid Build Coastguard Worker }
905*f6dc9357SAndroid Build Coastguard Worker
906*f6dc9357SAndroid Build Coastguard Worker case kpidErrorFlags:
907*f6dc9357SAndroid Build Coastguard Worker {
908*f6dc9357SAndroid Build Coastguard Worker UInt32 v = 0;
909*f6dc9357SAndroid Build Coastguard Worker if (!_isArc) v |= kpv_ErrorFlags_IsNotArc;
910*f6dc9357SAndroid Build Coastguard Worker if (_unsupported) v |= kpv_ErrorFlags_UnsupportedMethod;
911*f6dc9357SAndroid Build Coastguard Worker if (_unsupportedSome) v |= kpv_ErrorFlags_UnsupportedMethod;
912*f6dc9357SAndroid Build Coastguard Worker if (_headerError) v |= kpv_ErrorFlags_HeadersError;
913*f6dc9357SAndroid Build Coastguard Worker // if (_missingVol) v |= kpv_ErrorFlags_UnexpectedEnd;
914*f6dc9357SAndroid Build Coastguard Worker if (v != 0)
915*f6dc9357SAndroid Build Coastguard Worker prop = v;
916*f6dc9357SAndroid Build Coastguard Worker break;
917*f6dc9357SAndroid Build Coastguard Worker }
918*f6dc9357SAndroid Build Coastguard Worker }
919*f6dc9357SAndroid Build Coastguard Worker
920*f6dc9357SAndroid Build Coastguard Worker prop.Detach(value);
921*f6dc9357SAndroid Build Coastguard Worker return S_OK;
922*f6dc9357SAndroid Build Coastguard Worker COM_TRY_END
923*f6dc9357SAndroid Build Coastguard Worker }
924*f6dc9357SAndroid Build Coastguard Worker
925*f6dc9357SAndroid Build Coastguard Worker
926*f6dc9357SAndroid Build Coastguard Worker Z7_COM7F_IMF(CHandler::GetProperty(UInt32 /* index */, PROPID propID, PROPVARIANT *value))
927*f6dc9357SAndroid Build Coastguard Worker {
928*f6dc9357SAndroid Build Coastguard Worker COM_TRY_BEGIN
929*f6dc9357SAndroid Build Coastguard Worker NCOM::CPropVariant prop;
930*f6dc9357SAndroid Build Coastguard Worker
931*f6dc9357SAndroid Build Coastguard Worker switch (propID)
932*f6dc9357SAndroid Build Coastguard Worker {
933*f6dc9357SAndroid Build Coastguard Worker case kpidSize: prop = _size; break;
934*f6dc9357SAndroid Build Coastguard Worker case kpidPackSize:
935*f6dc9357SAndroid Build Coastguard Worker {
936*f6dc9357SAndroid Build Coastguard Worker UInt64 packSize = 0;
937*f6dc9357SAndroid Build Coastguard Worker FOR_VECTOR (i, _extents)
938*f6dc9357SAndroid Build Coastguard Worker {
939*f6dc9357SAndroid Build Coastguard Worker const CExtent &e = _extents[i];
940*f6dc9357SAndroid Build Coastguard Worker if (!e.IsOK)
941*f6dc9357SAndroid Build Coastguard Worker continue;
942*f6dc9357SAndroid Build Coastguard Worker if (e.IsVmdk() && !_isMultiVol)
943*f6dc9357SAndroid Build Coastguard Worker {
944*f6dc9357SAndroid Build Coastguard Worker UInt64 ov = (e.h.overHead << 9);
945*f6dc9357SAndroid Build Coastguard Worker if (e.PhySize >= ov)
946*f6dc9357SAndroid Build Coastguard Worker packSize += e.PhySize - ov;
947*f6dc9357SAndroid Build Coastguard Worker }
948*f6dc9357SAndroid Build Coastguard Worker else
949*f6dc9357SAndroid Build Coastguard Worker packSize += e.PhySize;
950*f6dc9357SAndroid Build Coastguard Worker }
951*f6dc9357SAndroid Build Coastguard Worker prop = packSize;
952*f6dc9357SAndroid Build Coastguard Worker break;
953*f6dc9357SAndroid Build Coastguard Worker }
954*f6dc9357SAndroid Build Coastguard Worker case kpidExtension: prop = (_imgExt ? _imgExt : "img"); break;
955*f6dc9357SAndroid Build Coastguard Worker }
956*f6dc9357SAndroid Build Coastguard Worker
957*f6dc9357SAndroid Build Coastguard Worker prop.Detach(value);
958*f6dc9357SAndroid Build Coastguard Worker return S_OK;
959*f6dc9357SAndroid Build Coastguard Worker COM_TRY_END
960*f6dc9357SAndroid Build Coastguard Worker }
961*f6dc9357SAndroid Build Coastguard Worker
962*f6dc9357SAndroid Build Coastguard Worker
963*f6dc9357SAndroid Build Coastguard Worker static int inline GetLog(UInt64 num)
964*f6dc9357SAndroid Build Coastguard Worker {
965*f6dc9357SAndroid Build Coastguard Worker for (int i = 0; i < 64; i++)
966*f6dc9357SAndroid Build Coastguard Worker if (((UInt64)1 << i) == num)
967*f6dc9357SAndroid Build Coastguard Worker return i;
968*f6dc9357SAndroid Build Coastguard Worker return -1;
969*f6dc9357SAndroid Build Coastguard Worker }
970*f6dc9357SAndroid Build Coastguard Worker
971*f6dc9357SAndroid Build Coastguard Worker
972*f6dc9357SAndroid Build Coastguard Worker HRESULT CExtent::ReadForHeader(IInStream *stream, UInt64 sector, void *data, size_t numSectors)
973*f6dc9357SAndroid Build Coastguard Worker {
974*f6dc9357SAndroid Build Coastguard Worker sector <<= 9;
975*f6dc9357SAndroid Build Coastguard Worker RINOK(InStream_SeekSet(stream, sector))
976*f6dc9357SAndroid Build Coastguard Worker size_t size = numSectors << 9;
977*f6dc9357SAndroid Build Coastguard Worker RINOK(ReadStream_FALSE(stream, data, size))
978*f6dc9357SAndroid Build Coastguard Worker UInt64 end = sector + size;
979*f6dc9357SAndroid Build Coastguard Worker if (PhySize < end)
980*f6dc9357SAndroid Build Coastguard Worker PhySize = end;
981*f6dc9357SAndroid Build Coastguard Worker return S_OK;
982*f6dc9357SAndroid Build Coastguard Worker }
983*f6dc9357SAndroid Build Coastguard Worker
984*f6dc9357SAndroid Build Coastguard Worker
985*f6dc9357SAndroid Build Coastguard Worker void CHandler::CloseAtError()
986*f6dc9357SAndroid Build Coastguard Worker {
987*f6dc9357SAndroid Build Coastguard Worker _extents.Clear();
988*f6dc9357SAndroid Build Coastguard Worker CHandlerImg::CloseAtError();
989*f6dc9357SAndroid Build Coastguard Worker }
990*f6dc9357SAndroid Build Coastguard Worker
991*f6dc9357SAndroid Build Coastguard Worker
992*f6dc9357SAndroid Build Coastguard Worker static const char * const kSignature_Descriptor = "# Disk DescriptorFile";
993*f6dc9357SAndroid Build Coastguard Worker
994*f6dc9357SAndroid Build Coastguard Worker
995*f6dc9357SAndroid Build Coastguard Worker HRESULT CHandler::Open2(IInStream *stream, IArchiveOpenCallback *openCallback)
996*f6dc9357SAndroid Build Coastguard Worker {
997*f6dc9357SAndroid Build Coastguard Worker const unsigned kSectoreSize = 512;
998*f6dc9357SAndroid Build Coastguard Worker Byte buf[kSectoreSize];
999*f6dc9357SAndroid Build Coastguard Worker size_t headerSize = kSectoreSize;
1000*f6dc9357SAndroid Build Coastguard Worker RINOK(ReadStream(stream, buf, &headerSize))
1001*f6dc9357SAndroid Build Coastguard Worker
1002*f6dc9357SAndroid Build Coastguard Worker if (headerSize < sizeof(k_Signature))
1003*f6dc9357SAndroid Build Coastguard Worker return S_FALSE;
1004*f6dc9357SAndroid Build Coastguard Worker
1005*f6dc9357SAndroid Build Coastguard Worker CMyComPtr<IArchiveOpenVolumeCallback> volumeCallback;
1006*f6dc9357SAndroid Build Coastguard Worker
1007*f6dc9357SAndroid Build Coastguard Worker if (memcmp(buf, k_Signature, sizeof(k_Signature)) != 0)
1008*f6dc9357SAndroid Build Coastguard Worker {
1009*f6dc9357SAndroid Build Coastguard Worker const size_t k_SigDesc_Size = strlen(kSignature_Descriptor);
1010*f6dc9357SAndroid Build Coastguard Worker if (headerSize < k_SigDesc_Size)
1011*f6dc9357SAndroid Build Coastguard Worker return S_FALSE;
1012*f6dc9357SAndroid Build Coastguard Worker if (memcmp(buf, kSignature_Descriptor, k_SigDesc_Size) != 0)
1013*f6dc9357SAndroid Build Coastguard Worker return S_FALSE;
1014*f6dc9357SAndroid Build Coastguard Worker
1015*f6dc9357SAndroid Build Coastguard Worker UInt64 endPos;
1016*f6dc9357SAndroid Build Coastguard Worker RINOK(InStream_GetSize_SeekToEnd(stream, endPos))
1017*f6dc9357SAndroid Build Coastguard Worker if (endPos > (1 << 20))
1018*f6dc9357SAndroid Build Coastguard Worker return S_FALSE;
1019*f6dc9357SAndroid Build Coastguard Worker const size_t numBytes = (size_t)endPos;
1020*f6dc9357SAndroid Build Coastguard Worker _descriptorBuf.Alloc(numBytes);
1021*f6dc9357SAndroid Build Coastguard Worker RINOK(InStream_SeekToBegin(stream))
1022*f6dc9357SAndroid Build Coastguard Worker RINOK(ReadStream_FALSE(stream, _descriptorBuf, numBytes))
1023*f6dc9357SAndroid Build Coastguard Worker
1024*f6dc9357SAndroid Build Coastguard Worker if (!_descriptor.Parse(_descriptorBuf, _descriptorBuf.Size()))
1025*f6dc9357SAndroid Build Coastguard Worker return S_FALSE;
1026*f6dc9357SAndroid Build Coastguard Worker _isMultiVol = true;
1027*f6dc9357SAndroid Build Coastguard Worker _isArc = true;
1028*f6dc9357SAndroid Build Coastguard Worker _phySize = numBytes;
1029*f6dc9357SAndroid Build Coastguard Worker if (_descriptor.IsThere_Parent())
1030*f6dc9357SAndroid Build Coastguard Worker _unsupported = true;
1031*f6dc9357SAndroid Build Coastguard Worker
1032*f6dc9357SAndroid Build Coastguard Worker if (openCallback)
1033*f6dc9357SAndroid Build Coastguard Worker {
1034*f6dc9357SAndroid Build Coastguard Worker openCallback->QueryInterface(IID_IArchiveOpenVolumeCallback, (void **)&volumeCallback);
1035*f6dc9357SAndroid Build Coastguard Worker }
1036*f6dc9357SAndroid Build Coastguard Worker if (!volumeCallback)
1037*f6dc9357SAndroid Build Coastguard Worker {
1038*f6dc9357SAndroid Build Coastguard Worker _unsupported = true;
1039*f6dc9357SAndroid Build Coastguard Worker return E_NOTIMPL;
1040*f6dc9357SAndroid Build Coastguard Worker }
1041*f6dc9357SAndroid Build Coastguard Worker
1042*f6dc9357SAndroid Build Coastguard Worker /*
1043*f6dc9357SAndroid Build Coastguard Worker UInt64 totalVirtSize = 0;
1044*f6dc9357SAndroid Build Coastguard Worker FOR_VECTOR (i, _descriptor.Extents)
1045*f6dc9357SAndroid Build Coastguard Worker {
1046*f6dc9357SAndroid Build Coastguard Worker const CExtentInfo &ei = _descriptor.Extents[i];
1047*f6dc9357SAndroid Build Coastguard Worker if (ei.NumSectors >= ((UInt64)1 << (63 - 9)))
1048*f6dc9357SAndroid Build Coastguard Worker return S_FALSE;
1049*f6dc9357SAndroid Build Coastguard Worker totalVirtSize += ei.NumSectors;
1050*f6dc9357SAndroid Build Coastguard Worker if (totalVirtSize >= ((UInt64)1 << (63 - 9)))
1051*f6dc9357SAndroid Build Coastguard Worker return S_FALSE;
1052*f6dc9357SAndroid Build Coastguard Worker }
1053*f6dc9357SAndroid Build Coastguard Worker totalVirtSize <<= 9;
1054*f6dc9357SAndroid Build Coastguard Worker */
1055*f6dc9357SAndroid Build Coastguard Worker
1056*f6dc9357SAndroid Build Coastguard Worker if (_descriptor.Extents.Size() > 1)
1057*f6dc9357SAndroid Build Coastguard Worker {
1058*f6dc9357SAndroid Build Coastguard Worker const UInt64 numFiles = _descriptor.Extents.Size();
1059*f6dc9357SAndroid Build Coastguard Worker RINOK(openCallback->SetTotal(&numFiles, NULL))
1060*f6dc9357SAndroid Build Coastguard Worker }
1061*f6dc9357SAndroid Build Coastguard Worker }
1062*f6dc9357SAndroid Build Coastguard Worker
1063*f6dc9357SAndroid Build Coastguard Worker UInt64 complexity = 0;
1064*f6dc9357SAndroid Build Coastguard Worker
1065*f6dc9357SAndroid Build Coastguard Worker for (;;)
1066*f6dc9357SAndroid Build Coastguard Worker {
1067*f6dc9357SAndroid Build Coastguard Worker CExtent *e = NULL;
1068*f6dc9357SAndroid Build Coastguard Worker CMyComPtr<IInStream> nextStream;
1069*f6dc9357SAndroid Build Coastguard Worker
1070*f6dc9357SAndroid Build Coastguard Worker if (_isMultiVol)
1071*f6dc9357SAndroid Build Coastguard Worker {
1072*f6dc9357SAndroid Build Coastguard Worker const unsigned extentIndex = _extents.Size();
1073*f6dc9357SAndroid Build Coastguard Worker if (extentIndex >= _descriptor.Extents.Size())
1074*f6dc9357SAndroid Build Coastguard Worker break;
1075*f6dc9357SAndroid Build Coastguard Worker const CExtentInfo &ei = _descriptor.Extents[extentIndex];
1076*f6dc9357SAndroid Build Coastguard Worker e = &_extents.AddNew();
1077*f6dc9357SAndroid Build Coastguard Worker e->StartOffset = 0;
1078*f6dc9357SAndroid Build Coastguard Worker if (ei.NumSectors >= ((UInt64)1 << (62 - 9)) ||
1079*f6dc9357SAndroid Build Coastguard Worker ei.StartSector >= ((UInt64)1 << (62 - 9)))
1080*f6dc9357SAndroid Build Coastguard Worker return S_FALSE;
1081*f6dc9357SAndroid Build Coastguard Worker e->NumBytes = ei.NumSectors << 9;
1082*f6dc9357SAndroid Build Coastguard Worker e->IsZero = ei.IsType_ZERO();
1083*f6dc9357SAndroid Build Coastguard Worker if (extentIndex != 0)
1084*f6dc9357SAndroid Build Coastguard Worker e->StartOffset = _extents[extentIndex - 1].GetEndOffset();
1085*f6dc9357SAndroid Build Coastguard Worker if (e->GetEndOffset() < e->StartOffset)
1086*f6dc9357SAndroid Build Coastguard Worker return S_FALSE;
1087*f6dc9357SAndroid Build Coastguard Worker
1088*f6dc9357SAndroid Build Coastguard Worker e->VirtSize = e->NumBytes;
1089*f6dc9357SAndroid Build Coastguard Worker if (e->IsZero)
1090*f6dc9357SAndroid Build Coastguard Worker {
1091*f6dc9357SAndroid Build Coastguard Worker e->IsOK = true;
1092*f6dc9357SAndroid Build Coastguard Worker continue;
1093*f6dc9357SAndroid Build Coastguard Worker }
1094*f6dc9357SAndroid Build Coastguard Worker
1095*f6dc9357SAndroid Build Coastguard Worker e->IsFlat = ei.IsType_Flat();
1096*f6dc9357SAndroid Build Coastguard Worker e->FlatOffset = ei.StartSector << 9;
1097*f6dc9357SAndroid Build Coastguard Worker
1098*f6dc9357SAndroid Build Coastguard Worker UString u;
1099*f6dc9357SAndroid Build Coastguard Worker CDescriptor::GetUnicodeName(ei.FileName, u);
1100*f6dc9357SAndroid Build Coastguard Worker if (u.IsEmpty())
1101*f6dc9357SAndroid Build Coastguard Worker {
1102*f6dc9357SAndroid Build Coastguard Worker _missingVol = true;
1103*f6dc9357SAndroid Build Coastguard Worker continue;
1104*f6dc9357SAndroid Build Coastguard Worker }
1105*f6dc9357SAndroid Build Coastguard Worker
1106*f6dc9357SAndroid Build Coastguard Worker HRESULT result = volumeCallback->GetStream(u, &nextStream);
1107*f6dc9357SAndroid Build Coastguard Worker
1108*f6dc9357SAndroid Build Coastguard Worker if (result != S_OK && result != S_FALSE)
1109*f6dc9357SAndroid Build Coastguard Worker return result;
1110*f6dc9357SAndroid Build Coastguard Worker
1111*f6dc9357SAndroid Build Coastguard Worker if (!nextStream || result != S_OK)
1112*f6dc9357SAndroid Build Coastguard Worker {
1113*f6dc9357SAndroid Build Coastguard Worker if (_missingVolName.IsEmpty())
1114*f6dc9357SAndroid Build Coastguard Worker _missingVolName = u;
1115*f6dc9357SAndroid Build Coastguard Worker _missingVol = true;
1116*f6dc9357SAndroid Build Coastguard Worker continue;
1117*f6dc9357SAndroid Build Coastguard Worker }
1118*f6dc9357SAndroid Build Coastguard Worker
1119*f6dc9357SAndroid Build Coastguard Worker if (e->IsFlat)
1120*f6dc9357SAndroid Build Coastguard Worker {
1121*f6dc9357SAndroid Build Coastguard Worker e->IsOK = true;
1122*f6dc9357SAndroid Build Coastguard Worker e->Stream = nextStream;
1123*f6dc9357SAndroid Build Coastguard Worker e->PhySize = e->NumBytes;
1124*f6dc9357SAndroid Build Coastguard Worker continue;
1125*f6dc9357SAndroid Build Coastguard Worker }
1126*f6dc9357SAndroid Build Coastguard Worker
1127*f6dc9357SAndroid Build Coastguard Worker stream = nextStream;
1128*f6dc9357SAndroid Build Coastguard Worker
1129*f6dc9357SAndroid Build Coastguard Worker headerSize = kSectoreSize;
1130*f6dc9357SAndroid Build Coastguard Worker RINOK(ReadStream(stream, buf, &headerSize))
1131*f6dc9357SAndroid Build Coastguard Worker
1132*f6dc9357SAndroid Build Coastguard Worker if (headerSize != kSectoreSize)
1133*f6dc9357SAndroid Build Coastguard Worker continue;
1134*f6dc9357SAndroid Build Coastguard Worker if (memcmp(buf, k_Signature, sizeof(k_Signature)) != 0)
1135*f6dc9357SAndroid Build Coastguard Worker continue;
1136*f6dc9357SAndroid Build Coastguard Worker }
1137*f6dc9357SAndroid Build Coastguard Worker else
1138*f6dc9357SAndroid Build Coastguard Worker {
1139*f6dc9357SAndroid Build Coastguard Worker if (headerSize != kSectoreSize)
1140*f6dc9357SAndroid Build Coastguard Worker return S_FALSE;
1141*f6dc9357SAndroid Build Coastguard Worker e = &_extents.AddNew();
1142*f6dc9357SAndroid Build Coastguard Worker e->StartOffset = 0;
1143*f6dc9357SAndroid Build Coastguard Worker }
1144*f6dc9357SAndroid Build Coastguard Worker
1145*f6dc9357SAndroid Build Coastguard Worker HRESULT res = S_FALSE;
1146*f6dc9357SAndroid Build Coastguard Worker if (e->h.Parse(buf))
1147*f6dc9357SAndroid Build Coastguard Worker res = e->Open3(stream, openCallback, _isMultiVol ? _descriptor.Extents.Size() : 1, _extents.Size() - 1, complexity);
1148*f6dc9357SAndroid Build Coastguard Worker
1149*f6dc9357SAndroid Build Coastguard Worker if (!_isMultiVol)
1150*f6dc9357SAndroid Build Coastguard Worker {
1151*f6dc9357SAndroid Build Coastguard Worker _isArc = e->IsArc;
1152*f6dc9357SAndroid Build Coastguard Worker _phySize = e->PhySize;
1153*f6dc9357SAndroid Build Coastguard Worker _unsupported = e->Unsupported;
1154*f6dc9357SAndroid Build Coastguard Worker }
1155*f6dc9357SAndroid Build Coastguard Worker
1156*f6dc9357SAndroid Build Coastguard Worker if (e->Unsupported)
1157*f6dc9357SAndroid Build Coastguard Worker _unsupportedSome = true;
1158*f6dc9357SAndroid Build Coastguard Worker if (e->HeadersError)
1159*f6dc9357SAndroid Build Coastguard Worker _headerError = true;
1160*f6dc9357SAndroid Build Coastguard Worker
1161*f6dc9357SAndroid Build Coastguard Worker if (res != S_OK)
1162*f6dc9357SAndroid Build Coastguard Worker {
1163*f6dc9357SAndroid Build Coastguard Worker if (res != S_FALSE)
1164*f6dc9357SAndroid Build Coastguard Worker return res;
1165*f6dc9357SAndroid Build Coastguard Worker if (!_isMultiVol)
1166*f6dc9357SAndroid Build Coastguard Worker return res;
1167*f6dc9357SAndroid Build Coastguard Worker continue;
1168*f6dc9357SAndroid Build Coastguard Worker }
1169*f6dc9357SAndroid Build Coastguard Worker
1170*f6dc9357SAndroid Build Coastguard Worker e->Stream = stream;
1171*f6dc9357SAndroid Build Coastguard Worker e->IsOK = true;
1172*f6dc9357SAndroid Build Coastguard Worker
1173*f6dc9357SAndroid Build Coastguard Worker if (!_isMultiVol)
1174*f6dc9357SAndroid Build Coastguard Worker {
1175*f6dc9357SAndroid Build Coastguard Worker e->NumBytes = e->VirtSize;
1176*f6dc9357SAndroid Build Coastguard Worker break;
1177*f6dc9357SAndroid Build Coastguard Worker }
1178*f6dc9357SAndroid Build Coastguard Worker
1179*f6dc9357SAndroid Build Coastguard Worker if (e->NumBytes != e->VirtSize)
1180*f6dc9357SAndroid Build Coastguard Worker _headerError = true;
1181*f6dc9357SAndroid Build Coastguard Worker }
1182*f6dc9357SAndroid Build Coastguard Worker
1183*f6dc9357SAndroid Build Coastguard Worker if (!_extents.IsEmpty())
1184*f6dc9357SAndroid Build Coastguard Worker _size = _extents.Back().GetEndOffset();
1185*f6dc9357SAndroid Build Coastguard Worker
1186*f6dc9357SAndroid Build Coastguard Worker _needDeflate = false;
1187*f6dc9357SAndroid Build Coastguard Worker _clusterBitsMax = 0;
1188*f6dc9357SAndroid Build Coastguard Worker
1189*f6dc9357SAndroid Build Coastguard Worker // unsigned numOKs = 0;
1190*f6dc9357SAndroid Build Coastguard Worker unsigned numUnsupported = 0;
1191*f6dc9357SAndroid Build Coastguard Worker
1192*f6dc9357SAndroid Build Coastguard Worker FOR_VECTOR (i, _extents)
1193*f6dc9357SAndroid Build Coastguard Worker {
1194*f6dc9357SAndroid Build Coastguard Worker const CExtent &e = _extents[i];
1195*f6dc9357SAndroid Build Coastguard Worker if (e.Unsupported)
1196*f6dc9357SAndroid Build Coastguard Worker numUnsupported++;
1197*f6dc9357SAndroid Build Coastguard Worker if (!e.IsOK)
1198*f6dc9357SAndroid Build Coastguard Worker continue;
1199*f6dc9357SAndroid Build Coastguard Worker // numOKs++;
1200*f6dc9357SAndroid Build Coastguard Worker if (e.IsVmdk())
1201*f6dc9357SAndroid Build Coastguard Worker {
1202*f6dc9357SAndroid Build Coastguard Worker if (e.NeedDeflate)
1203*f6dc9357SAndroid Build Coastguard Worker _needDeflate = true;
1204*f6dc9357SAndroid Build Coastguard Worker if (_clusterBitsMax < e.ClusterBits)
1205*f6dc9357SAndroid Build Coastguard Worker _clusterBitsMax = e.ClusterBits;
1206*f6dc9357SAndroid Build Coastguard Worker }
1207*f6dc9357SAndroid Build Coastguard Worker }
1208*f6dc9357SAndroid Build Coastguard Worker
1209*f6dc9357SAndroid Build Coastguard Worker if (numUnsupported != 0 && numUnsupported == _extents.Size())
1210*f6dc9357SAndroid Build Coastguard Worker _unsupported = true;
1211*f6dc9357SAndroid Build Coastguard Worker
1212*f6dc9357SAndroid Build Coastguard Worker return S_OK;
1213*f6dc9357SAndroid Build Coastguard Worker }
1214*f6dc9357SAndroid Build Coastguard Worker
1215*f6dc9357SAndroid Build Coastguard Worker
1216*f6dc9357SAndroid Build Coastguard Worker HRESULT CExtent::Open3(IInStream *stream, IArchiveOpenCallback *openCallback,
1217*f6dc9357SAndroid Build Coastguard Worker unsigned numVols, unsigned volIndex, UInt64 &complexity)
1218*f6dc9357SAndroid Build Coastguard Worker {
1219*f6dc9357SAndroid Build Coastguard Worker if (h.descriptorSize != 0)
1220*f6dc9357SAndroid Build Coastguard Worker {
1221*f6dc9357SAndroid Build Coastguard Worker if (h.descriptorOffset == 0 ||
1222*f6dc9357SAndroid Build Coastguard Worker h.descriptorSize > (1 << 10))
1223*f6dc9357SAndroid Build Coastguard Worker return S_FALSE;
1224*f6dc9357SAndroid Build Coastguard Worker DescriptorBuf.Alloc((size_t)h.descriptorSize << 9);
1225*f6dc9357SAndroid Build Coastguard Worker RINOK(ReadForHeader(stream, h.descriptorOffset, DescriptorBuf, (size_t)h.descriptorSize))
1226*f6dc9357SAndroid Build Coastguard Worker if (h.descriptorOffset == 1 && h.Is_Marker() && Get64(DescriptorBuf) == 0)
1227*f6dc9357SAndroid Build Coastguard Worker {
1228*f6dc9357SAndroid Build Coastguard Worker // We check data as end marker.
1229*f6dc9357SAndroid Build Coastguard Worker // and if probably it's footer's copy of header, we don't want to open it.
1230*f6dc9357SAndroid Build Coastguard Worker return S_FALSE;
1231*f6dc9357SAndroid Build Coastguard Worker }
1232*f6dc9357SAndroid Build Coastguard Worker
1233*f6dc9357SAndroid Build Coastguard Worker DescriptorOK = Descriptor.Parse(DescriptorBuf, DescriptorBuf.Size());
1234*f6dc9357SAndroid Build Coastguard Worker if (!DescriptorOK)
1235*f6dc9357SAndroid Build Coastguard Worker HeadersError = true;
1236*f6dc9357SAndroid Build Coastguard Worker if (Descriptor.IsThere_Parent())
1237*f6dc9357SAndroid Build Coastguard Worker Unsupported = true;
1238*f6dc9357SAndroid Build Coastguard Worker }
1239*f6dc9357SAndroid Build Coastguard Worker
1240*f6dc9357SAndroid Build Coastguard Worker if (h.gdOffset == (UInt64)(Int64)-1)
1241*f6dc9357SAndroid Build Coastguard Worker {
1242*f6dc9357SAndroid Build Coastguard Worker // Grain Dir is at end of file
1243*f6dc9357SAndroid Build Coastguard Worker UInt64 endPos;
1244*f6dc9357SAndroid Build Coastguard Worker RINOK(InStream_GetSize_SeekToEnd(stream, endPos))
1245*f6dc9357SAndroid Build Coastguard Worker if ((endPos & 511) != 0)
1246*f6dc9357SAndroid Build Coastguard Worker return S_FALSE;
1247*f6dc9357SAndroid Build Coastguard Worker
1248*f6dc9357SAndroid Build Coastguard Worker const size_t kEndSize = 512 * 3;
1249*f6dc9357SAndroid Build Coastguard Worker Byte buf2[kEndSize];
1250*f6dc9357SAndroid Build Coastguard Worker if (endPos < kEndSize)
1251*f6dc9357SAndroid Build Coastguard Worker return S_FALSE;
1252*f6dc9357SAndroid Build Coastguard Worker RINOK(InStream_SeekSet(stream, endPos - kEndSize))
1253*f6dc9357SAndroid Build Coastguard Worker RINOK(ReadStream_FALSE(stream, buf2, kEndSize))
1254*f6dc9357SAndroid Build Coastguard Worker
1255*f6dc9357SAndroid Build Coastguard Worker CHeader h2;
1256*f6dc9357SAndroid Build Coastguard Worker if (!h2.Parse(buf2 + 512))
1257*f6dc9357SAndroid Build Coastguard Worker return S_FALSE;
1258*f6dc9357SAndroid Build Coastguard Worker if (!h.IsSameImageFor(h2))
1259*f6dc9357SAndroid Build Coastguard Worker return S_FALSE;
1260*f6dc9357SAndroid Build Coastguard Worker
1261*f6dc9357SAndroid Build Coastguard Worker h = h2;
1262*f6dc9357SAndroid Build Coastguard Worker
1263*f6dc9357SAndroid Build Coastguard Worker CMarker m;
1264*f6dc9357SAndroid Build Coastguard Worker m.Parse(buf2);
1265*f6dc9357SAndroid Build Coastguard Worker if (m.NumSectors != 1 || m.SpecSize != 0 || m.Type != k_Marker_FOOTER)
1266*f6dc9357SAndroid Build Coastguard Worker return S_FALSE;
1267*f6dc9357SAndroid Build Coastguard Worker m.Parse(buf2 + 512 * 2);
1268*f6dc9357SAndroid Build Coastguard Worker if (m.NumSectors != 0 || m.SpecSize != 0 || m.Type != k_Marker_END_OF_STREAM)
1269*f6dc9357SAndroid Build Coastguard Worker return S_FALSE;
1270*f6dc9357SAndroid Build Coastguard Worker PhySize = endPos;
1271*f6dc9357SAndroid Build Coastguard Worker }
1272*f6dc9357SAndroid Build Coastguard Worker
1273*f6dc9357SAndroid Build Coastguard Worker const int grainSize_Log = GetLog(h.grainSize);
1274*f6dc9357SAndroid Build Coastguard Worker if (grainSize_Log < 3 || grainSize_Log > 30 - 9) // grain size must be >= 4 KB
1275*f6dc9357SAndroid Build Coastguard Worker return S_FALSE;
1276*f6dc9357SAndroid Build Coastguard Worker if (h.capacity >= ((UInt64)1 << (63 - 9)))
1277*f6dc9357SAndroid Build Coastguard Worker return S_FALSE;
1278*f6dc9357SAndroid Build Coastguard Worker if (h.overHead >= ((UInt64)1 << (63 - 9)))
1279*f6dc9357SAndroid Build Coastguard Worker return S_FALSE;
1280*f6dc9357SAndroid Build Coastguard Worker
1281*f6dc9357SAndroid Build Coastguard Worker IsArc = true;
1282*f6dc9357SAndroid Build Coastguard Worker ClusterBits = (9 + (unsigned)grainSize_Log);
1283*f6dc9357SAndroid Build Coastguard Worker VirtSize = h.capacity << 9;
1284*f6dc9357SAndroid Build Coastguard Worker NeedDeflate = (h.algo >= 1);
1285*f6dc9357SAndroid Build Coastguard Worker
1286*f6dc9357SAndroid Build Coastguard Worker if (h.Is_Compressed() ? (h.algo > 1 || !h.Is_Marker()) : (h.algo != 0))
1287*f6dc9357SAndroid Build Coastguard Worker {
1288*f6dc9357SAndroid Build Coastguard Worker Unsupported = true;
1289*f6dc9357SAndroid Build Coastguard Worker PhySize = 0;
1290*f6dc9357SAndroid Build Coastguard Worker return S_FALSE;
1291*f6dc9357SAndroid Build Coastguard Worker }
1292*f6dc9357SAndroid Build Coastguard Worker
1293*f6dc9357SAndroid Build Coastguard Worker {
1294*f6dc9357SAndroid Build Coastguard Worker const UInt64 overHeadBytes = h.overHead << 9;
1295*f6dc9357SAndroid Build Coastguard Worker if (PhySize < overHeadBytes)
1296*f6dc9357SAndroid Build Coastguard Worker PhySize = overHeadBytes;
1297*f6dc9357SAndroid Build Coastguard Worker }
1298*f6dc9357SAndroid Build Coastguard Worker
1299*f6dc9357SAndroid Build Coastguard Worker ZeroSector = 0;
1300*f6dc9357SAndroid Build Coastguard Worker if (h.Is_ZeroGrain())
1301*f6dc9357SAndroid Build Coastguard Worker ZeroSector = 1;
1302*f6dc9357SAndroid Build Coastguard Worker
1303*f6dc9357SAndroid Build Coastguard Worker const UInt64 numSectorsPerGde = (UInt64)1 << ((unsigned)grainSize_Log + k_NumMidBits);
1304*f6dc9357SAndroid Build Coastguard Worker const UInt64 numGdeEntries = (h.capacity + numSectorsPerGde - 1) >> ((unsigned)grainSize_Log + k_NumMidBits);
1305*f6dc9357SAndroid Build Coastguard Worker CByteBuffer table;
1306*f6dc9357SAndroid Build Coastguard Worker
1307*f6dc9357SAndroid Build Coastguard Worker if (numGdeEntries != 0)
1308*f6dc9357SAndroid Build Coastguard Worker {
1309*f6dc9357SAndroid Build Coastguard Worker if (h.gdOffset == 0)
1310*f6dc9357SAndroid Build Coastguard Worker return S_FALSE;
1311*f6dc9357SAndroid Build Coastguard Worker
1312*f6dc9357SAndroid Build Coastguard Worker size_t numSectors = (size_t)((numGdeEntries + ((1 << (9 - 2)) - 1)) >> (9 - 2));
1313*f6dc9357SAndroid Build Coastguard Worker size_t t1SizeBytes = numSectors << 9;
1314*f6dc9357SAndroid Build Coastguard Worker if ((t1SizeBytes >> 2) < numGdeEntries)
1315*f6dc9357SAndroid Build Coastguard Worker return S_FALSE;
1316*f6dc9357SAndroid Build Coastguard Worker table.Alloc(t1SizeBytes);
1317*f6dc9357SAndroid Build Coastguard Worker
1318*f6dc9357SAndroid Build Coastguard Worker if (h.Is_Marker())
1319*f6dc9357SAndroid Build Coastguard Worker {
1320*f6dc9357SAndroid Build Coastguard Worker Byte buf2[1 << 9];
1321*f6dc9357SAndroid Build Coastguard Worker if (ReadForHeader(stream, h.gdOffset - 1, buf2, 1) != S_OK)
1322*f6dc9357SAndroid Build Coastguard Worker return S_FALSE;
1323*f6dc9357SAndroid Build Coastguard Worker {
1324*f6dc9357SAndroid Build Coastguard Worker CMarker m;
1325*f6dc9357SAndroid Build Coastguard Worker m.Parse(buf2);
1326*f6dc9357SAndroid Build Coastguard Worker if (m.Type != k_Marker_GRAIN_DIR
1327*f6dc9357SAndroid Build Coastguard Worker || m.NumSectors != numSectors
1328*f6dc9357SAndroid Build Coastguard Worker || m.SpecSize != 0)
1329*f6dc9357SAndroid Build Coastguard Worker return S_FALSE;
1330*f6dc9357SAndroid Build Coastguard Worker }
1331*f6dc9357SAndroid Build Coastguard Worker }
1332*f6dc9357SAndroid Build Coastguard Worker
1333*f6dc9357SAndroid Build Coastguard Worker RINOK(ReadForHeader(stream, h.gdOffset, table, numSectors))
1334*f6dc9357SAndroid Build Coastguard Worker }
1335*f6dc9357SAndroid Build Coastguard Worker
1336*f6dc9357SAndroid Build Coastguard Worker const size_t clusterSize = (size_t)1 << ClusterBits;
1337*f6dc9357SAndroid Build Coastguard Worker
1338*f6dc9357SAndroid Build Coastguard Worker const UInt64 complexityStart = complexity;
1339*f6dc9357SAndroid Build Coastguard Worker
1340*f6dc9357SAndroid Build Coastguard Worker if (openCallback)
1341*f6dc9357SAndroid Build Coastguard Worker {
1342*f6dc9357SAndroid Build Coastguard Worker complexity += (UInt64)numGdeEntries << (k_NumMidBits + 2);
1343*f6dc9357SAndroid Build Coastguard Worker {
1344*f6dc9357SAndroid Build Coastguard Worker const UInt64 numVols2 = numVols;
1345*f6dc9357SAndroid Build Coastguard Worker RINOK(openCallback->SetTotal((numVols == 1) ? NULL : &numVols2, &complexity))
1346*f6dc9357SAndroid Build Coastguard Worker }
1347*f6dc9357SAndroid Build Coastguard Worker if (numVols != 1)
1348*f6dc9357SAndroid Build Coastguard Worker {
1349*f6dc9357SAndroid Build Coastguard Worker const UInt64 volIndex2 = volIndex;
1350*f6dc9357SAndroid Build Coastguard Worker RINOK(openCallback->SetCompleted(numVols == 1 ? NULL : &volIndex2, &complexityStart))
1351*f6dc9357SAndroid Build Coastguard Worker }
1352*f6dc9357SAndroid Build Coastguard Worker }
1353*f6dc9357SAndroid Build Coastguard Worker
1354*f6dc9357SAndroid Build Coastguard Worker UInt64 lastSector = 0;
1355*f6dc9357SAndroid Build Coastguard Worker UInt64 lastVirtCluster = 0;
1356*f6dc9357SAndroid Build Coastguard Worker size_t numProcessed_Prev = 0;
1357*f6dc9357SAndroid Build Coastguard Worker
1358*f6dc9357SAndroid Build Coastguard Worker for (size_t i = 0; i < numGdeEntries; i++)
1359*f6dc9357SAndroid Build Coastguard Worker {
1360*f6dc9357SAndroid Build Coastguard Worker const size_t k_NumSectors = (size_t)1 << (k_NumMidBits - 9 + 2);
1361*f6dc9357SAndroid Build Coastguard Worker const size_t k_NumMidItems = (size_t)1 << k_NumMidBits;
1362*f6dc9357SAndroid Build Coastguard Worker
1363*f6dc9357SAndroid Build Coastguard Worker CByteBuffer &buf = Tables.AddNew();
1364*f6dc9357SAndroid Build Coastguard Worker
1365*f6dc9357SAndroid Build Coastguard Worker {
1366*f6dc9357SAndroid Build Coastguard Worker const UInt32 v = Get32((const Byte *)table + (size_t)i * 4);
1367*f6dc9357SAndroid Build Coastguard Worker if (v == 0 || v == ZeroSector)
1368*f6dc9357SAndroid Build Coastguard Worker continue;
1369*f6dc9357SAndroid Build Coastguard Worker if (openCallback && (i - numProcessed_Prev) >= 1024)
1370*f6dc9357SAndroid Build Coastguard Worker {
1371*f6dc9357SAndroid Build Coastguard Worker const UInt64 comp = complexityStart + ((UInt64)i << (k_NumMidBits + 2));
1372*f6dc9357SAndroid Build Coastguard Worker const UInt64 volIndex2 = volIndex;
1373*f6dc9357SAndroid Build Coastguard Worker RINOK(openCallback->SetCompleted(numVols == 1 ? NULL : &volIndex2, &comp))
1374*f6dc9357SAndroid Build Coastguard Worker numProcessed_Prev = i;
1375*f6dc9357SAndroid Build Coastguard Worker }
1376*f6dc9357SAndroid Build Coastguard Worker
1377*f6dc9357SAndroid Build Coastguard Worker if (h.Is_Marker())
1378*f6dc9357SAndroid Build Coastguard Worker {
1379*f6dc9357SAndroid Build Coastguard Worker Byte buf2[1 << 9];
1380*f6dc9357SAndroid Build Coastguard Worker if (ReadForHeader(stream, v - 1, buf2, 1) != S_OK)
1381*f6dc9357SAndroid Build Coastguard Worker return S_FALSE;
1382*f6dc9357SAndroid Build Coastguard Worker {
1383*f6dc9357SAndroid Build Coastguard Worker CMarker m;
1384*f6dc9357SAndroid Build Coastguard Worker m.Parse(buf2);
1385*f6dc9357SAndroid Build Coastguard Worker if (m.Type != k_Marker_GRAIN_TABLE
1386*f6dc9357SAndroid Build Coastguard Worker || m.NumSectors != k_NumSectors
1387*f6dc9357SAndroid Build Coastguard Worker || m.SpecSize != 0)
1388*f6dc9357SAndroid Build Coastguard Worker return S_FALSE;
1389*f6dc9357SAndroid Build Coastguard Worker }
1390*f6dc9357SAndroid Build Coastguard Worker }
1391*f6dc9357SAndroid Build Coastguard Worker
1392*f6dc9357SAndroid Build Coastguard Worker buf.Alloc(k_NumMidItems * 4);
1393*f6dc9357SAndroid Build Coastguard Worker RINOK(ReadForHeader(stream, v, buf, k_NumSectors))
1394*f6dc9357SAndroid Build Coastguard Worker }
1395*f6dc9357SAndroid Build Coastguard Worker
1396*f6dc9357SAndroid Build Coastguard Worker for (size_t k = 0; k < k_NumMidItems; k++)
1397*f6dc9357SAndroid Build Coastguard Worker {
1398*f6dc9357SAndroid Build Coastguard Worker const UInt32 v = Get32((const Byte *)buf + (size_t)k * 4);
1399*f6dc9357SAndroid Build Coastguard Worker if (v == 0 || v == ZeroSector)
1400*f6dc9357SAndroid Build Coastguard Worker continue;
1401*f6dc9357SAndroid Build Coastguard Worker if (v < h.overHead)
1402*f6dc9357SAndroid Build Coastguard Worker return S_FALSE;
1403*f6dc9357SAndroid Build Coastguard Worker if (lastSector < v)
1404*f6dc9357SAndroid Build Coastguard Worker {
1405*f6dc9357SAndroid Build Coastguard Worker lastSector = v;
1406*f6dc9357SAndroid Build Coastguard Worker if (NeedDeflate)
1407*f6dc9357SAndroid Build Coastguard Worker lastVirtCluster = ((UInt64)i << k_NumMidBits) + k;
1408*f6dc9357SAndroid Build Coastguard Worker }
1409*f6dc9357SAndroid Build Coastguard Worker }
1410*f6dc9357SAndroid Build Coastguard Worker }
1411*f6dc9357SAndroid Build Coastguard Worker
1412*f6dc9357SAndroid Build Coastguard Worker if (!NeedDeflate)
1413*f6dc9357SAndroid Build Coastguard Worker {
1414*f6dc9357SAndroid Build Coastguard Worker UInt64 end = ((UInt64)lastSector << 9) + clusterSize;
1415*f6dc9357SAndroid Build Coastguard Worker if (PhySize < end)
1416*f6dc9357SAndroid Build Coastguard Worker PhySize = end;
1417*f6dc9357SAndroid Build Coastguard Worker }
1418*f6dc9357SAndroid Build Coastguard Worker else if (lastSector != 0)
1419*f6dc9357SAndroid Build Coastguard Worker {
1420*f6dc9357SAndroid Build Coastguard Worker Byte buf[1 << 9];
1421*f6dc9357SAndroid Build Coastguard Worker if (ReadForHeader(stream, lastSector, buf, 1) == S_OK)
1422*f6dc9357SAndroid Build Coastguard Worker {
1423*f6dc9357SAndroid Build Coastguard Worker UInt64 lba = Get64(buf);
1424*f6dc9357SAndroid Build Coastguard Worker if (lba == (lastVirtCluster << (ClusterBits - 9)))
1425*f6dc9357SAndroid Build Coastguard Worker {
1426*f6dc9357SAndroid Build Coastguard Worker UInt32 dataSize = Get32(buf + 8);
1427*f6dc9357SAndroid Build Coastguard Worker size_t dataSize2 = (size_t)dataSize + 12;
1428*f6dc9357SAndroid Build Coastguard Worker dataSize2 = (dataSize2 + 511) & ~(size_t)511;
1429*f6dc9357SAndroid Build Coastguard Worker UInt64 end = ((UInt64)lastSector << 9) + dataSize2;
1430*f6dc9357SAndroid Build Coastguard Worker if (PhySize < end)
1431*f6dc9357SAndroid Build Coastguard Worker PhySize = end;
1432*f6dc9357SAndroid Build Coastguard Worker }
1433*f6dc9357SAndroid Build Coastguard Worker }
1434*f6dc9357SAndroid Build Coastguard Worker }
1435*f6dc9357SAndroid Build Coastguard Worker
1436*f6dc9357SAndroid Build Coastguard Worker return S_OK;
1437*f6dc9357SAndroid Build Coastguard Worker }
1438*f6dc9357SAndroid Build Coastguard Worker
1439*f6dc9357SAndroid Build Coastguard Worker
1440*f6dc9357SAndroid Build Coastguard Worker Z7_COM7F_IMF(CHandler::Close())
1441*f6dc9357SAndroid Build Coastguard Worker {
1442*f6dc9357SAndroid Build Coastguard Worker _phySize = 0;
1443*f6dc9357SAndroid Build Coastguard Worker
1444*f6dc9357SAndroid Build Coastguard Worker _cacheCluster = (UInt64)(Int64)-1;
1445*f6dc9357SAndroid Build Coastguard Worker _cacheExtent = (unsigned)(int)-1;
1446*f6dc9357SAndroid Build Coastguard Worker
1447*f6dc9357SAndroid Build Coastguard Worker _clusterBitsMax = 0;
1448*f6dc9357SAndroid Build Coastguard Worker
1449*f6dc9357SAndroid Build Coastguard Worker _isArc = false;
1450*f6dc9357SAndroid Build Coastguard Worker _unsupported = false;
1451*f6dc9357SAndroid Build Coastguard Worker _unsupportedSome = false;
1452*f6dc9357SAndroid Build Coastguard Worker _headerError = false;
1453*f6dc9357SAndroid Build Coastguard Worker _missingVol = false;
1454*f6dc9357SAndroid Build Coastguard Worker _isMultiVol = false;
1455*f6dc9357SAndroid Build Coastguard Worker _needDeflate = false;
1456*f6dc9357SAndroid Build Coastguard Worker
1457*f6dc9357SAndroid Build Coastguard Worker _missingVolName.Empty();
1458*f6dc9357SAndroid Build Coastguard Worker
1459*f6dc9357SAndroid Build Coastguard Worker _descriptorBuf.Free();
1460*f6dc9357SAndroid Build Coastguard Worker _descriptor.Clear();
1461*f6dc9357SAndroid Build Coastguard Worker
1462*f6dc9357SAndroid Build Coastguard Worker // CHandlerImg:
1463*f6dc9357SAndroid Build Coastguard Worker Clear_HandlerImg_Vars();
1464*f6dc9357SAndroid Build Coastguard Worker Stream.Release();
1465*f6dc9357SAndroid Build Coastguard Worker
1466*f6dc9357SAndroid Build Coastguard Worker _extents.Clear();
1467*f6dc9357SAndroid Build Coastguard Worker return S_OK;
1468*f6dc9357SAndroid Build Coastguard Worker }
1469*f6dc9357SAndroid Build Coastguard Worker
1470*f6dc9357SAndroid Build Coastguard Worker
1471*f6dc9357SAndroid Build Coastguard Worker Z7_COM7F_IMF(CHandler::GetStream(UInt32 /* index */, ISequentialInStream **stream))
1472*f6dc9357SAndroid Build Coastguard Worker {
1473*f6dc9357SAndroid Build Coastguard Worker COM_TRY_BEGIN
1474*f6dc9357SAndroid Build Coastguard Worker *stream = NULL;
1475*f6dc9357SAndroid Build Coastguard Worker
1476*f6dc9357SAndroid Build Coastguard Worker if (_unsupported)
1477*f6dc9357SAndroid Build Coastguard Worker return S_FALSE;
1478*f6dc9357SAndroid Build Coastguard Worker
1479*f6dc9357SAndroid Build Coastguard Worker ClearStreamVars();
1480*f6dc9357SAndroid Build Coastguard Worker // _stream_UsePackSize = true;
1481*f6dc9357SAndroid Build Coastguard Worker
1482*f6dc9357SAndroid Build Coastguard Worker if (_needDeflate)
1483*f6dc9357SAndroid Build Coastguard Worker {
1484*f6dc9357SAndroid Build Coastguard Worker if (!_bufInStream)
1485*f6dc9357SAndroid Build Coastguard Worker {
1486*f6dc9357SAndroid Build Coastguard Worker _bufInStreamSpec = new CBufInStream;
1487*f6dc9357SAndroid Build Coastguard Worker _bufInStream = _bufInStreamSpec;
1488*f6dc9357SAndroid Build Coastguard Worker }
1489*f6dc9357SAndroid Build Coastguard Worker
1490*f6dc9357SAndroid Build Coastguard Worker if (!_bufOutStream)
1491*f6dc9357SAndroid Build Coastguard Worker {
1492*f6dc9357SAndroid Build Coastguard Worker _bufOutStreamSpec = new CBufPtrSeqOutStream();
1493*f6dc9357SAndroid Build Coastguard Worker _bufOutStream = _bufOutStreamSpec;
1494*f6dc9357SAndroid Build Coastguard Worker }
1495*f6dc9357SAndroid Build Coastguard Worker
1496*f6dc9357SAndroid Build Coastguard Worker if (!_zlibDecoder)
1497*f6dc9357SAndroid Build Coastguard Worker {
1498*f6dc9357SAndroid Build Coastguard Worker _zlibDecoderSpec = new NCompress::NZlib::CDecoder;
1499*f6dc9357SAndroid Build Coastguard Worker _zlibDecoder = _zlibDecoderSpec;
1500*f6dc9357SAndroid Build Coastguard Worker }
1501*f6dc9357SAndroid Build Coastguard Worker
1502*f6dc9357SAndroid Build Coastguard Worker const size_t clusterSize = (size_t)1 << _clusterBitsMax;
1503*f6dc9357SAndroid Build Coastguard Worker _cache.AllocAtLeast(clusterSize);
1504*f6dc9357SAndroid Build Coastguard Worker _cacheCompressed.AllocAtLeast(clusterSize * 2);
1505*f6dc9357SAndroid Build Coastguard Worker }
1506*f6dc9357SAndroid Build Coastguard Worker
1507*f6dc9357SAndroid Build Coastguard Worker FOR_VECTOR (i, _extents)
1508*f6dc9357SAndroid Build Coastguard Worker {
1509*f6dc9357SAndroid Build Coastguard Worker RINOK(_extents[i].InitAndSeek())
1510*f6dc9357SAndroid Build Coastguard Worker }
1511*f6dc9357SAndroid Build Coastguard Worker
1512*f6dc9357SAndroid Build Coastguard Worker CMyComPtr<ISequentialInStream> streamTemp = this;
1513*f6dc9357SAndroid Build Coastguard Worker InitAndSeekMain();
1514*f6dc9357SAndroid Build Coastguard Worker *stream = streamTemp.Detach();
1515*f6dc9357SAndroid Build Coastguard Worker return S_OK;
1516*f6dc9357SAndroid Build Coastguard Worker COM_TRY_END
1517*f6dc9357SAndroid Build Coastguard Worker }
1518*f6dc9357SAndroid Build Coastguard Worker
1519*f6dc9357SAndroid Build Coastguard Worker
1520*f6dc9357SAndroid Build Coastguard Worker REGISTER_ARC_I(
1521*f6dc9357SAndroid Build Coastguard Worker "VMDK", "vmdk", NULL, 0xC8,
1522*f6dc9357SAndroid Build Coastguard Worker k_Signature,
1523*f6dc9357SAndroid Build Coastguard Worker 0,
1524*f6dc9357SAndroid Build Coastguard Worker 0,
1525*f6dc9357SAndroid Build Coastguard Worker NULL)
1526*f6dc9357SAndroid Build Coastguard Worker
1527*f6dc9357SAndroid Build Coastguard Worker }}
1528