xref: /aosp_15_r20/external/lzma/CPP/7zip/Archive/Udf/UdfIn.cpp (revision f6dc9357d832569d4d1f5d24eacdb3935a1ae8e6)
1*f6dc9357SAndroid Build Coastguard Worker // Archive/UdfIn.cpp
2*f6dc9357SAndroid Build Coastguard Worker 
3*f6dc9357SAndroid Build Coastguard Worker #include "StdAfx.h"
4*f6dc9357SAndroid Build Coastguard Worker 
5*f6dc9357SAndroid Build Coastguard Worker // #define SHOW_DEBUG_INFO
6*f6dc9357SAndroid Build Coastguard Worker 
7*f6dc9357SAndroid Build Coastguard Worker #ifdef SHOW_DEBUG_INFO
8*f6dc9357SAndroid Build Coastguard Worker #include <stdio.h>
9*f6dc9357SAndroid Build Coastguard Worker #endif
10*f6dc9357SAndroid Build Coastguard Worker 
11*f6dc9357SAndroid Build Coastguard Worker #include "../../../../C/CpuArch.h"
12*f6dc9357SAndroid Build Coastguard Worker 
13*f6dc9357SAndroid Build Coastguard Worker #include "../../../Windows/PropVariantUtils.h"
14*f6dc9357SAndroid Build Coastguard Worker 
15*f6dc9357SAndroid Build Coastguard Worker #include "../../Common/RegisterArc.h"
16*f6dc9357SAndroid Build Coastguard Worker #include "../../Common/StreamUtils.h"
17*f6dc9357SAndroid Build Coastguard Worker 
18*f6dc9357SAndroid Build Coastguard Worker #include "UdfIn.h"
19*f6dc9357SAndroid Build Coastguard Worker 
20*f6dc9357SAndroid Build Coastguard Worker #ifdef SHOW_DEBUG_INFO
21*f6dc9357SAndroid Build Coastguard Worker #define PRF(x) x
22*f6dc9357SAndroid Build Coastguard Worker #else
23*f6dc9357SAndroid Build Coastguard Worker #define PRF(x)
24*f6dc9357SAndroid Build Coastguard Worker #endif
25*f6dc9357SAndroid Build Coastguard Worker 
26*f6dc9357SAndroid Build Coastguard Worker #define Get16(p) GetUi16(p)
27*f6dc9357SAndroid Build Coastguard Worker #define Get32(p) GetUi32(p)
28*f6dc9357SAndroid Build Coastguard Worker #define Get64(p) GetUi64(p)
29*f6dc9357SAndroid Build Coastguard Worker 
30*f6dc9357SAndroid Build Coastguard Worker #define G16(_offs_, dest) dest = Get16(p + (_offs_))
31*f6dc9357SAndroid Build Coastguard Worker #define G32(_offs_, dest) dest = Get32(p + (_offs_))
32*f6dc9357SAndroid Build Coastguard Worker #define G64(_offs_, dest) dest = Get64(p + (_offs_))
33*f6dc9357SAndroid Build Coastguard Worker 
34*f6dc9357SAndroid Build Coastguard Worker namespace NArchive {
35*f6dc9357SAndroid Build Coastguard Worker namespace NUdf {
36*f6dc9357SAndroid Build Coastguard Worker 
37*f6dc9357SAndroid Build Coastguard Worker static const unsigned kNumPartitionsMax = 64;
38*f6dc9357SAndroid Build Coastguard Worker static const unsigned kNumLogVolumesMax = 64;
39*f6dc9357SAndroid Build Coastguard Worker static const unsigned kNumRecursionLevelsMax = 1 << 10;
40*f6dc9357SAndroid Build Coastguard Worker static const unsigned kNumItemsMax = 1 << 27;
41*f6dc9357SAndroid Build Coastguard Worker static const unsigned kNumFilesMax = 1 << 28;
42*f6dc9357SAndroid Build Coastguard Worker static const unsigned kNumRefsMax = 1 << 28;
43*f6dc9357SAndroid Build Coastguard Worker static const UInt32 kNumExtentsMax = (UInt32)1 << 30;
44*f6dc9357SAndroid Build Coastguard Worker static const UInt64 kFileNameLengthTotalMax = (UInt64)1 << 33;
45*f6dc9357SAndroid Build Coastguard Worker static const UInt64 kInlineExtentsSizeMax = (UInt64)1 << 33;
46*f6dc9357SAndroid Build Coastguard Worker 
47*f6dc9357SAndroid Build Coastguard Worker #define CRC16_INIT_VAL 0
48*f6dc9357SAndroid Build Coastguard Worker #define CRC16_UPDATE_BYTE(crc, b) ((UInt16)(g_Crc16Table[(((crc) >> 8) ^ (b)) & 0xFF] ^ ((crc) << 8)))
49*f6dc9357SAndroid Build Coastguard Worker 
50*f6dc9357SAndroid Build Coastguard Worker #define kCrc16Poly 0x1021
51*f6dc9357SAndroid Build Coastguard Worker static UInt16 g_Crc16Table[256];
52*f6dc9357SAndroid Build Coastguard Worker 
Crc16GenerateTable(void)53*f6dc9357SAndroid Build Coastguard Worker static void Z7_FASTCALL Crc16GenerateTable(void)
54*f6dc9357SAndroid Build Coastguard Worker {
55*f6dc9357SAndroid Build Coastguard Worker   UInt32 i;
56*f6dc9357SAndroid Build Coastguard Worker   for (i = 0; i < 256; i++)
57*f6dc9357SAndroid Build Coastguard Worker   {
58*f6dc9357SAndroid Build Coastguard Worker     UInt32 r = (i << 8);
59*f6dc9357SAndroid Build Coastguard Worker     for (unsigned j = 0; j < 8; j++)
60*f6dc9357SAndroid Build Coastguard Worker       r = ((r << 1) ^ (kCrc16Poly & ((UInt32)0 - (r >> 15)))) & 0xFFFF;
61*f6dc9357SAndroid Build Coastguard Worker     g_Crc16Table[i] = (UInt16)r;
62*f6dc9357SAndroid Build Coastguard Worker   }
63*f6dc9357SAndroid Build Coastguard Worker }
64*f6dc9357SAndroid Build Coastguard Worker 
Crc16Calc(const void * data,size_t size)65*f6dc9357SAndroid Build Coastguard Worker static UInt32 Z7_FASTCALL Crc16Calc(const void *data, size_t size)
66*f6dc9357SAndroid Build Coastguard Worker {
67*f6dc9357SAndroid Build Coastguard Worker   UInt32 v = CRC16_INIT_VAL;
68*f6dc9357SAndroid Build Coastguard Worker   const Byte *p = (const Byte *)data;
69*f6dc9357SAndroid Build Coastguard Worker   const Byte *pEnd = p + size;
70*f6dc9357SAndroid Build Coastguard Worker   for (; p != pEnd; p++)
71*f6dc9357SAndroid Build Coastguard Worker     v = CRC16_UPDATE_BYTE(v, *p);
72*f6dc9357SAndroid Build Coastguard Worker   return v;
73*f6dc9357SAndroid Build Coastguard Worker }
74*f6dc9357SAndroid Build Coastguard Worker 
CCrc16TableInitNArchive::NUdf::CCrc16TableInit75*f6dc9357SAndroid Build Coastguard Worker static struct CCrc16TableInit { CCrc16TableInit() { Crc16GenerateTable(); } } g_Crc16TableInit;
76*f6dc9357SAndroid Build Coastguard Worker 
77*f6dc9357SAndroid Build Coastguard Worker 
78*f6dc9357SAndroid Build Coastguard Worker // ---------- ECMA Part 1 ----------
79*f6dc9357SAndroid Build Coastguard Worker 
Parse(const Byte * p,unsigned size)80*f6dc9357SAndroid Build Coastguard Worker void CDString::Parse(const Byte *p, unsigned size)
81*f6dc9357SAndroid Build Coastguard Worker {
82*f6dc9357SAndroid Build Coastguard Worker   Data.CopyFrom(p, size);
83*f6dc9357SAndroid Build Coastguard Worker }
84*f6dc9357SAndroid Build Coastguard Worker 
ParseDString(const Byte * data,unsigned size)85*f6dc9357SAndroid Build Coastguard Worker static UString ParseDString(const Byte *data, unsigned size)
86*f6dc9357SAndroid Build Coastguard Worker {
87*f6dc9357SAndroid Build Coastguard Worker   UString res;
88*f6dc9357SAndroid Build Coastguard Worker   if (size != 0)
89*f6dc9357SAndroid Build Coastguard Worker   {
90*f6dc9357SAndroid Build Coastguard Worker     wchar_t *p;
91*f6dc9357SAndroid Build Coastguard Worker     const Byte type = *data++;
92*f6dc9357SAndroid Build Coastguard Worker     size--;
93*f6dc9357SAndroid Build Coastguard Worker     if (type == 8)
94*f6dc9357SAndroid Build Coastguard Worker     {
95*f6dc9357SAndroid Build Coastguard Worker       p = res.GetBuf(size);
96*f6dc9357SAndroid Build Coastguard Worker       for (unsigned i = 0; i < size; i++)
97*f6dc9357SAndroid Build Coastguard Worker       {
98*f6dc9357SAndroid Build Coastguard Worker         const wchar_t c = data[i];
99*f6dc9357SAndroid Build Coastguard Worker         if (c == 0)
100*f6dc9357SAndroid Build Coastguard Worker           break;
101*f6dc9357SAndroid Build Coastguard Worker         *p++ = c;
102*f6dc9357SAndroid Build Coastguard Worker       }
103*f6dc9357SAndroid Build Coastguard Worker     }
104*f6dc9357SAndroid Build Coastguard Worker     else if (type == 16)
105*f6dc9357SAndroid Build Coastguard Worker     {
106*f6dc9357SAndroid Build Coastguard Worker       size &= ~(unsigned)1;
107*f6dc9357SAndroid Build Coastguard Worker       p = res.GetBuf(size / 2);
108*f6dc9357SAndroid Build Coastguard Worker       for (unsigned i = 0; i < size; i += 2)
109*f6dc9357SAndroid Build Coastguard Worker       {
110*f6dc9357SAndroid Build Coastguard Worker         const wchar_t c = GetBe16(data + i);
111*f6dc9357SAndroid Build Coastguard Worker         if (c == 0)
112*f6dc9357SAndroid Build Coastguard Worker           break;
113*f6dc9357SAndroid Build Coastguard Worker         *p++ = c;
114*f6dc9357SAndroid Build Coastguard Worker       }
115*f6dc9357SAndroid Build Coastguard Worker     }
116*f6dc9357SAndroid Build Coastguard Worker     else
117*f6dc9357SAndroid Build Coastguard Worker       return UString("[unknown]");
118*f6dc9357SAndroid Build Coastguard Worker     *p = 0;
119*f6dc9357SAndroid Build Coastguard Worker     res.ReleaseBuf_SetLen((unsigned)(p - (const wchar_t *)res));
120*f6dc9357SAndroid Build Coastguard Worker   }
121*f6dc9357SAndroid Build Coastguard Worker   return res;
122*f6dc9357SAndroid Build Coastguard Worker }
123*f6dc9357SAndroid Build Coastguard Worker 
GetString() const124*f6dc9357SAndroid Build Coastguard Worker UString CDString32::GetString() const
125*f6dc9357SAndroid Build Coastguard Worker {
126*f6dc9357SAndroid Build Coastguard Worker   const unsigned size = Data[sizeof(Data) - 1];
127*f6dc9357SAndroid Build Coastguard Worker   return ParseDString(Data, MyMin(size, (unsigned)(sizeof(Data) - 1)));
128*f6dc9357SAndroid Build Coastguard Worker }
129*f6dc9357SAndroid Build Coastguard Worker 
GetString() const130*f6dc9357SAndroid Build Coastguard Worker UString CDString128::GetString() const
131*f6dc9357SAndroid Build Coastguard Worker {
132*f6dc9357SAndroid Build Coastguard Worker   const unsigned size = Data[sizeof(Data) - 1];
133*f6dc9357SAndroid Build Coastguard Worker   return ParseDString(Data, MyMin(size, (unsigned)(sizeof(Data) - 1)));
134*f6dc9357SAndroid Build Coastguard Worker }
135*f6dc9357SAndroid Build Coastguard Worker 
GetString() const136*f6dc9357SAndroid Build Coastguard Worker UString CDString::GetString() const { return ParseDString(Data, (unsigned)Data.Size()); }
137*f6dc9357SAndroid Build Coastguard Worker 
Parse(const Byte * p)138*f6dc9357SAndroid Build Coastguard Worker void CTime::Parse(const Byte *p) { memcpy(Data, p, sizeof(Data)); }
139*f6dc9357SAndroid Build Coastguard Worker 
140*f6dc9357SAndroid Build Coastguard Worker 
AddCommentChars(UString & dest,const char * s,size_t size)141*f6dc9357SAndroid Build Coastguard Worker static void AddCommentChars(UString &dest, const char *s, size_t size)
142*f6dc9357SAndroid Build Coastguard Worker {
143*f6dc9357SAndroid Build Coastguard Worker   for (size_t i = 0; i < size; i++)
144*f6dc9357SAndroid Build Coastguard Worker   {
145*f6dc9357SAndroid Build Coastguard Worker     char c = s[i];
146*f6dc9357SAndroid Build Coastguard Worker     if (c == 0)
147*f6dc9357SAndroid Build Coastguard Worker       break;
148*f6dc9357SAndroid Build Coastguard Worker     if (c < 0x20)
149*f6dc9357SAndroid Build Coastguard Worker       c = '_';
150*f6dc9357SAndroid Build Coastguard Worker     dest += (wchar_t)c;
151*f6dc9357SAndroid Build Coastguard Worker   }
152*f6dc9357SAndroid Build Coastguard Worker }
153*f6dc9357SAndroid Build Coastguard Worker 
154*f6dc9357SAndroid Build Coastguard Worker 
Parse(const Byte * p)155*f6dc9357SAndroid Build Coastguard Worker void CRegId::Parse(const Byte *p)
156*f6dc9357SAndroid Build Coastguard Worker {
157*f6dc9357SAndroid Build Coastguard Worker   Flags = p[0];
158*f6dc9357SAndroid Build Coastguard Worker   memcpy(Id, p + 1, sizeof(Id));
159*f6dc9357SAndroid Build Coastguard Worker   memcpy(Suffix, p + 24, sizeof(Suffix));
160*f6dc9357SAndroid Build Coastguard Worker }
161*f6dc9357SAndroid Build Coastguard Worker 
AddCommentTo(UString & s) const162*f6dc9357SAndroid Build Coastguard Worker void CRegId::AddCommentTo(UString &s) const
163*f6dc9357SAndroid Build Coastguard Worker {
164*f6dc9357SAndroid Build Coastguard Worker   AddCommentChars(s, Id, sizeof(Id));
165*f6dc9357SAndroid Build Coastguard Worker }
166*f6dc9357SAndroid Build Coastguard Worker 
AddUdfVersionTo(UString & s) const167*f6dc9357SAndroid Build Coastguard Worker void CRegId::AddUdfVersionTo(UString &s) const
168*f6dc9357SAndroid Build Coastguard Worker {
169*f6dc9357SAndroid Build Coastguard Worker   // use it only for "Domain Identifier Suffix" and "UDF Identifier Suffix"
170*f6dc9357SAndroid Build Coastguard Worker   // UDF 2.1.5.3
171*f6dc9357SAndroid Build Coastguard Worker   // Revision in hex (3 digits)
172*f6dc9357SAndroid Build Coastguard Worker   const Byte minor = Suffix[0];
173*f6dc9357SAndroid Build Coastguard Worker   const Byte major = Suffix[1];
174*f6dc9357SAndroid Build Coastguard Worker   if (major != 0 || minor != 0)
175*f6dc9357SAndroid Build Coastguard Worker   {
176*f6dc9357SAndroid Build Coastguard Worker     char temp[16];
177*f6dc9357SAndroid Build Coastguard Worker     ConvertUInt32ToHex(major, temp);
178*f6dc9357SAndroid Build Coastguard Worker     s += temp;
179*f6dc9357SAndroid Build Coastguard Worker     s.Add_Dot();
180*f6dc9357SAndroid Build Coastguard Worker     ConvertUInt32ToHex8Digits(minor, temp);
181*f6dc9357SAndroid Build Coastguard Worker     s += &temp[8 - 2];
182*f6dc9357SAndroid Build Coastguard Worker   }
183*f6dc9357SAndroid Build Coastguard Worker }
184*f6dc9357SAndroid Build Coastguard Worker 
185*f6dc9357SAndroid Build Coastguard Worker 
186*f6dc9357SAndroid Build Coastguard Worker // ---------- ECMA Part 3: Volume Structure ----------
187*f6dc9357SAndroid Build Coastguard Worker 
Parse(const Byte * p)188*f6dc9357SAndroid Build Coastguard Worker void CExtent::Parse(const Byte *p)
189*f6dc9357SAndroid Build Coastguard Worker {
190*f6dc9357SAndroid Build Coastguard Worker   /* Len shall be less than < 2^30.
191*f6dc9357SAndroid Build Coastguard Worker      Unless otherwise specified, the length shall be an integral multiple of the logical sector size.
192*f6dc9357SAndroid Build Coastguard Worker      If (Len == 0), no extent is specified and (Pos) shall contain 0 */
193*f6dc9357SAndroid Build Coastguard Worker   G32 (0, Len);
194*f6dc9357SAndroid Build Coastguard Worker   G32 (4, Pos);
195*f6dc9357SAndroid Build Coastguard Worker }
196*f6dc9357SAndroid Build Coastguard Worker 
197*f6dc9357SAndroid Build Coastguard Worker 
198*f6dc9357SAndroid Build Coastguard Worker // ECMA 3/7.2
199*f6dc9357SAndroid Build Coastguard Worker 
200*f6dc9357SAndroid Build Coastguard Worker struct CTag
201*f6dc9357SAndroid Build Coastguard Worker {
202*f6dc9357SAndroid Build Coastguard Worker   UInt16 Id;
203*f6dc9357SAndroid Build Coastguard Worker   // UInt16 Version;
204*f6dc9357SAndroid Build Coastguard Worker   // Byte Checksum;
205*f6dc9357SAndroid Build Coastguard Worker   // UInt16 SerialNumber;
206*f6dc9357SAndroid Build Coastguard Worker   // UInt16 Crc;
207*f6dc9357SAndroid Build Coastguard Worker   UInt16 CrcLen;
208*f6dc9357SAndroid Build Coastguard Worker   // UInt32 TagLocation; // the number of the logical sector
209*f6dc9357SAndroid Build Coastguard Worker 
210*f6dc9357SAndroid Build Coastguard Worker   HRESULT Parse(const Byte *p, size_t size);
211*f6dc9357SAndroid Build Coastguard Worker };
212*f6dc9357SAndroid Build Coastguard Worker 
Parse(const Byte * p,size_t size)213*f6dc9357SAndroid Build Coastguard Worker HRESULT CTag::Parse(const Byte *p, size_t size)
214*f6dc9357SAndroid Build Coastguard Worker {
215*f6dc9357SAndroid Build Coastguard Worker   if (size < 16)
216*f6dc9357SAndroid Build Coastguard Worker     return S_FALSE;
217*f6dc9357SAndroid Build Coastguard Worker   {
218*f6dc9357SAndroid Build Coastguard Worker     unsigned sum = 0;
219*f6dc9357SAndroid Build Coastguard Worker     for (unsigned i = 0; i < 16; i++)
220*f6dc9357SAndroid Build Coastguard Worker       sum = sum + p[i];
221*f6dc9357SAndroid Build Coastguard Worker     if ((Byte)(sum - p[4]) != p[4] || p[5] != 0)
222*f6dc9357SAndroid Build Coastguard Worker       return S_FALSE;
223*f6dc9357SAndroid Build Coastguard Worker   }
224*f6dc9357SAndroid Build Coastguard Worker   Id = Get16(p);
225*f6dc9357SAndroid Build Coastguard Worker   const UInt16 Version = Get16(p + 2);
226*f6dc9357SAndroid Build Coastguard Worker   if (Version != 2 && Version != 3)
227*f6dc9357SAndroid Build Coastguard Worker     return S_FALSE;
228*f6dc9357SAndroid Build Coastguard Worker   // SerialNumber = Get16(p + 6);
229*f6dc9357SAndroid Build Coastguard Worker   const UInt32 crc = Get16(p + 8);
230*f6dc9357SAndroid Build Coastguard Worker   CrcLen = Get16(p + 10);
231*f6dc9357SAndroid Build Coastguard Worker   // TagLocation = Get32(p + 12);
232*f6dc9357SAndroid Build Coastguard Worker 
233*f6dc9357SAndroid Build Coastguard Worker   if (size >= 16 + (size_t)CrcLen)
234*f6dc9357SAndroid Build Coastguard Worker     if (crc == Crc16Calc(p + 16, (size_t)CrcLen))
235*f6dc9357SAndroid Build Coastguard Worker       return S_OK;
236*f6dc9357SAndroid Build Coastguard Worker   return S_FALSE;
237*f6dc9357SAndroid Build Coastguard Worker }
238*f6dc9357SAndroid Build Coastguard Worker 
239*f6dc9357SAndroid Build Coastguard Worker // ECMA 3/7.2.1
240*f6dc9357SAndroid Build Coastguard Worker 
241*f6dc9357SAndroid Build Coastguard Worker enum EDescriptorType
242*f6dc9357SAndroid Build Coastguard Worker {
243*f6dc9357SAndroid Build Coastguard Worker   DESC_TYPE_SpoaringTable       = 0, // UDF
244*f6dc9357SAndroid Build Coastguard Worker   DESC_TYPE_PrimVol             = 1,
245*f6dc9357SAndroid Build Coastguard Worker   DESC_TYPE_AnchorVolPtr        = 2,
246*f6dc9357SAndroid Build Coastguard Worker   DESC_TYPE_VolPtr              = 3,
247*f6dc9357SAndroid Build Coastguard Worker   DESC_TYPE_ImplUseVol          = 4,
248*f6dc9357SAndroid Build Coastguard Worker   DESC_TYPE_Partition           = 5,
249*f6dc9357SAndroid Build Coastguard Worker   DESC_TYPE_LogicalVol          = 6,
250*f6dc9357SAndroid Build Coastguard Worker   DESC_TYPE_UnallocSpace        = 7,
251*f6dc9357SAndroid Build Coastguard Worker   DESC_TYPE_Terminating         = 8,
252*f6dc9357SAndroid Build Coastguard Worker   DESC_TYPE_LogicalVolIntegrity = 9,
253*f6dc9357SAndroid Build Coastguard Worker   DESC_TYPE_FileSet             = 256,
254*f6dc9357SAndroid Build Coastguard Worker   DESC_TYPE_FileId              = 257,
255*f6dc9357SAndroid Build Coastguard Worker   DESC_TYPE_AllocationExtent    = 258,
256*f6dc9357SAndroid Build Coastguard Worker   DESC_TYPE_Indirect            = 259,
257*f6dc9357SAndroid Build Coastguard Worker   DESC_TYPE_Terminal            = 260,
258*f6dc9357SAndroid Build Coastguard Worker   DESC_TYPE_File                = 261,
259*f6dc9357SAndroid Build Coastguard Worker   DESC_TYPE_ExtendedAttrHeader  = 262,
260*f6dc9357SAndroid Build Coastguard Worker   DESC_TYPE_UnallocatedSpaceEntry = 263,
261*f6dc9357SAndroid Build Coastguard Worker   DESC_TYPE_SpaceBitmap         = 264,
262*f6dc9357SAndroid Build Coastguard Worker   DESC_TYPE_PartitionIntegrity  = 265,
263*f6dc9357SAndroid Build Coastguard Worker   DESC_TYPE_ExtendedFile        = 266
264*f6dc9357SAndroid Build Coastguard Worker };
265*f6dc9357SAndroid Build Coastguard Worker 
266*f6dc9357SAndroid Build Coastguard Worker 
Parse(const Byte * p)267*f6dc9357SAndroid Build Coastguard Worker void CLogBlockAddr::Parse(const Byte *p)
268*f6dc9357SAndroid Build Coastguard Worker {
269*f6dc9357SAndroid Build Coastguard Worker   G32 (0, Pos);
270*f6dc9357SAndroid Build Coastguard Worker   G16 (4, PartitionRef);
271*f6dc9357SAndroid Build Coastguard Worker }
272*f6dc9357SAndroid Build Coastguard Worker 
Parse(const Byte * p)273*f6dc9357SAndroid Build Coastguard Worker void CShortAllocDesc::Parse(const Byte *p)
274*f6dc9357SAndroid Build Coastguard Worker {
275*f6dc9357SAndroid Build Coastguard Worker   G32 (0, Len);
276*f6dc9357SAndroid Build Coastguard Worker   G32 (4, Pos);
277*f6dc9357SAndroid Build Coastguard Worker }
278*f6dc9357SAndroid Build Coastguard Worker 
279*f6dc9357SAndroid Build Coastguard Worker /*
280*f6dc9357SAndroid Build Coastguard Worker void CADImpUse::Parse(const Byte *p)
281*f6dc9357SAndroid Build Coastguard Worker {
282*f6dc9357SAndroid Build Coastguard Worker   G16 (0, Flags);
283*f6dc9357SAndroid Build Coastguard Worker   G32 (2, UdfUniqueId);
284*f6dc9357SAndroid Build Coastguard Worker }
285*f6dc9357SAndroid Build Coastguard Worker */
286*f6dc9357SAndroid Build Coastguard Worker 
Parse(const Byte * p)287*f6dc9357SAndroid Build Coastguard Worker void CLongAllocDesc::Parse(const Byte *p)
288*f6dc9357SAndroid Build Coastguard Worker {
289*f6dc9357SAndroid Build Coastguard Worker   G32 (0, Len);
290*f6dc9357SAndroid Build Coastguard Worker   Location.Parse(p + 4);
291*f6dc9357SAndroid Build Coastguard Worker   // memcpy(ImplUse, p + 10, sizeof(ImplUse));
292*f6dc9357SAndroid Build Coastguard Worker   // adImpUse.Parse(ImplUse);
293*f6dc9357SAndroid Build Coastguard Worker }
294*f6dc9357SAndroid Build Coastguard Worker 
295*f6dc9357SAndroid Build Coastguard Worker 
Parse(const Byte * p)296*f6dc9357SAndroid Build Coastguard Worker void CPrimeVol::Parse(const Byte *p)
297*f6dc9357SAndroid Build Coastguard Worker {
298*f6dc9357SAndroid Build Coastguard Worker   // G32 (16, VolumeDescriptorSequenceNumber);
299*f6dc9357SAndroid Build Coastguard Worker   G32 (20, PrimaryVolumeDescriptorNumber);
300*f6dc9357SAndroid Build Coastguard Worker   VolumeId.Parse(p + 24);
301*f6dc9357SAndroid Build Coastguard Worker   G16 (56, VolumeSequenceNumber);
302*f6dc9357SAndroid Build Coastguard Worker   G16 (58, MaximumVolumeSequenceNumber);
303*f6dc9357SAndroid Build Coastguard Worker   // G16 (60, InterchangeLevel);
304*f6dc9357SAndroid Build Coastguard Worker   // G16 (62, MaximumInterchangeLevel);
305*f6dc9357SAndroid Build Coastguard Worker   // G32 (64, CharacterSetList)
306*f6dc9357SAndroid Build Coastguard Worker   // G32 (68, MaximumCharacterSetList)
307*f6dc9357SAndroid Build Coastguard Worker   VolumeSetId.Parse(p + 72);
308*f6dc9357SAndroid Build Coastguard Worker   // 200 64 Descriptor Character Set charspec (1/7.2.1)
309*f6dc9357SAndroid Build Coastguard Worker   // 264 64 Explanatory Character Set charspec (1/7.2.1)
310*f6dc9357SAndroid Build Coastguard Worker   // VolumeAbstract.Parse(p + 328);
311*f6dc9357SAndroid Build Coastguard Worker   // VolumeCopyrightNotice.Parse(p + 336);
312*f6dc9357SAndroid Build Coastguard Worker   ApplicationId.Parse(p + 344);
313*f6dc9357SAndroid Build Coastguard Worker   RecordingTime.Parse(p + 376);
314*f6dc9357SAndroid Build Coastguard Worker   ImplId.Parse(p + 388);
315*f6dc9357SAndroid Build Coastguard Worker   // 420 64 Implementation Use bytes
316*f6dc9357SAndroid Build Coastguard Worker   // G32 (484, PredecessorVolumeDescriptorSequenceLocation);
317*f6dc9357SAndroid Build Coastguard Worker   // G16 (488, Flags);
318*f6dc9357SAndroid Build Coastguard Worker }
319*f6dc9357SAndroid Build Coastguard Worker 
320*f6dc9357SAndroid Build Coastguard Worker 
321*f6dc9357SAndroid Build Coastguard Worker 
CheckExtent(unsigned volIndex,unsigned partitionRef,UInt32 blockPos,UInt32 len) const322*f6dc9357SAndroid Build Coastguard Worker bool CInArchive::CheckExtent(unsigned volIndex, unsigned partitionRef, UInt32 blockPos, UInt32 len) const
323*f6dc9357SAndroid Build Coastguard Worker {
324*f6dc9357SAndroid Build Coastguard Worker   const CLogVol &vol = LogVols[volIndex];
325*f6dc9357SAndroid Build Coastguard Worker   if (partitionRef >= vol.PartitionMaps.Size())
326*f6dc9357SAndroid Build Coastguard Worker     return false;
327*f6dc9357SAndroid Build Coastguard Worker   const CPartition &partition = Partitions[vol.PartitionMaps[partitionRef].PartitionIndex];
328*f6dc9357SAndroid Build Coastguard Worker   return ((UInt64)blockPos * vol.BlockSize + len) <= ((UInt64)partition.Len << SecLogSize);
329*f6dc9357SAndroid Build Coastguard Worker }
330*f6dc9357SAndroid Build Coastguard Worker 
CheckItemExtents(unsigned volIndex,const CItem & item) const331*f6dc9357SAndroid Build Coastguard Worker bool CInArchive::CheckItemExtents(unsigned volIndex, const CItem &item) const
332*f6dc9357SAndroid Build Coastguard Worker {
333*f6dc9357SAndroid Build Coastguard Worker   FOR_VECTOR (i, item.Extents)
334*f6dc9357SAndroid Build Coastguard Worker   {
335*f6dc9357SAndroid Build Coastguard Worker     const CMyExtent &e = item.Extents[i];
336*f6dc9357SAndroid Build Coastguard Worker     if (!CheckExtent(volIndex, e.PartitionRef, e.Pos, e.GetLen()))
337*f6dc9357SAndroid Build Coastguard Worker       return false;
338*f6dc9357SAndroid Build Coastguard Worker   }
339*f6dc9357SAndroid Build Coastguard Worker   return true;
340*f6dc9357SAndroid Build Coastguard Worker }
341*f6dc9357SAndroid Build Coastguard Worker 
Read(unsigned volIndex,unsigned partitionRef,UInt32 blockPos,UInt32 len,Byte * buf)342*f6dc9357SAndroid Build Coastguard Worker HRESULT CInArchive::Read(unsigned volIndex, unsigned partitionRef, UInt32 blockPos, UInt32 len, Byte *buf)
343*f6dc9357SAndroid Build Coastguard Worker {
344*f6dc9357SAndroid Build Coastguard Worker   if (!CheckExtent(volIndex, partitionRef, blockPos, len))
345*f6dc9357SAndroid Build Coastguard Worker     return S_FALSE;
346*f6dc9357SAndroid Build Coastguard Worker   const CLogVol &vol = LogVols[volIndex];
347*f6dc9357SAndroid Build Coastguard Worker   const CPartition &partition = Partitions[vol.PartitionMaps[partitionRef].PartitionIndex];
348*f6dc9357SAndroid Build Coastguard Worker   UInt64 offset = ((UInt64)partition.Pos << SecLogSize) + (UInt64)blockPos * vol.BlockSize;
349*f6dc9357SAndroid Build Coastguard Worker   RINOK(InStream_SeekSet(_stream, offset))
350*f6dc9357SAndroid Build Coastguard Worker   offset += len;
351*f6dc9357SAndroid Build Coastguard Worker   UpdatePhySize(offset);
352*f6dc9357SAndroid Build Coastguard Worker   const HRESULT res = ReadStream_FALSE(_stream, buf, len);
353*f6dc9357SAndroid Build Coastguard Worker   if (res == S_FALSE && offset > FileSize)
354*f6dc9357SAndroid Build Coastguard Worker     UnexpectedEnd = true;
355*f6dc9357SAndroid Build Coastguard Worker   return res;
356*f6dc9357SAndroid Build Coastguard Worker }
357*f6dc9357SAndroid Build Coastguard Worker 
ReadLad(unsigned volIndex,const CLongAllocDesc & lad,Byte * buf)358*f6dc9357SAndroid Build Coastguard Worker HRESULT CInArchive::ReadLad(unsigned volIndex, const CLongAllocDesc &lad, Byte *buf)
359*f6dc9357SAndroid Build Coastguard Worker {
360*f6dc9357SAndroid Build Coastguard Worker   return Read(volIndex, lad.Location.PartitionRef, lad.Location.Pos, lad.GetLen(), (Byte *)buf);
361*f6dc9357SAndroid Build Coastguard Worker }
362*f6dc9357SAndroid Build Coastguard Worker 
ReadFromFile(unsigned volIndex,const CItem & item,CByteBuffer & buf)363*f6dc9357SAndroid Build Coastguard Worker HRESULT CInArchive::ReadFromFile(unsigned volIndex, const CItem &item, CByteBuffer &buf)
364*f6dc9357SAndroid Build Coastguard Worker {
365*f6dc9357SAndroid Build Coastguard Worker   if (item.Size >= (UInt32)1 << 30)
366*f6dc9357SAndroid Build Coastguard Worker     return S_FALSE;
367*f6dc9357SAndroid Build Coastguard Worker   if (item.IsInline)
368*f6dc9357SAndroid Build Coastguard Worker   {
369*f6dc9357SAndroid Build Coastguard Worker     buf = item.InlineData;
370*f6dc9357SAndroid Build Coastguard Worker     return S_OK;
371*f6dc9357SAndroid Build Coastguard Worker   }
372*f6dc9357SAndroid Build Coastguard Worker   buf.Alloc((size_t)item.Size);
373*f6dc9357SAndroid Build Coastguard Worker   size_t pos = 0;
374*f6dc9357SAndroid Build Coastguard Worker   FOR_VECTOR (i, item.Extents)
375*f6dc9357SAndroid Build Coastguard Worker   {
376*f6dc9357SAndroid Build Coastguard Worker     const CMyExtent &e = item.Extents[i];
377*f6dc9357SAndroid Build Coastguard Worker     const UInt32 len = e.GetLen();
378*f6dc9357SAndroid Build Coastguard Worker     RINOK(Read(volIndex, e.PartitionRef, e.Pos, len, (Byte *)buf + pos))
379*f6dc9357SAndroid Build Coastguard Worker     pos += len;
380*f6dc9357SAndroid Build Coastguard Worker   }
381*f6dc9357SAndroid Build Coastguard Worker   return S_OK;
382*f6dc9357SAndroid Build Coastguard Worker }
383*f6dc9357SAndroid Build Coastguard Worker 
384*f6dc9357SAndroid Build Coastguard Worker 
Parse(const Byte * p)385*f6dc9357SAndroid Build Coastguard Worker void CIcbTag::Parse(const Byte *p)
386*f6dc9357SAndroid Build Coastguard Worker {
387*f6dc9357SAndroid Build Coastguard Worker   // G32 (0, PriorDirectNum);
388*f6dc9357SAndroid Build Coastguard Worker   // G16 (4, StrategyType);
389*f6dc9357SAndroid Build Coastguard Worker   // G16 (6, StrategyParam);
390*f6dc9357SAndroid Build Coastguard Worker   // G16 (8, MaxNumOfEntries);
391*f6dc9357SAndroid Build Coastguard Worker   FileType = p[11];
392*f6dc9357SAndroid Build Coastguard Worker   // ParentIcb.Parse(p + 12);
393*f6dc9357SAndroid Build Coastguard Worker   G16 (18, Flags);
394*f6dc9357SAndroid Build Coastguard Worker }
395*f6dc9357SAndroid Build Coastguard Worker 
396*f6dc9357SAndroid Build Coastguard Worker 
397*f6dc9357SAndroid Build Coastguard Worker // ECMA 4/14.9 File Entry
398*f6dc9357SAndroid Build Coastguard Worker // UDF FileEntry 2.3.6
399*f6dc9357SAndroid Build Coastguard Worker 
400*f6dc9357SAndroid Build Coastguard Worker // ECMA 4/14.17 Extended File Entry
401*f6dc9357SAndroid Build Coastguard Worker 
Parse(const Byte * p)402*f6dc9357SAndroid Build Coastguard Worker void CItem::Parse(const Byte *p)
403*f6dc9357SAndroid Build Coastguard Worker {
404*f6dc9357SAndroid Build Coastguard Worker   // (-1) can be stored in Uid/Gid.
405*f6dc9357SAndroid Build Coastguard Worker   // G32 (36, Uid);
406*f6dc9357SAndroid Build Coastguard Worker   // G32 (40, Gid);
407*f6dc9357SAndroid Build Coastguard Worker   // G32 (44, Permissions);
408*f6dc9357SAndroid Build Coastguard Worker   G16 (48, FileLinkCount);
409*f6dc9357SAndroid Build Coastguard Worker   // RecordFormat = p[50];
410*f6dc9357SAndroid Build Coastguard Worker   // RecordDisplayAttr = p[51];
411*f6dc9357SAndroid Build Coastguard Worker   // G32 (52, RecordLen);
412*f6dc9357SAndroid Build Coastguard Worker   G64 (56, Size);
413*f6dc9357SAndroid Build Coastguard Worker   if (IsExtended)
414*f6dc9357SAndroid Build Coastguard Worker   {
415*f6dc9357SAndroid Build Coastguard Worker     // The sum of all Information Length fields for all streams of a file (including the default stream). If this file has no
416*f6dc9357SAndroid Build Coastguard Worker     // streams, the Object Size shall be equal to the Information Length.
417*f6dc9357SAndroid Build Coastguard Worker     // G64 (64, ObjectSize);
418*f6dc9357SAndroid Build Coastguard Worker     p += 8;
419*f6dc9357SAndroid Build Coastguard Worker   }
420*f6dc9357SAndroid Build Coastguard Worker   G64 (64, NumLogBlockRecorded);
421*f6dc9357SAndroid Build Coastguard Worker   ATime.Parse(p + 72);
422*f6dc9357SAndroid Build Coastguard Worker   MTime.Parse(p + 84);
423*f6dc9357SAndroid Build Coastguard Worker   if (IsExtended)
424*f6dc9357SAndroid Build Coastguard Worker   {
425*f6dc9357SAndroid Build Coastguard Worker     CreateTime.Parse(p + 96);
426*f6dc9357SAndroid Build Coastguard Worker     p += 12;
427*f6dc9357SAndroid Build Coastguard Worker   }
428*f6dc9357SAndroid Build Coastguard Worker   AttribTime.Parse(p + 96);
429*f6dc9357SAndroid Build Coastguard Worker   // G32 (108, CheckPoint);
430*f6dc9357SAndroid Build Coastguard Worker   /*
431*f6dc9357SAndroid Build Coastguard Worker   if (IsExtended)
432*f6dc9357SAndroid Build Coastguard Worker   {
433*f6dc9357SAndroid Build Coastguard Worker     // Get32(p + 112); // reserved
434*f6dc9357SAndroid Build Coastguard Worker     p += 4;
435*f6dc9357SAndroid Build Coastguard Worker   }
436*f6dc9357SAndroid Build Coastguard Worker   // ExtendedAttrIcb.Parse(p + 112);
437*f6dc9357SAndroid Build Coastguard Worker   if (IsExtended)
438*f6dc9357SAndroid Build Coastguard Worker   {
439*f6dc9357SAndroid Build Coastguard Worker     StreamDirectoryIcb.Parse(p + 128);
440*f6dc9357SAndroid Build Coastguard Worker     p += 16;
441*f6dc9357SAndroid Build Coastguard Worker   }
442*f6dc9357SAndroid Build Coastguard Worker   */
443*f6dc9357SAndroid Build Coastguard Worker 
444*f6dc9357SAndroid Build Coastguard Worker   // ImplId.Parse(p + 128);
445*f6dc9357SAndroid Build Coastguard Worker   // G64 (160, UniqueId);
446*f6dc9357SAndroid Build Coastguard Worker }
447*f6dc9357SAndroid Build Coastguard Worker 
448*f6dc9357SAndroid Build Coastguard Worker 
449*f6dc9357SAndroid Build Coastguard Worker // ECMA 4/14.4
450*f6dc9357SAndroid Build Coastguard Worker // UDF 2.3.4
451*f6dc9357SAndroid Build Coastguard Worker 
452*f6dc9357SAndroid Build Coastguard Worker /*
453*f6dc9357SAndroid Build Coastguard Worker File Characteristics:
454*f6dc9357SAndroid Build Coastguard Worker Deleted bit:
455*f6dc9357SAndroid Build Coastguard Worker   ECMA: If set to ONE, shall mean this File Identifier Descriptor
456*f6dc9357SAndroid Build Coastguard Worker         identifies a file that has been deleted;
457*f6dc9357SAndroid Build Coastguard Worker   UDF:  If the space for the file or directory is deallocated,
458*f6dc9357SAndroid Build Coastguard Worker         the implementation shall set the ICB field to zero.
459*f6dc9357SAndroid Build Coastguard Worker     ECMA 167 4/8.6 requires that the File Identifiers of all FIDs in a directory shall be unique.
460*f6dc9357SAndroid Build Coastguard Worker     The implementations shall follow these rules when a Deleted bit is set:
461*f6dc9357SAndroid Build Coastguard Worker     rewrire the compression ID of the File Identifier: 8 -> 254, 16 -> 255.
462*f6dc9357SAndroid Build Coastguard Worker */
463*f6dc9357SAndroid Build Coastguard Worker 
464*f6dc9357SAndroid Build Coastguard Worker struct CFileId
465*f6dc9357SAndroid Build Coastguard Worker {
466*f6dc9357SAndroid Build Coastguard Worker   // UInt16 FileVersion;
467*f6dc9357SAndroid Build Coastguard Worker   Byte FileCharacteristics;
468*f6dc9357SAndroid Build Coastguard Worker   // CByteBuffer ImplUse;
469*f6dc9357SAndroid Build Coastguard Worker   CDString Id;
470*f6dc9357SAndroid Build Coastguard Worker   CLongAllocDesc Icb;
471*f6dc9357SAndroid Build Coastguard Worker 
IsItLink_DirNArchive::NUdf::CFileId472*f6dc9357SAndroid Build Coastguard Worker   bool IsItLink_Dir    () const { return (FileCharacteristics & FILEID_CHARACS_Dir)     != 0; }
IsItLink_DeletedNArchive::NUdf::CFileId473*f6dc9357SAndroid Build Coastguard Worker   bool IsItLink_Deleted() const { return (FileCharacteristics & FILEID_CHARACS_Deleted) != 0; }
IsItLink_ParentNArchive::NUdf::CFileId474*f6dc9357SAndroid Build Coastguard Worker   bool IsItLink_Parent () const { return (FileCharacteristics & FILEID_CHARACS_Parent)  != 0; }
475*f6dc9357SAndroid Build Coastguard Worker 
476*f6dc9357SAndroid Build Coastguard Worker   size_t Parse(const Byte *p, size_t size);
477*f6dc9357SAndroid Build Coastguard Worker };
478*f6dc9357SAndroid Build Coastguard Worker 
Parse(const Byte * p,size_t size)479*f6dc9357SAndroid Build Coastguard Worker size_t CFileId::Parse(const Byte *p, size_t size)
480*f6dc9357SAndroid Build Coastguard Worker {
481*f6dc9357SAndroid Build Coastguard Worker   size_t processed = 0;
482*f6dc9357SAndroid Build Coastguard Worker   if (size < 38)
483*f6dc9357SAndroid Build Coastguard Worker     return 0;
484*f6dc9357SAndroid Build Coastguard Worker   CTag tag;
485*f6dc9357SAndroid Build Coastguard Worker   if (tag.Parse(p, size) != S_OK)
486*f6dc9357SAndroid Build Coastguard Worker     return 0;
487*f6dc9357SAndroid Build Coastguard Worker   if (tag.Id != DESC_TYPE_FileId)
488*f6dc9357SAndroid Build Coastguard Worker     return 0;
489*f6dc9357SAndroid Build Coastguard Worker   // FileVersion = Get16(p + 16);
490*f6dc9357SAndroid Build Coastguard Worker   // UDF: There shall be only one version of a file as specified below with the value being set to 1.
491*f6dc9357SAndroid Build Coastguard Worker 
492*f6dc9357SAndroid Build Coastguard Worker   FileCharacteristics = p[18];
493*f6dc9357SAndroid Build Coastguard Worker   const unsigned idLen = p[19];
494*f6dc9357SAndroid Build Coastguard Worker   Icb.Parse(p + 20);
495*f6dc9357SAndroid Build Coastguard Worker   const unsigned impLen = Get16(p + 36);
496*f6dc9357SAndroid Build Coastguard Worker   if (size < 38 + idLen + impLen)
497*f6dc9357SAndroid Build Coastguard Worker     return 0;
498*f6dc9357SAndroid Build Coastguard Worker   processed = 38;
499*f6dc9357SAndroid Build Coastguard Worker   // ImplUse.CopyFrom(p + processed, impLen);
500*f6dc9357SAndroid Build Coastguard Worker   processed += impLen;
501*f6dc9357SAndroid Build Coastguard Worker   Id.Parse(p + processed, idLen);
502*f6dc9357SAndroid Build Coastguard Worker   processed += idLen;
503*f6dc9357SAndroid Build Coastguard Worker   for (;(processed & 3) != 0; processed++)
504*f6dc9357SAndroid Build Coastguard Worker     if (p[processed] != 0)
505*f6dc9357SAndroid Build Coastguard Worker       return 0;
506*f6dc9357SAndroid Build Coastguard Worker   if ((size_t)tag.CrcLen + 16 != processed) return 0;
507*f6dc9357SAndroid Build Coastguard Worker   return (processed <= size) ? processed : 0;
508*f6dc9357SAndroid Build Coastguard Worker }
509*f6dc9357SAndroid Build Coastguard Worker 
510*f6dc9357SAndroid Build Coastguard Worker 
511*f6dc9357SAndroid Build Coastguard Worker 
ReadFileItem(unsigned volIndex,unsigned fsIndex,const CLongAllocDesc & lad,bool isDir,int numRecurseAllowed)512*f6dc9357SAndroid Build Coastguard Worker HRESULT CInArchive::ReadFileItem(unsigned volIndex, unsigned fsIndex, const CLongAllocDesc &lad, bool isDir, int numRecurseAllowed)
513*f6dc9357SAndroid Build Coastguard Worker {
514*f6dc9357SAndroid Build Coastguard Worker   if (Files.Size() % 100 == 0)
515*f6dc9357SAndroid Build Coastguard Worker     RINOK(_progress->SetCompleted(Files.Size(), _processedProgressBytes))
516*f6dc9357SAndroid Build Coastguard Worker   if (numRecurseAllowed-- == 0)
517*f6dc9357SAndroid Build Coastguard Worker     return S_FALSE;
518*f6dc9357SAndroid Build Coastguard Worker   CFile &file = Files.Back();
519*f6dc9357SAndroid Build Coastguard Worker   const CLogVol &vol = LogVols[volIndex];
520*f6dc9357SAndroid Build Coastguard Worker   const unsigned partitionRef = lad.Location.PartitionRef;
521*f6dc9357SAndroid Build Coastguard Worker   if (partitionRef >= vol.PartitionMaps.Size())
522*f6dc9357SAndroid Build Coastguard Worker     return S_FALSE;
523*f6dc9357SAndroid Build Coastguard Worker   CPartition &partition = Partitions[vol.PartitionMaps[partitionRef].PartitionIndex];
524*f6dc9357SAndroid Build Coastguard Worker 
525*f6dc9357SAndroid Build Coastguard Worker   const UInt32 key = lad.Location.Pos;
526*f6dc9357SAndroid Build Coastguard Worker   UInt32 value;
527*f6dc9357SAndroid Build Coastguard Worker   const UInt32 kRecursedErrorValue = (UInt32)(Int32)-1;
528*f6dc9357SAndroid Build Coastguard Worker   if (partition.Map.Find(key, value))
529*f6dc9357SAndroid Build Coastguard Worker   {
530*f6dc9357SAndroid Build Coastguard Worker     if (value == kRecursedErrorValue)
531*f6dc9357SAndroid Build Coastguard Worker       return S_FALSE;
532*f6dc9357SAndroid Build Coastguard Worker     file.ItemIndex = (int)(Int32)value;
533*f6dc9357SAndroid Build Coastguard Worker   }
534*f6dc9357SAndroid Build Coastguard Worker   else
535*f6dc9357SAndroid Build Coastguard Worker   {
536*f6dc9357SAndroid Build Coastguard Worker     value = Items.Size();
537*f6dc9357SAndroid Build Coastguard Worker     file.ItemIndex = (int)(Int32)value;
538*f6dc9357SAndroid Build Coastguard Worker     if (partition.Map.Set(key, kRecursedErrorValue))
539*f6dc9357SAndroid Build Coastguard Worker       return S_FALSE;
540*f6dc9357SAndroid Build Coastguard Worker     RINOK(ReadItem(volIndex, (int)fsIndex, lad, isDir, numRecurseAllowed))
541*f6dc9357SAndroid Build Coastguard Worker     if (!partition.Map.Set(key, value))
542*f6dc9357SAndroid Build Coastguard Worker       return S_FALSE;
543*f6dc9357SAndroid Build Coastguard Worker   }
544*f6dc9357SAndroid Build Coastguard Worker   return S_OK;
545*f6dc9357SAndroid Build Coastguard Worker }
546*f6dc9357SAndroid Build Coastguard Worker 
547*f6dc9357SAndroid Build Coastguard Worker 
548*f6dc9357SAndroid Build Coastguard Worker // (fsIndex = -1) means that it's metadata file
549*f6dc9357SAndroid Build Coastguard Worker 
ReadItem(unsigned volIndex,int fsIndex,const CLongAllocDesc & lad,bool isDir,int numRecurseAllowed)550*f6dc9357SAndroid Build Coastguard Worker HRESULT CInArchive::ReadItem(unsigned volIndex, int fsIndex, const CLongAllocDesc &lad, bool isDir, int numRecurseAllowed)
551*f6dc9357SAndroid Build Coastguard Worker {
552*f6dc9357SAndroid Build Coastguard Worker   if (Items.Size() >= kNumItemsMax)
553*f6dc9357SAndroid Build Coastguard Worker     return S_FALSE;
554*f6dc9357SAndroid Build Coastguard Worker   CItem &item = Items.AddNew();
555*f6dc9357SAndroid Build Coastguard Worker 
556*f6dc9357SAndroid Build Coastguard Worker   const CLogVol &vol = LogVols[volIndex];
557*f6dc9357SAndroid Build Coastguard Worker 
558*f6dc9357SAndroid Build Coastguard Worker   const size_t size = lad.GetLen();
559*f6dc9357SAndroid Build Coastguard Worker   if (size != vol.BlockSize)
560*f6dc9357SAndroid Build Coastguard Worker     return S_FALSE;
561*f6dc9357SAndroid Build Coastguard Worker 
562*f6dc9357SAndroid Build Coastguard Worker   CByteBuffer buf(size);
563*f6dc9357SAndroid Build Coastguard Worker   RINOK(ReadLad(volIndex, lad, buf))
564*f6dc9357SAndroid Build Coastguard Worker 
565*f6dc9357SAndroid Build Coastguard Worker   CTag tag;
566*f6dc9357SAndroid Build Coastguard Worker   const Byte *p = buf;
567*f6dc9357SAndroid Build Coastguard Worker   RINOK(tag.Parse(p, size))
568*f6dc9357SAndroid Build Coastguard Worker 
569*f6dc9357SAndroid Build Coastguard Worker   item.IsExtended = (tag.Id == DESC_TYPE_ExtendedFile);
570*f6dc9357SAndroid Build Coastguard Worker   const size_t kExtendOffset = item.IsExtended ? 40 : 0;
571*f6dc9357SAndroid Build Coastguard Worker 
572*f6dc9357SAndroid Build Coastguard Worker   if (size < kExtendOffset + 176)
573*f6dc9357SAndroid Build Coastguard Worker     return S_FALSE;
574*f6dc9357SAndroid Build Coastguard Worker   if (tag.Id != DESC_TYPE_File &&
575*f6dc9357SAndroid Build Coastguard Worker       tag.Id != DESC_TYPE_ExtendedFile)
576*f6dc9357SAndroid Build Coastguard Worker     return S_FALSE;
577*f6dc9357SAndroid Build Coastguard Worker 
578*f6dc9357SAndroid Build Coastguard Worker   item.IcbTag.Parse(p + 16);
579*f6dc9357SAndroid Build Coastguard Worker 
580*f6dc9357SAndroid Build Coastguard Worker   if (fsIndex < 0)
581*f6dc9357SAndroid Build Coastguard Worker   {
582*f6dc9357SAndroid Build Coastguard Worker     if (item.IcbTag.FileType != ICB_FILE_TYPE_METADATA &&
583*f6dc9357SAndroid Build Coastguard Worker         item.IcbTag.FileType != ICB_FILE_TYPE_METADATA_MIRROR)
584*f6dc9357SAndroid Build Coastguard Worker       return S_FALSE;
585*f6dc9357SAndroid Build Coastguard Worker   }
586*f6dc9357SAndroid Build Coastguard Worker   else if (
587*f6dc9357SAndroid Build Coastguard Worker       item.IcbTag.FileType != ICB_FILE_TYPE_DIR &&
588*f6dc9357SAndroid Build Coastguard Worker       item.IcbTag.FileType != ICB_FILE_TYPE_FILE)
589*f6dc9357SAndroid Build Coastguard Worker     return S_FALSE;
590*f6dc9357SAndroid Build Coastguard Worker 
591*f6dc9357SAndroid Build Coastguard Worker   item.Parse(p);
592*f6dc9357SAndroid Build Coastguard Worker 
593*f6dc9357SAndroid Build Coastguard Worker   _processedProgressBytes += (UInt64)item.NumLogBlockRecorded * vol.BlockSize + size;
594*f6dc9357SAndroid Build Coastguard Worker 
595*f6dc9357SAndroid Build Coastguard Worker   const UInt32 extendedAttrLen = Get32(p + 168 + kExtendOffset);
596*f6dc9357SAndroid Build Coastguard Worker   const UInt32 allocDescriptorsLen = Get32(p + 172 + kExtendOffset);
597*f6dc9357SAndroid Build Coastguard Worker 
598*f6dc9357SAndroid Build Coastguard Worker   if ((extendedAttrLen & 3) != 0)
599*f6dc9357SAndroid Build Coastguard Worker     return S_FALSE;
600*f6dc9357SAndroid Build Coastguard Worker   size_t pos = 176 + kExtendOffset;
601*f6dc9357SAndroid Build Coastguard Worker   if (extendedAttrLen > size - pos)
602*f6dc9357SAndroid Build Coastguard Worker     return S_FALSE;
603*f6dc9357SAndroid Build Coastguard Worker   /*
604*f6dc9357SAndroid Build Coastguard Worker   if (extendedAttrLen != 16)
605*f6dc9357SAndroid Build Coastguard Worker   {
606*f6dc9357SAndroid Build Coastguard Worker     if (extendedAttrLen < 24)
607*f6dc9357SAndroid Build Coastguard Worker       return S_FALSE;
608*f6dc9357SAndroid Build Coastguard Worker     CTag attrTag;
609*f6dc9357SAndroid Build Coastguard Worker     RINOK(attrTag.Parse(p + pos, size));
610*f6dc9357SAndroid Build Coastguard Worker     if (attrTag.Id != DESC_TYPE_ExtendedAttrHeader)
611*f6dc9357SAndroid Build Coastguard Worker       return S_FALSE;
612*f6dc9357SAndroid Build Coastguard Worker     // UInt32 implAttrLocation = Get32(p + pos + 16);
613*f6dc9357SAndroid Build Coastguard Worker     // UInt32 applicationlAttrLocation = Get32(p + pos + 20);
614*f6dc9357SAndroid Build Coastguard Worker   }
615*f6dc9357SAndroid Build Coastguard Worker   */
616*f6dc9357SAndroid Build Coastguard Worker   pos += extendedAttrLen;
617*f6dc9357SAndroid Build Coastguard Worker 
618*f6dc9357SAndroid Build Coastguard Worker   const int descType = item.IcbTag.GetDescriptorType();
619*f6dc9357SAndroid Build Coastguard Worker   if (allocDescriptorsLen > size - pos)
620*f6dc9357SAndroid Build Coastguard Worker     return S_FALSE;
621*f6dc9357SAndroid Build Coastguard Worker   if (descType == ICB_DESC_TYPE_INLINE)
622*f6dc9357SAndroid Build Coastguard Worker   {
623*f6dc9357SAndroid Build Coastguard Worker     item.IsInline = true;
624*f6dc9357SAndroid Build Coastguard Worker     item.InlineData.CopyFrom(p + pos, allocDescriptorsLen);
625*f6dc9357SAndroid Build Coastguard Worker   }
626*f6dc9357SAndroid Build Coastguard Worker   else
627*f6dc9357SAndroid Build Coastguard Worker   {
628*f6dc9357SAndroid Build Coastguard Worker     item.IsInline = false;
629*f6dc9357SAndroid Build Coastguard Worker     if (descType != ICB_DESC_TYPE_SHORT && descType != ICB_DESC_TYPE_LONG)
630*f6dc9357SAndroid Build Coastguard Worker       return S_FALSE;
631*f6dc9357SAndroid Build Coastguard Worker     for (UInt32 i = 0; i < allocDescriptorsLen;)
632*f6dc9357SAndroid Build Coastguard Worker     {
633*f6dc9357SAndroid Build Coastguard Worker       CMyExtent e;
634*f6dc9357SAndroid Build Coastguard Worker       if (descType == ICB_DESC_TYPE_SHORT)
635*f6dc9357SAndroid Build Coastguard Worker       {
636*f6dc9357SAndroid Build Coastguard Worker         if (i + 8 > allocDescriptorsLen)
637*f6dc9357SAndroid Build Coastguard Worker           return S_FALSE;
638*f6dc9357SAndroid Build Coastguard Worker         CShortAllocDesc sad;
639*f6dc9357SAndroid Build Coastguard Worker         sad.Parse(p + pos + i);
640*f6dc9357SAndroid Build Coastguard Worker         e.Pos = sad.Pos;
641*f6dc9357SAndroid Build Coastguard Worker         e.Len = sad.Len;
642*f6dc9357SAndroid Build Coastguard Worker         e.PartitionRef = lad.Location.PartitionRef;
643*f6dc9357SAndroid Build Coastguard Worker         i += 8;
644*f6dc9357SAndroid Build Coastguard Worker       }
645*f6dc9357SAndroid Build Coastguard Worker       else
646*f6dc9357SAndroid Build Coastguard Worker       {
647*f6dc9357SAndroid Build Coastguard Worker         if (i + 16 > allocDescriptorsLen)
648*f6dc9357SAndroid Build Coastguard Worker           return S_FALSE;
649*f6dc9357SAndroid Build Coastguard Worker         CLongAllocDesc ladNew;
650*f6dc9357SAndroid Build Coastguard Worker         ladNew.Parse(p + pos + i);
651*f6dc9357SAndroid Build Coastguard Worker         e.Pos = ladNew.Location.Pos;
652*f6dc9357SAndroid Build Coastguard Worker         e.PartitionRef = ladNew.Location.PartitionRef;
653*f6dc9357SAndroid Build Coastguard Worker         e.Len = ladNew.Len;
654*f6dc9357SAndroid Build Coastguard Worker         i += 16;
655*f6dc9357SAndroid Build Coastguard Worker       }
656*f6dc9357SAndroid Build Coastguard Worker       item.Extents.Add(e);
657*f6dc9357SAndroid Build Coastguard Worker     }
658*f6dc9357SAndroid Build Coastguard Worker   }
659*f6dc9357SAndroid Build Coastguard Worker 
660*f6dc9357SAndroid Build Coastguard Worker   if (isDir != item.IcbTag.IsDir())
661*f6dc9357SAndroid Build Coastguard Worker     return S_FALSE;
662*f6dc9357SAndroid Build Coastguard Worker 
663*f6dc9357SAndroid Build Coastguard Worker   if (item.IcbTag.IsDir())
664*f6dc9357SAndroid Build Coastguard Worker   {
665*f6dc9357SAndroid Build Coastguard Worker     if (fsIndex < 0)
666*f6dc9357SAndroid Build Coastguard Worker       return S_FALSE;
667*f6dc9357SAndroid Build Coastguard Worker 
668*f6dc9357SAndroid Build Coastguard Worker     if (!item.CheckChunkSizes() || !CheckItemExtents(volIndex, item))
669*f6dc9357SAndroid Build Coastguard Worker       return S_FALSE;
670*f6dc9357SAndroid Build Coastguard Worker     CByteBuffer buf2;
671*f6dc9357SAndroid Build Coastguard Worker     RINOK(ReadFromFile(volIndex, item, buf2))
672*f6dc9357SAndroid Build Coastguard Worker     item.Size = 0;
673*f6dc9357SAndroid Build Coastguard Worker     item.Extents.ClearAndFree();
674*f6dc9357SAndroid Build Coastguard Worker     item.InlineData.Free();
675*f6dc9357SAndroid Build Coastguard Worker 
676*f6dc9357SAndroid Build Coastguard Worker     const Byte *p2 = buf2;
677*f6dc9357SAndroid Build Coastguard Worker     size_t size2 = buf2.Size();
678*f6dc9357SAndroid Build Coastguard Worker     while (size2 != 0)
679*f6dc9357SAndroid Build Coastguard Worker     {
680*f6dc9357SAndroid Build Coastguard Worker       CFileId fileId;
681*f6dc9357SAndroid Build Coastguard Worker       {
682*f6dc9357SAndroid Build Coastguard Worker         const size_t cur = fileId.Parse(p2, size2);
683*f6dc9357SAndroid Build Coastguard Worker         if (cur == 0)
684*f6dc9357SAndroid Build Coastguard Worker           return S_FALSE;
685*f6dc9357SAndroid Build Coastguard Worker         p2 += cur;
686*f6dc9357SAndroid Build Coastguard Worker         size2 -= cur;
687*f6dc9357SAndroid Build Coastguard Worker       }
688*f6dc9357SAndroid Build Coastguard Worker       if (fileId.IsItLink_Parent())
689*f6dc9357SAndroid Build Coastguard Worker         continue;
690*f6dc9357SAndroid Build Coastguard Worker       if (fileId.IsItLink_Deleted())
691*f6dc9357SAndroid Build Coastguard Worker         continue;
692*f6dc9357SAndroid Build Coastguard Worker       {
693*f6dc9357SAndroid Build Coastguard Worker         CFile file;
694*f6dc9357SAndroid Build Coastguard Worker         // file.FileVersion = fileId.FileVersion;
695*f6dc9357SAndroid Build Coastguard Worker         // file.FileCharacteristics = fileId.FileCharacteristics;
696*f6dc9357SAndroid Build Coastguard Worker         // file.ImplUse = fileId.ImplUse;
697*f6dc9357SAndroid Build Coastguard Worker         file.Id = fileId.Id;
698*f6dc9357SAndroid Build Coastguard Worker 
699*f6dc9357SAndroid Build Coastguard Worker         _fileNameLengthTotal += file.Id.Data.Size();
700*f6dc9357SAndroid Build Coastguard Worker         if (_fileNameLengthTotal > kFileNameLengthTotalMax)
701*f6dc9357SAndroid Build Coastguard Worker           return S_FALSE;
702*f6dc9357SAndroid Build Coastguard Worker 
703*f6dc9357SAndroid Build Coastguard Worker         item.SubFiles.Add(Files.Size());
704*f6dc9357SAndroid Build Coastguard Worker         if (Files.Size() >= kNumFilesMax)
705*f6dc9357SAndroid Build Coastguard Worker           return S_FALSE;
706*f6dc9357SAndroid Build Coastguard Worker         Files.Add(file);
707*f6dc9357SAndroid Build Coastguard Worker         RINOK(ReadFileItem(volIndex, (unsigned)fsIndex, fileId.Icb,
708*f6dc9357SAndroid Build Coastguard Worker             fileId.IsItLink_Dir(), numRecurseAllowed))
709*f6dc9357SAndroid Build Coastguard Worker       }
710*f6dc9357SAndroid Build Coastguard Worker     }
711*f6dc9357SAndroid Build Coastguard Worker   }
712*f6dc9357SAndroid Build Coastguard Worker   else
713*f6dc9357SAndroid Build Coastguard Worker   {
714*f6dc9357SAndroid Build Coastguard Worker     if ((UInt32)item.Extents.Size() > kNumExtentsMax - _numExtents)
715*f6dc9357SAndroid Build Coastguard Worker       return S_FALSE;
716*f6dc9357SAndroid Build Coastguard Worker     _numExtents += item.Extents.Size();
717*f6dc9357SAndroid Build Coastguard Worker 
718*f6dc9357SAndroid Build Coastguard Worker     if (item.InlineData.Size() > kInlineExtentsSizeMax - _inlineExtentsSize)
719*f6dc9357SAndroid Build Coastguard Worker       return S_FALSE;
720*f6dc9357SAndroid Build Coastguard Worker     _inlineExtentsSize += item.InlineData.Size();
721*f6dc9357SAndroid Build Coastguard Worker   }
722*f6dc9357SAndroid Build Coastguard Worker 
723*f6dc9357SAndroid Build Coastguard Worker   return S_OK;
724*f6dc9357SAndroid Build Coastguard Worker }
725*f6dc9357SAndroid Build Coastguard Worker 
726*f6dc9357SAndroid Build Coastguard Worker 
FillRefs(CFileSet & fs,unsigned fileIndex,int parent,int numRecurseAllowed)727*f6dc9357SAndroid Build Coastguard Worker HRESULT CInArchive::FillRefs(CFileSet &fs, unsigned fileIndex, int parent, int numRecurseAllowed)
728*f6dc9357SAndroid Build Coastguard Worker {
729*f6dc9357SAndroid Build Coastguard Worker   if ((_numRefs & 0xFFF) == 0)
730*f6dc9357SAndroid Build Coastguard Worker   {
731*f6dc9357SAndroid Build Coastguard Worker     RINOK(_progress->SetCompleted())
732*f6dc9357SAndroid Build Coastguard Worker   }
733*f6dc9357SAndroid Build Coastguard Worker   if (numRecurseAllowed-- == 0)
734*f6dc9357SAndroid Build Coastguard Worker     return S_FALSE;
735*f6dc9357SAndroid Build Coastguard Worker   if (_numRefs >= kNumRefsMax)
736*f6dc9357SAndroid Build Coastguard Worker     return S_FALSE;
737*f6dc9357SAndroid Build Coastguard Worker   _numRefs++;
738*f6dc9357SAndroid Build Coastguard Worker   CRef ref;
739*f6dc9357SAndroid Build Coastguard Worker   ref.FileIndex = fileIndex;
740*f6dc9357SAndroid Build Coastguard Worker   ref.Parent = parent;
741*f6dc9357SAndroid Build Coastguard Worker   parent = (int)fs.Refs.Size();
742*f6dc9357SAndroid Build Coastguard Worker   fs.Refs.Add(ref);
743*f6dc9357SAndroid Build Coastguard Worker   const CItem &item = Items[Files[fileIndex].ItemIndex];
744*f6dc9357SAndroid Build Coastguard Worker   FOR_VECTOR (i, item.SubFiles)
745*f6dc9357SAndroid Build Coastguard Worker   {
746*f6dc9357SAndroid Build Coastguard Worker     RINOK(FillRefs(fs, item.SubFiles[i], parent, numRecurseAllowed))
747*f6dc9357SAndroid Build Coastguard Worker   }
748*f6dc9357SAndroid Build Coastguard Worker   return S_OK;
749*f6dc9357SAndroid Build Coastguard Worker }
750*f6dc9357SAndroid Build Coastguard Worker 
751*f6dc9357SAndroid Build Coastguard Worker 
IsArc_Udf(const Byte * p,size_t size)752*f6dc9357SAndroid Build Coastguard Worker API_FUNC_IsArc IsArc_Udf(const Byte *p, size_t size)
753*f6dc9357SAndroid Build Coastguard Worker {
754*f6dc9357SAndroid Build Coastguard Worker   UInt32 res = k_IsArc_Res_NO;
755*f6dc9357SAndroid Build Coastguard Worker   unsigned SecLogSize;
756*f6dc9357SAndroid Build Coastguard Worker   for (SecLogSize = 11;; SecLogSize -= 2)
757*f6dc9357SAndroid Build Coastguard Worker   {
758*f6dc9357SAndroid Build Coastguard Worker     if (SecLogSize < 9)
759*f6dc9357SAndroid Build Coastguard Worker       return res;
760*f6dc9357SAndroid Build Coastguard Worker     const UInt32 offset = (UInt32)256 << SecLogSize;
761*f6dc9357SAndroid Build Coastguard Worker     const UInt32 bufSize = (UInt32)1 << SecLogSize;
762*f6dc9357SAndroid Build Coastguard Worker     if (offset + bufSize > size)
763*f6dc9357SAndroid Build Coastguard Worker       res = k_IsArc_Res_NEED_MORE;
764*f6dc9357SAndroid Build Coastguard Worker     else
765*f6dc9357SAndroid Build Coastguard Worker     {
766*f6dc9357SAndroid Build Coastguard Worker       CTag tag;
767*f6dc9357SAndroid Build Coastguard Worker       if (tag.Parse(p + offset, bufSize) == S_OK)
768*f6dc9357SAndroid Build Coastguard Worker         if (tag.Id == DESC_TYPE_AnchorVolPtr)
769*f6dc9357SAndroid Build Coastguard Worker         {
770*f6dc9357SAndroid Build Coastguard Worker           if (Get32(p + offset + 12) == 256 &&  // TagLocation
771*f6dc9357SAndroid Build Coastguard Worker               tag.CrcLen >= 16)
772*f6dc9357SAndroid Build Coastguard Worker             return k_IsArc_Res_YES;
773*f6dc9357SAndroid Build Coastguard Worker         }
774*f6dc9357SAndroid Build Coastguard Worker     }
775*f6dc9357SAndroid Build Coastguard Worker   }
776*f6dc9357SAndroid Build Coastguard Worker }
777*f6dc9357SAndroid Build Coastguard Worker 
778*f6dc9357SAndroid Build Coastguard Worker 
Open2()779*f6dc9357SAndroid Build Coastguard Worker HRESULT CInArchive::Open2()
780*f6dc9357SAndroid Build Coastguard Worker {
781*f6dc9357SAndroid Build Coastguard Worker   Clear();
782*f6dc9357SAndroid Build Coastguard Worker   UInt64 fileSize;
783*f6dc9357SAndroid Build Coastguard Worker   RINOK(InStream_GetSize_SeekToEnd(_stream, fileSize))
784*f6dc9357SAndroid Build Coastguard Worker   FileSize = fileSize;
785*f6dc9357SAndroid Build Coastguard Worker 
786*f6dc9357SAndroid Build Coastguard Worker   // Some UDFs contain additional pad zeros (2 KB).
787*f6dc9357SAndroid Build Coastguard Worker   // Seek to STREAM_SEEK_END for direct DVD reading can return 8 KB more, so we check last 16 KB.
788*f6dc9357SAndroid Build Coastguard Worker   // And when we read last block, result read size can be smaller than required size.
789*f6dc9357SAndroid Build Coastguard Worker 
790*f6dc9357SAndroid Build Coastguard Worker   /*
791*f6dc9357SAndroid Build Coastguard Worker   const size_t kBufSize = 1 << 14;
792*f6dc9357SAndroid Build Coastguard Worker   Byte buf[kBufSize];
793*f6dc9357SAndroid Build Coastguard Worker   size_t readSize = (fileSize < kBufSize) ? (size_t)fileSize : kBufSize;
794*f6dc9357SAndroid Build Coastguard Worker   RINOK(InStream_SeekSet(_stream, fileSize - readSize))
795*f6dc9357SAndroid Build Coastguard Worker   RINOK(ReadStream(_stream, buf, &readSize));
796*f6dc9357SAndroid Build Coastguard Worker   size_t i = readSize;
797*f6dc9357SAndroid Build Coastguard Worker   for (;;)
798*f6dc9357SAndroid Build Coastguard Worker   {
799*f6dc9357SAndroid Build Coastguard Worker     const size_t kSecSizeMin = 1 << 8;
800*f6dc9357SAndroid Build Coastguard Worker     if (i < kSecSizeMin)
801*f6dc9357SAndroid Build Coastguard Worker       return S_FALSE;
802*f6dc9357SAndroid Build Coastguard Worker     i -= kSecSizeMin;
803*f6dc9357SAndroid Build Coastguard Worker     SecLogSize = (readSize - i < ((size_t)1 << 11)) ? 8 : 11;
804*f6dc9357SAndroid Build Coastguard Worker     CTag tag;
805*f6dc9357SAndroid Build Coastguard Worker     if (tag.Parse(buf + i, (1 << SecLogSize)) == S_OK)
806*f6dc9357SAndroid Build Coastguard Worker       if (tag.Id == DESC_TYPE_AnchorVolPtr)
807*f6dc9357SAndroid Build Coastguard Worker         break;
808*f6dc9357SAndroid Build Coastguard Worker   }
809*f6dc9357SAndroid Build Coastguard Worker   PhySize = fileSize;
810*f6dc9357SAndroid Build Coastguard Worker   CExtent extentVDS;
811*f6dc9357SAndroid Build Coastguard Worker   extentVDS.Parse(buf + i + 16);
812*f6dc9357SAndroid Build Coastguard Worker   */
813*f6dc9357SAndroid Build Coastguard Worker 
814*f6dc9357SAndroid Build Coastguard Worker   /*
815*f6dc9357SAndroid Build Coastguard Worker   An Anchor Volume Descriptor Pointer structure shall be recorded in at
816*f6dc9357SAndroid Build Coastguard Worker   least 2 of the following 3 locations on the media:
817*f6dc9357SAndroid Build Coastguard Worker       Logical Sector 256.
818*f6dc9357SAndroid Build Coastguard Worker       Logical Sector (N - 256).
819*f6dc9357SAndroid Build Coastguard Worker       N
820*f6dc9357SAndroid Build Coastguard Worker   */
821*f6dc9357SAndroid Build Coastguard Worker 
822*f6dc9357SAndroid Build Coastguard Worker   const size_t kBufSize = 1 << 11;
823*f6dc9357SAndroid Build Coastguard Worker   Byte buf[kBufSize];
824*f6dc9357SAndroid Build Coastguard Worker 
825*f6dc9357SAndroid Build Coastguard Worker   for (SecLogSize = 11;; SecLogSize -= 2)
826*f6dc9357SAndroid Build Coastguard Worker   {
827*f6dc9357SAndroid Build Coastguard Worker     // Windows 10 uses unusual (SecLogSize = 9)
828*f6dc9357SAndroid Build Coastguard Worker     if (SecLogSize < 9)
829*f6dc9357SAndroid Build Coastguard Worker       return S_FALSE;
830*f6dc9357SAndroid Build Coastguard Worker     const UInt32 offset = (UInt32)256 << SecLogSize;
831*f6dc9357SAndroid Build Coastguard Worker     if (offset >= fileSize)
832*f6dc9357SAndroid Build Coastguard Worker       continue;
833*f6dc9357SAndroid Build Coastguard Worker     RINOK(InStream_SeekSet(_stream, offset))
834*f6dc9357SAndroid Build Coastguard Worker     const size_t bufSize = (size_t)1 << SecLogSize;
835*f6dc9357SAndroid Build Coastguard Worker     size_t readSize = bufSize;
836*f6dc9357SAndroid Build Coastguard Worker     RINOK(ReadStream(_stream, buf, &readSize))
837*f6dc9357SAndroid Build Coastguard Worker     if (readSize == bufSize)
838*f6dc9357SAndroid Build Coastguard Worker     {
839*f6dc9357SAndroid Build Coastguard Worker       CTag tag;
840*f6dc9357SAndroid Build Coastguard Worker       if (tag.Parse(buf, readSize) == S_OK)
841*f6dc9357SAndroid Build Coastguard Worker         if (tag.Id == DESC_TYPE_AnchorVolPtr)
842*f6dc9357SAndroid Build Coastguard Worker         {
843*f6dc9357SAndroid Build Coastguard Worker           if (Get32(buf + 12) == 256 &&
844*f6dc9357SAndroid Build Coastguard Worker             tag.CrcLen >= 16) // TagLocation
845*f6dc9357SAndroid Build Coastguard Worker             break;
846*f6dc9357SAndroid Build Coastguard Worker         }
847*f6dc9357SAndroid Build Coastguard Worker     }
848*f6dc9357SAndroid Build Coastguard Worker   }
849*f6dc9357SAndroid Build Coastguard Worker 
850*f6dc9357SAndroid Build Coastguard Worker   PhySize = (UInt32)(256 + 1) << SecLogSize;
851*f6dc9357SAndroid Build Coastguard Worker   IsArc = true;
852*f6dc9357SAndroid Build Coastguard Worker 
853*f6dc9357SAndroid Build Coastguard Worker   // UDF 2.2.3  AnchorVolumeDescriptorPointer
854*f6dc9357SAndroid Build Coastguard Worker 
855*f6dc9357SAndroid Build Coastguard Worker   CExtent extentVDS;
856*f6dc9357SAndroid Build Coastguard Worker   extentVDS.Parse(buf + 16);
857*f6dc9357SAndroid Build Coastguard Worker   {
858*f6dc9357SAndroid Build Coastguard Worker     CExtent extentVDS2;
859*f6dc9357SAndroid Build Coastguard Worker     extentVDS2.Parse(buf + 24);
860*f6dc9357SAndroid Build Coastguard Worker     UpdatePhySize(extentVDS);
861*f6dc9357SAndroid Build Coastguard Worker     UpdatePhySize(extentVDS2);
862*f6dc9357SAndroid Build Coastguard Worker   }
863*f6dc9357SAndroid Build Coastguard Worker 
864*f6dc9357SAndroid Build Coastguard Worker   for (UInt32 location = 0; ; location++)
865*f6dc9357SAndroid Build Coastguard Worker   {
866*f6dc9357SAndroid Build Coastguard Worker     if (location >= (extentVDS.Len >> SecLogSize))
867*f6dc9357SAndroid Build Coastguard Worker       return S_FALSE;
868*f6dc9357SAndroid Build Coastguard Worker 
869*f6dc9357SAndroid Build Coastguard Worker     const size_t bufSize = (size_t)1 << SecLogSize;
870*f6dc9357SAndroid Build Coastguard Worker     {
871*f6dc9357SAndroid Build Coastguard Worker       const UInt64 offs = ((UInt64)extentVDS.Pos + location) << SecLogSize;
872*f6dc9357SAndroid Build Coastguard Worker       RINOK(InStream_SeekSet(_stream, offs))
873*f6dc9357SAndroid Build Coastguard Worker       const HRESULT res = ReadStream_FALSE(_stream, buf, bufSize);
874*f6dc9357SAndroid Build Coastguard Worker       if (res == S_FALSE && offs + bufSize > FileSize)
875*f6dc9357SAndroid Build Coastguard Worker         UnexpectedEnd = true;
876*f6dc9357SAndroid Build Coastguard Worker       RINOK(res)
877*f6dc9357SAndroid Build Coastguard Worker     }
878*f6dc9357SAndroid Build Coastguard Worker 
879*f6dc9357SAndroid Build Coastguard Worker     CTag tag;
880*f6dc9357SAndroid Build Coastguard Worker     RINOK(tag.Parse(buf, bufSize))
881*f6dc9357SAndroid Build Coastguard Worker 
882*f6dc9357SAndroid Build Coastguard Worker     if (tag.Id == DESC_TYPE_Terminating)
883*f6dc9357SAndroid Build Coastguard Worker       break;
884*f6dc9357SAndroid Build Coastguard Worker 
885*f6dc9357SAndroid Build Coastguard Worker     if (tag.Id == DESC_TYPE_PrimVol)
886*f6dc9357SAndroid Build Coastguard Worker     {
887*f6dc9357SAndroid Build Coastguard Worker       CPrimeVol &pm = PrimeVols.AddNew();
888*f6dc9357SAndroid Build Coastguard Worker       pm.Parse(buf);
889*f6dc9357SAndroid Build Coastguard Worker       continue;
890*f6dc9357SAndroid Build Coastguard Worker     }
891*f6dc9357SAndroid Build Coastguard Worker 
892*f6dc9357SAndroid Build Coastguard Worker     if (tag.Id == DESC_TYPE_Partition)
893*f6dc9357SAndroid Build Coastguard Worker     {
894*f6dc9357SAndroid Build Coastguard Worker       // Partition Descriptor
895*f6dc9357SAndroid Build Coastguard Worker       // ECMA 3/10.5
896*f6dc9357SAndroid Build Coastguard Worker       // UDF 2.2.14
897*f6dc9357SAndroid Build Coastguard Worker       if (Partitions.Size() >= kNumPartitionsMax)
898*f6dc9357SAndroid Build Coastguard Worker         return S_FALSE;
899*f6dc9357SAndroid Build Coastguard Worker       CPartition partition;
900*f6dc9357SAndroid Build Coastguard Worker       // const UInt32 volDescSeqNumer = Get32(buf + 16);
901*f6dc9357SAndroid Build Coastguard Worker       partition.Flags = Get16(buf + 20);
902*f6dc9357SAndroid Build Coastguard Worker       partition.Number = Get16(buf + 22);
903*f6dc9357SAndroid Build Coastguard Worker       partition.ContentsId.Parse(buf + 24);
904*f6dc9357SAndroid Build Coastguard Worker 
905*f6dc9357SAndroid Build Coastguard Worker       // memcpy(partition.ContentsUse, buf + 56, sizeof(partition.ContentsUse));
906*f6dc9357SAndroid Build Coastguard Worker       // ContentsUse contains Partition Header Description.
907*f6dc9357SAndroid Build Coastguard Worker       // ECMA 4/14.3
908*f6dc9357SAndroid Build Coastguard Worker       // UDF PartitionHeaderDescriptor 2.3.3
909*f6dc9357SAndroid Build Coastguard Worker 
910*f6dc9357SAndroid Build Coastguard Worker       partition.AccessType = Get32(buf + 184);
911*f6dc9357SAndroid Build Coastguard Worker       partition.Pos = Get32(buf + 188);
912*f6dc9357SAndroid Build Coastguard Worker       partition.Len = Get32(buf + 192);
913*f6dc9357SAndroid Build Coastguard Worker       partition.ImplId.Parse(buf + 196);
914*f6dc9357SAndroid Build Coastguard Worker       // memcpy(partition.ImplUse, buf + 228, sizeof(partition.ImplUse));
915*f6dc9357SAndroid Build Coastguard Worker 
916*f6dc9357SAndroid Build Coastguard Worker       PRF(printf("\nPartition number = %2d   pos = %d   len = %d", partition.Number, partition.Pos, partition.Len));
917*f6dc9357SAndroid Build Coastguard Worker       Partitions.Add(partition);
918*f6dc9357SAndroid Build Coastguard Worker       continue;
919*f6dc9357SAndroid Build Coastguard Worker     }
920*f6dc9357SAndroid Build Coastguard Worker 
921*f6dc9357SAndroid Build Coastguard Worker     if (tag.Id == DESC_TYPE_LogicalVol)
922*f6dc9357SAndroid Build Coastguard Worker     {
923*f6dc9357SAndroid Build Coastguard Worker       /* Logical Volume Descriptor
924*f6dc9357SAndroid Build Coastguard Worker           ECMA 3/10.6
925*f6dc9357SAndroid Build Coastguard Worker           UDF 2.60 2.2.4 */
926*f6dc9357SAndroid Build Coastguard Worker 
927*f6dc9357SAndroid Build Coastguard Worker       if (LogVols.Size() >= kNumLogVolumesMax)
928*f6dc9357SAndroid Build Coastguard Worker         return S_FALSE;
929*f6dc9357SAndroid Build Coastguard Worker       CLogVol &vol = LogVols.AddNew();
930*f6dc9357SAndroid Build Coastguard Worker 
931*f6dc9357SAndroid Build Coastguard Worker       vol.Id.Parse(buf + 84);
932*f6dc9357SAndroid Build Coastguard Worker       vol.BlockSize = Get32(buf + 212);
933*f6dc9357SAndroid Build Coastguard Worker       if (vol.BlockSize != ((UInt32)1 << SecLogSize))
934*f6dc9357SAndroid Build Coastguard Worker       {
935*f6dc9357SAndroid Build Coastguard Worker         // UDF 2.2.4.2 LogicalBlockSize
936*f6dc9357SAndroid Build Coastguard Worker         // UDF probably doesn't allow different sizes
937*f6dc9357SAndroid Build Coastguard Worker         return S_FALSE;
938*f6dc9357SAndroid Build Coastguard Worker       }
939*f6dc9357SAndroid Build Coastguard Worker       /*
940*f6dc9357SAndroid Build Coastguard Worker       if (vol.BlockSize < 512 || vol.BlockSize > ((UInt32)1 << 30))
941*f6dc9357SAndroid Build Coastguard Worker         return S_FALSE;
942*f6dc9357SAndroid Build Coastguard Worker       */
943*f6dc9357SAndroid Build Coastguard Worker 
944*f6dc9357SAndroid Build Coastguard Worker       vol.DomainId.Parse(buf + 216);
945*f6dc9357SAndroid Build Coastguard Worker 
946*f6dc9357SAndroid Build Coastguard Worker       // ECMA 4/3.1
947*f6dc9357SAndroid Build Coastguard Worker       // UDF 2.2.4.4 LogicalVolumeContentsUse
948*f6dc9357SAndroid Build Coastguard Worker       /* the extent in which the first File Set Descriptor Sequence
949*f6dc9357SAndroid Build Coastguard Worker          of the logical volume is recorded */
950*f6dc9357SAndroid Build Coastguard Worker       vol.FileSetLocation.Parse(buf + 248);
951*f6dc9357SAndroid Build Coastguard Worker       // memcpy(vol.ContentsUse, buf + 248, sizeof(vol.ContentsUse));
952*f6dc9357SAndroid Build Coastguard Worker 
953*f6dc9357SAndroid Build Coastguard Worker       vol.ImplId.Parse(buf + 272);
954*f6dc9357SAndroid Build Coastguard Worker       // memcpy(vol.ImplUse, buf + 304, sizeof(vol.ImplUse));
955*f6dc9357SAndroid Build Coastguard Worker       // vol.IntegritySequenceExtent.Parse(buf + 432);
956*f6dc9357SAndroid Build Coastguard Worker 
957*f6dc9357SAndroid Build Coastguard Worker       const UInt32 mapTableLen = Get32(buf + 264);
958*f6dc9357SAndroid Build Coastguard Worker       const UInt32 numPartitionMaps = Get32(buf + 268);
959*f6dc9357SAndroid Build Coastguard Worker       if (numPartitionMaps > kNumPartitionsMax)
960*f6dc9357SAndroid Build Coastguard Worker         return S_FALSE;
961*f6dc9357SAndroid Build Coastguard Worker 
962*f6dc9357SAndroid Build Coastguard Worker       PRF(printf("\nLogicalVol numPartitionMaps = %2d", numPartitionMaps));
963*f6dc9357SAndroid Build Coastguard Worker 
964*f6dc9357SAndroid Build Coastguard Worker       size_t pos = 440;
965*f6dc9357SAndroid Build Coastguard Worker       if (mapTableLen > bufSize - pos)
966*f6dc9357SAndroid Build Coastguard Worker         return S_FALSE;
967*f6dc9357SAndroid Build Coastguard Worker       const size_t posLimit = pos + mapTableLen;
968*f6dc9357SAndroid Build Coastguard Worker 
969*f6dc9357SAndroid Build Coastguard Worker       for (UInt32 i = 0; i < numPartitionMaps; i++)
970*f6dc9357SAndroid Build Coastguard Worker       {
971*f6dc9357SAndroid Build Coastguard Worker         // ECMA 3/10.7 Partition maps
972*f6dc9357SAndroid Build Coastguard Worker         if (pos + 2 > posLimit)
973*f6dc9357SAndroid Build Coastguard Worker           return S_FALSE;
974*f6dc9357SAndroid Build Coastguard Worker         CPartitionMap pm;
975*f6dc9357SAndroid Build Coastguard Worker         pm.Type = buf[pos + 0];
976*f6dc9357SAndroid Build Coastguard Worker         // pm.Length = buf[pos + 1];
977*f6dc9357SAndroid Build Coastguard Worker         const Byte len = buf[pos + 1];
978*f6dc9357SAndroid Build Coastguard Worker         if (pos + len > posLimit)
979*f6dc9357SAndroid Build Coastguard Worker           return S_FALSE;
980*f6dc9357SAndroid Build Coastguard Worker 
981*f6dc9357SAndroid Build Coastguard Worker         // memcpy(pm.Data, buf + pos + 2, pm.Length - 2);
982*f6dc9357SAndroid Build Coastguard Worker         if (pm.Type == 1)
983*f6dc9357SAndroid Build Coastguard Worker         {
984*f6dc9357SAndroid Build Coastguard Worker           // ECMA 3/10.7.2
985*f6dc9357SAndroid Build Coastguard Worker           if (len != 6)
986*f6dc9357SAndroid Build Coastguard Worker             return S_FALSE;
987*f6dc9357SAndroid Build Coastguard Worker           pm.VolumeSequenceNumber = Get16(buf + pos + 2);
988*f6dc9357SAndroid Build Coastguard Worker           pm.PartitionNumber = Get16(buf + pos + 4);
989*f6dc9357SAndroid Build Coastguard Worker           PRF(printf("\nPartitionMap type 1 PartitionNumber = %2d", pm.PartitionNumber));
990*f6dc9357SAndroid Build Coastguard Worker         }
991*f6dc9357SAndroid Build Coastguard Worker         else if (pm.Type == 2)
992*f6dc9357SAndroid Build Coastguard Worker         {
993*f6dc9357SAndroid Build Coastguard Worker           if (len != 64)
994*f6dc9357SAndroid Build Coastguard Worker             return S_FALSE;
995*f6dc9357SAndroid Build Coastguard Worker           /* ECMA 10.7.3 / Type 2 Partition Map
996*f6dc9357SAndroid Build Coastguard Worker              62 bytes: Partition Identifier. */
997*f6dc9357SAndroid Build Coastguard Worker 
998*f6dc9357SAndroid Build Coastguard Worker           /* UDF
999*f6dc9357SAndroid Build Coastguard Worker               2.2.8   "*UDF Virtual Partition"
1000*f6dc9357SAndroid Build Coastguard Worker               2.2.9   "*UDF Sparable Partition"
1001*f6dc9357SAndroid Build Coastguard Worker               2.2.10  "*UDF Metadata Partition"
1002*f6dc9357SAndroid Build Coastguard Worker           */
1003*f6dc9357SAndroid Build Coastguard Worker 
1004*f6dc9357SAndroid Build Coastguard Worker           if (Get16(buf + pos + 2) != 0) // reserved
1005*f6dc9357SAndroid Build Coastguard Worker             return S_FALSE;
1006*f6dc9357SAndroid Build Coastguard Worker 
1007*f6dc9357SAndroid Build Coastguard Worker           pm.PartitionTypeId.Parse(buf + pos + 4);
1008*f6dc9357SAndroid Build Coastguard Worker           pm.VolumeSequenceNumber = Get16(buf + pos + 36);
1009*f6dc9357SAndroid Build Coastguard Worker           pm.PartitionNumber = Get16(buf + pos + 38);
1010*f6dc9357SAndroid Build Coastguard Worker 
1011*f6dc9357SAndroid Build Coastguard Worker           if (memcmp(pm.PartitionTypeId.Id, "*UDF Metadata Partition", 23) != 0)
1012*f6dc9357SAndroid Build Coastguard Worker             return S_FALSE;
1013*f6dc9357SAndroid Build Coastguard Worker 
1014*f6dc9357SAndroid Build Coastguard Worker           // UDF 2.2.10 Metadata Partition Map
1015*f6dc9357SAndroid Build Coastguard Worker           pm.MetadataFileLocation = Get32(buf + pos + 40);
1016*f6dc9357SAndroid Build Coastguard Worker           // pm.MetadataMirrorFileLocation = Get32(buf + pos + 44);
1017*f6dc9357SAndroid Build Coastguard Worker           // pm.MetadataBitmapFileLocation = Get32(buf + pos + 48);
1018*f6dc9357SAndroid Build Coastguard Worker           // pm.AllocationUnitSize = Get32(buf + pos + 52);
1019*f6dc9357SAndroid Build Coastguard Worker           // pm.AlignmentUnitSize = Get16(buf + pos + 56);
1020*f6dc9357SAndroid Build Coastguard Worker           // pm.Flags = buf[pos + 58];
1021*f6dc9357SAndroid Build Coastguard Worker 
1022*f6dc9357SAndroid Build Coastguard Worker           PRF(printf("\nPartitionMap type 2 PartitionNumber = %2d", pm.PartitionNumber));
1023*f6dc9357SAndroid Build Coastguard Worker           // Unsupported = true;
1024*f6dc9357SAndroid Build Coastguard Worker           // return S_FALSE;
1025*f6dc9357SAndroid Build Coastguard Worker         }
1026*f6dc9357SAndroid Build Coastguard Worker         else
1027*f6dc9357SAndroid Build Coastguard Worker           return S_FALSE;
1028*f6dc9357SAndroid Build Coastguard Worker         pos += len;
1029*f6dc9357SAndroid Build Coastguard Worker         vol.PartitionMaps.Add(pm);
1030*f6dc9357SAndroid Build Coastguard Worker       }
1031*f6dc9357SAndroid Build Coastguard Worker       continue;
1032*f6dc9357SAndroid Build Coastguard Worker     }
1033*f6dc9357SAndroid Build Coastguard Worker 
1034*f6dc9357SAndroid Build Coastguard Worker     /*
1035*f6dc9357SAndroid Build Coastguard Worker     if (tag.Id == DESC_TYPE_UnallocSpace)
1036*f6dc9357SAndroid Build Coastguard Worker     {
1037*f6dc9357SAndroid Build Coastguard Worker       // UInt32 volDescSeqNumer = Get32(buf + 16);
1038*f6dc9357SAndroid Build Coastguard Worker       const UInt32 numAlocDescs = Get32(buf + 20);
1039*f6dc9357SAndroid Build Coastguard Worker       // we need examples for (numAlocDescs != 0) case
1040*f6dc9357SAndroid Build Coastguard Worker       if (numAlocDescs > (bufSize - 24) / 8)
1041*f6dc9357SAndroid Build Coastguard Worker         return S_FALSE;
1042*f6dc9357SAndroid Build Coastguard Worker       for (UInt32 i = 0; i < numAlocDescs; i++)
1043*f6dc9357SAndroid Build Coastguard Worker       {
1044*f6dc9357SAndroid Build Coastguard Worker         CExtent e;
1045*f6dc9357SAndroid Build Coastguard Worker         e.Parse(buf + 24 + i * 8);
1046*f6dc9357SAndroid Build Coastguard Worker       }
1047*f6dc9357SAndroid Build Coastguard Worker       continue;
1048*f6dc9357SAndroid Build Coastguard Worker     }
1049*f6dc9357SAndroid Build Coastguard Worker     else
1050*f6dc9357SAndroid Build Coastguard Worker       continue;
1051*f6dc9357SAndroid Build Coastguard Worker     */
1052*f6dc9357SAndroid Build Coastguard Worker   }
1053*f6dc9357SAndroid Build Coastguard Worker 
1054*f6dc9357SAndroid Build Coastguard Worker   UInt64 totalSize = 0;
1055*f6dc9357SAndroid Build Coastguard Worker 
1056*f6dc9357SAndroid Build Coastguard Worker   unsigned volIndex;
1057*f6dc9357SAndroid Build Coastguard Worker   for (volIndex = 0; volIndex < LogVols.Size(); volIndex++)
1058*f6dc9357SAndroid Build Coastguard Worker   {
1059*f6dc9357SAndroid Build Coastguard Worker     CLogVol &vol = LogVols[volIndex];
1060*f6dc9357SAndroid Build Coastguard Worker     FOR_VECTOR (pmIndex, vol.PartitionMaps)
1061*f6dc9357SAndroid Build Coastguard Worker     {
1062*f6dc9357SAndroid Build Coastguard Worker       CPartitionMap &pm = vol.PartitionMaps[pmIndex];
1063*f6dc9357SAndroid Build Coastguard Worker       for (unsigned i = 0;; i++)
1064*f6dc9357SAndroid Build Coastguard Worker       {
1065*f6dc9357SAndroid Build Coastguard Worker         if (i == Partitions.Size())
1066*f6dc9357SAndroid Build Coastguard Worker           return S_FALSE;
1067*f6dc9357SAndroid Build Coastguard Worker         CPartition &part = Partitions[i];
1068*f6dc9357SAndroid Build Coastguard Worker         if (part.Number == pm.PartitionNumber)
1069*f6dc9357SAndroid Build Coastguard Worker         {
1070*f6dc9357SAndroid Build Coastguard Worker           pm.PartitionIndex = i;
1071*f6dc9357SAndroid Build Coastguard Worker           if (pm.Type == 2)
1072*f6dc9357SAndroid Build Coastguard Worker             break;
1073*f6dc9357SAndroid Build Coastguard Worker 
1074*f6dc9357SAndroid Build Coastguard Worker           /*
1075*f6dc9357SAndroid Build Coastguard Worker           if (part.VolIndex >= 0)
1076*f6dc9357SAndroid Build Coastguard Worker           {
1077*f6dc9357SAndroid Build Coastguard Worker             // it's for 2.60. Fix it
1078*f6dc9357SAndroid Build Coastguard Worker             if (part.VolIndex != (int)volIndex)
1079*f6dc9357SAndroid Build Coastguard Worker               return S_FALSE;
1080*f6dc9357SAndroid Build Coastguard Worker             // return S_FALSE;
1081*f6dc9357SAndroid Build Coastguard Worker           }
1082*f6dc9357SAndroid Build Coastguard Worker           part.VolIndex = volIndex;
1083*f6dc9357SAndroid Build Coastguard Worker           */
1084*f6dc9357SAndroid Build Coastguard Worker 
1085*f6dc9357SAndroid Build Coastguard Worker           totalSize += (UInt64)part.Len << SecLogSize;
1086*f6dc9357SAndroid Build Coastguard Worker           break;
1087*f6dc9357SAndroid Build Coastguard Worker         }
1088*f6dc9357SAndroid Build Coastguard Worker       }
1089*f6dc9357SAndroid Build Coastguard Worker     }
1090*f6dc9357SAndroid Build Coastguard Worker   }
1091*f6dc9357SAndroid Build Coastguard Worker 
1092*f6dc9357SAndroid Build Coastguard Worker   for (volIndex = 0; volIndex < LogVols.Size(); volIndex++)
1093*f6dc9357SAndroid Build Coastguard Worker   {
1094*f6dc9357SAndroid Build Coastguard Worker     CLogVol &vol = LogVols[volIndex];
1095*f6dc9357SAndroid Build Coastguard Worker     FOR_VECTOR (pmIndex, vol.PartitionMaps)
1096*f6dc9357SAndroid Build Coastguard Worker     {
1097*f6dc9357SAndroid Build Coastguard Worker       CPartitionMap &pm = vol.PartitionMaps[pmIndex];
1098*f6dc9357SAndroid Build Coastguard Worker       if (pm.Type != 2)
1099*f6dc9357SAndroid Build Coastguard Worker         continue;
1100*f6dc9357SAndroid Build Coastguard Worker 
1101*f6dc9357SAndroid Build Coastguard Worker       {
1102*f6dc9357SAndroid Build Coastguard Worker         CLongAllocDesc lad;
1103*f6dc9357SAndroid Build Coastguard Worker         lad.Len = vol.BlockSize;
1104*f6dc9357SAndroid Build Coastguard Worker         lad.Location.Pos = pm.MetadataFileLocation;
1105*f6dc9357SAndroid Build Coastguard Worker         // lad.Location.Pos = pm.MetadataMirrorFileLocation;
1106*f6dc9357SAndroid Build Coastguard Worker 
1107*f6dc9357SAndroid Build Coastguard Worker         lad.Location.PartitionRef = (UInt16)pmIndex;
1108*f6dc9357SAndroid Build Coastguard Worker 
1109*f6dc9357SAndroid Build Coastguard Worker         /* we need correct PartitionMaps[lad.Location.PartitionRef].PartitionIndex.
1110*f6dc9357SAndroid Build Coastguard Worker            so we can use pmIndex or find (Type==1) PartitionMap */
1111*f6dc9357SAndroid Build Coastguard Worker         FOR_VECTOR (pmIndex2, vol.PartitionMaps)
1112*f6dc9357SAndroid Build Coastguard Worker         {
1113*f6dc9357SAndroid Build Coastguard Worker           const CPartitionMap &pm2 = vol.PartitionMaps[pmIndex2];
1114*f6dc9357SAndroid Build Coastguard Worker           if (pm2.PartitionNumber == pm.PartitionNumber && pm2.Type == 1)
1115*f6dc9357SAndroid Build Coastguard Worker           {
1116*f6dc9357SAndroid Build Coastguard Worker             lad.Location.PartitionRef = (UInt16)pmIndex2;
1117*f6dc9357SAndroid Build Coastguard Worker             break;
1118*f6dc9357SAndroid Build Coastguard Worker           }
1119*f6dc9357SAndroid Build Coastguard Worker         }
1120*f6dc9357SAndroid Build Coastguard Worker 
1121*f6dc9357SAndroid Build Coastguard Worker         RINOK(ReadItem(volIndex,
1122*f6dc9357SAndroid Build Coastguard Worker             -1, // (fsIndex = -1) means that it's metadata
1123*f6dc9357SAndroid Build Coastguard Worker             lad,
1124*f6dc9357SAndroid Build Coastguard Worker             false, // isDir
1125*f6dc9357SAndroid Build Coastguard Worker             1)) // numRecurseAllowed
1126*f6dc9357SAndroid Build Coastguard Worker       }
1127*f6dc9357SAndroid Build Coastguard Worker       {
1128*f6dc9357SAndroid Build Coastguard Worker         const CItem &item = Items.Back();
1129*f6dc9357SAndroid Build Coastguard Worker         if (!CheckItemExtents(volIndex, item))
1130*f6dc9357SAndroid Build Coastguard Worker           return S_FALSE;
1131*f6dc9357SAndroid Build Coastguard Worker         if (item.Extents.Size() != 1)
1132*f6dc9357SAndroid Build Coastguard Worker         {
1133*f6dc9357SAndroid Build Coastguard Worker           if (item.Extents.Size() < 1)
1134*f6dc9357SAndroid Build Coastguard Worker             return S_FALSE;
1135*f6dc9357SAndroid Build Coastguard Worker           /* Windows 10 writes empty record item.Extents[1].
1136*f6dc9357SAndroid Build Coastguard Worker              we ignore such extent here */
1137*f6dc9357SAndroid Build Coastguard Worker           for (unsigned k = 1; k < item.Extents.Size(); k++)
1138*f6dc9357SAndroid Build Coastguard Worker           {
1139*f6dc9357SAndroid Build Coastguard Worker             const CMyExtent &e = item.Extents[k];
1140*f6dc9357SAndroid Build Coastguard Worker             if (e.GetLen() != 0)
1141*f6dc9357SAndroid Build Coastguard Worker               return S_FALSE;
1142*f6dc9357SAndroid Build Coastguard Worker           }
1143*f6dc9357SAndroid Build Coastguard Worker         }
1144*f6dc9357SAndroid Build Coastguard Worker 
1145*f6dc9357SAndroid Build Coastguard Worker         const CMyExtent &e = item.Extents[0];
1146*f6dc9357SAndroid Build Coastguard Worker         const CPartition &part = Partitions[pm.PartitionIndex];
1147*f6dc9357SAndroid Build Coastguard Worker         CPartition mp = part;
1148*f6dc9357SAndroid Build Coastguard Worker         mp.IsMetadata = true;
1149*f6dc9357SAndroid Build Coastguard Worker         // mp.Number = part.Number;
1150*f6dc9357SAndroid Build Coastguard Worker         mp.Pos = part.Pos + e.Pos;
1151*f6dc9357SAndroid Build Coastguard Worker         mp.Len = e.Len >> SecLogSize;
1152*f6dc9357SAndroid Build Coastguard Worker         pm.PartitionIndex = Partitions.Add(mp);
1153*f6dc9357SAndroid Build Coastguard Worker       }
1154*f6dc9357SAndroid Build Coastguard Worker       // Items.DeleteBack(); // we can delete that metadata item
1155*f6dc9357SAndroid Build Coastguard Worker 
1156*f6dc9357SAndroid Build Coastguard Worker       /*
1157*f6dc9357SAndroid Build Coastguard Worker       // short version of code to read metadata file.
1158*f6dc9357SAndroid Build Coastguard Worker       RINOK(CInArchive::Read(volIndex, pmIndex, pm.MetadataFileLocation, 224, buf));
1159*f6dc9357SAndroid Build Coastguard Worker       CTag tag;
1160*f6dc9357SAndroid Build Coastguard Worker       RINOK(tag.Parse(buf, 224));
1161*f6dc9357SAndroid Build Coastguard Worker       if (tag.Id != DESC_TYPE_ExtendedFile)
1162*f6dc9357SAndroid Build Coastguard Worker         return S_FALSE;
1163*f6dc9357SAndroid Build Coastguard Worker       CShortAllocDesc sad;
1164*f6dc9357SAndroid Build Coastguard Worker       sad.Parse(buf + 216);
1165*f6dc9357SAndroid Build Coastguard Worker       const CPartition &part = Partitions[pm.PartitionIndex];
1166*f6dc9357SAndroid Build Coastguard Worker       CPartition mp = part;
1167*f6dc9357SAndroid Build Coastguard Worker       mp.IsMetadata = true;
1168*f6dc9357SAndroid Build Coastguard Worker       // mp.Number = part.Number;
1169*f6dc9357SAndroid Build Coastguard Worker       mp.Pos = part.Pos + sad.Pos;
1170*f6dc9357SAndroid Build Coastguard Worker       mp.Len = sad.Len >> SecLogSize;
1171*f6dc9357SAndroid Build Coastguard Worker       pm.PartitionIndex = Partitions.Add(mp);
1172*f6dc9357SAndroid Build Coastguard Worker       */
1173*f6dc9357SAndroid Build Coastguard Worker     }
1174*f6dc9357SAndroid Build Coastguard Worker   }
1175*f6dc9357SAndroid Build Coastguard Worker 
1176*f6dc9357SAndroid Build Coastguard Worker   RINOK(_progress->SetTotal(totalSize))
1177*f6dc9357SAndroid Build Coastguard Worker 
1178*f6dc9357SAndroid Build Coastguard Worker   PRF(printf("\n Read files"));
1179*f6dc9357SAndroid Build Coastguard Worker 
1180*f6dc9357SAndroid Build Coastguard Worker   for (volIndex = 0; volIndex < LogVols.Size(); volIndex++)
1181*f6dc9357SAndroid Build Coastguard Worker   {
1182*f6dc9357SAndroid Build Coastguard Worker     CLogVol &vol = LogVols[volIndex];
1183*f6dc9357SAndroid Build Coastguard Worker 
1184*f6dc9357SAndroid Build Coastguard Worker     PRF(printf("\nLogVol %2d", volIndex));
1185*f6dc9357SAndroid Build Coastguard Worker 
1186*f6dc9357SAndroid Build Coastguard Worker     CLongAllocDesc nextExtent = vol.FileSetLocation;
1187*f6dc9357SAndroid Build Coastguard Worker     // while (nextExtent.ExtentLen != 0)
1188*f6dc9357SAndroid Build Coastguard Worker     // for (int i = 0; i < 1; i++)
1189*f6dc9357SAndroid Build Coastguard Worker     {
1190*f6dc9357SAndroid Build Coastguard Worker       if (nextExtent.GetLen() < 512)
1191*f6dc9357SAndroid Build Coastguard Worker         return S_FALSE;
1192*f6dc9357SAndroid Build Coastguard Worker       CByteBuffer buf2(nextExtent.GetLen());
1193*f6dc9357SAndroid Build Coastguard Worker       RINOK(ReadLad(volIndex, nextExtent, buf2))
1194*f6dc9357SAndroid Build Coastguard Worker       const Byte *p = buf2;
1195*f6dc9357SAndroid Build Coastguard Worker       const size_t size = nextExtent.GetLen();
1196*f6dc9357SAndroid Build Coastguard Worker 
1197*f6dc9357SAndroid Build Coastguard Worker       CTag tag;
1198*f6dc9357SAndroid Build Coastguard Worker       RINOK(tag.Parse(p, size))
1199*f6dc9357SAndroid Build Coastguard Worker 
1200*f6dc9357SAndroid Build Coastguard Worker       /*
1201*f6dc9357SAndroid Build Coastguard Worker       // commented in 22.01
1202*f6dc9357SAndroid Build Coastguard Worker       if (tag.Id == DESC_TYPE_ExtendedFile)
1203*f6dc9357SAndroid Build Coastguard Worker       {
1204*f6dc9357SAndroid Build Coastguard Worker         // ECMA 4 / 14.17
1205*f6dc9357SAndroid Build Coastguard Worker         // 2.60 ??
1206*f6dc9357SAndroid Build Coastguard Worker         return S_FALSE;
1207*f6dc9357SAndroid Build Coastguard Worker       }
1208*f6dc9357SAndroid Build Coastguard Worker       */
1209*f6dc9357SAndroid Build Coastguard Worker 
1210*f6dc9357SAndroid Build Coastguard Worker       if (tag.Id != DESC_TYPE_FileSet)
1211*f6dc9357SAndroid Build Coastguard Worker         return S_FALSE;
1212*f6dc9357SAndroid Build Coastguard Worker 
1213*f6dc9357SAndroid Build Coastguard Worker       PRF(printf("\n FileSet", volIndex));
1214*f6dc9357SAndroid Build Coastguard Worker       CFileSet fs;
1215*f6dc9357SAndroid Build Coastguard Worker       fs.RecordingTime.Parse(p + 16);
1216*f6dc9357SAndroid Build Coastguard Worker       // fs.InterchangeLevel = Get16(p + 18);
1217*f6dc9357SAndroid Build Coastguard Worker       // fs.MaxInterchangeLevel = Get16(p + 20);
1218*f6dc9357SAndroid Build Coastguard Worker       fs.FileSetNumber = Get32(p + 40);
1219*f6dc9357SAndroid Build Coastguard Worker       fs.FileSetDescNumber = Get32(p + 44);
1220*f6dc9357SAndroid Build Coastguard Worker 
1221*f6dc9357SAndroid Build Coastguard Worker       fs.LogicalVolumeId.Parse(p + 112);
1222*f6dc9357SAndroid Build Coastguard Worker       fs.Id.Parse(p + 304);
1223*f6dc9357SAndroid Build Coastguard Worker       fs.CopyrightId.Parse(p + 336);
1224*f6dc9357SAndroid Build Coastguard Worker       fs.AbstractId.Parse(p + 368);
1225*f6dc9357SAndroid Build Coastguard Worker 
1226*f6dc9357SAndroid Build Coastguard Worker       fs.RootDirICB.Parse(p + 400);
1227*f6dc9357SAndroid Build Coastguard Worker       fs.DomainId.Parse(p + 416);
1228*f6dc9357SAndroid Build Coastguard Worker 
1229*f6dc9357SAndroid Build Coastguard Worker       // fs.SystemStreamDirICB.Parse(p + 464);
1230*f6dc9357SAndroid Build Coastguard Worker 
1231*f6dc9357SAndroid Build Coastguard Worker       vol.FileSets.Add(fs);
1232*f6dc9357SAndroid Build Coastguard Worker 
1233*f6dc9357SAndroid Build Coastguard Worker       // nextExtent.Parse(p + 448);
1234*f6dc9357SAndroid Build Coastguard Worker     }
1235*f6dc9357SAndroid Build Coastguard Worker 
1236*f6dc9357SAndroid Build Coastguard Worker     FOR_VECTOR (fsIndex, vol.FileSets)
1237*f6dc9357SAndroid Build Coastguard Worker     {
1238*f6dc9357SAndroid Build Coastguard Worker       CFileSet &fs = vol.FileSets[fsIndex];
1239*f6dc9357SAndroid Build Coastguard Worker       const unsigned fileIndex = Files.Size();
1240*f6dc9357SAndroid Build Coastguard Worker       Files.AddNew();
1241*f6dc9357SAndroid Build Coastguard Worker       RINOK(ReadFileItem(volIndex, fsIndex, fs.RootDirICB,
1242*f6dc9357SAndroid Build Coastguard Worker           true, // isDir
1243*f6dc9357SAndroid Build Coastguard Worker           kNumRecursionLevelsMax))
1244*f6dc9357SAndroid Build Coastguard Worker       RINOK(FillRefs(fs, fileIndex, -1, kNumRecursionLevelsMax))
1245*f6dc9357SAndroid Build Coastguard Worker     }
1246*f6dc9357SAndroid Build Coastguard Worker   }
1247*f6dc9357SAndroid Build Coastguard Worker 
1248*f6dc9357SAndroid Build Coastguard Worker 
1249*f6dc9357SAndroid Build Coastguard Worker   for (volIndex = 0; volIndex < LogVols.Size(); volIndex++)
1250*f6dc9357SAndroid Build Coastguard Worker   {
1251*f6dc9357SAndroid Build Coastguard Worker     const CLogVol &vol = LogVols[volIndex];
1252*f6dc9357SAndroid Build Coastguard Worker     // bool showFileSetName = (vol.FileSets.Size() > 1);
1253*f6dc9357SAndroid Build Coastguard Worker     FOR_VECTOR (fsIndex, vol.FileSets)
1254*f6dc9357SAndroid Build Coastguard Worker     {
1255*f6dc9357SAndroid Build Coastguard Worker       const CFileSet &fs = vol.FileSets[fsIndex];
1256*f6dc9357SAndroid Build Coastguard Worker       for (unsigned i =
1257*f6dc9357SAndroid Build Coastguard Worker           // ((showVolName || showFileSetName) ? 0 : 1)
1258*f6dc9357SAndroid Build Coastguard Worker             0; i < fs.Refs.Size(); i++)
1259*f6dc9357SAndroid Build Coastguard Worker       {
1260*f6dc9357SAndroid Build Coastguard Worker         const CRef &ref = vol.FileSets[fsIndex].Refs[i];
1261*f6dc9357SAndroid Build Coastguard Worker         const CFile &file = Files[ref.FileIndex];
1262*f6dc9357SAndroid Build Coastguard Worker         const CItem &item = Items[file.ItemIndex];
1263*f6dc9357SAndroid Build Coastguard Worker         UInt64 size = item.Size;
1264*f6dc9357SAndroid Build Coastguard Worker 
1265*f6dc9357SAndroid Build Coastguard Worker         if (!item.IsRecAndAlloc() || !item.CheckChunkSizes() || !CheckItemExtents(volIndex, item))
1266*f6dc9357SAndroid Build Coastguard Worker           continue;
1267*f6dc9357SAndroid Build Coastguard Worker 
1268*f6dc9357SAndroid Build Coastguard Worker         FOR_VECTOR (extentIndex, item.Extents)
1269*f6dc9357SAndroid Build Coastguard Worker         {
1270*f6dc9357SAndroid Build Coastguard Worker           const CMyExtent &extent = item.Extents[extentIndex];
1271*f6dc9357SAndroid Build Coastguard Worker           const UInt32 len = extent.GetLen();
1272*f6dc9357SAndroid Build Coastguard Worker           if (len == 0)
1273*f6dc9357SAndroid Build Coastguard Worker             continue;
1274*f6dc9357SAndroid Build Coastguard Worker           if (size < len)
1275*f6dc9357SAndroid Build Coastguard Worker             break;
1276*f6dc9357SAndroid Build Coastguard Worker 
1277*f6dc9357SAndroid Build Coastguard Worker           const unsigned partitionIndex = vol.PartitionMaps[extent.PartitionRef].PartitionIndex;
1278*f6dc9357SAndroid Build Coastguard Worker           const UInt32 logBlockNumber = extent.Pos;
1279*f6dc9357SAndroid Build Coastguard Worker           const CPartition &partition = Partitions[partitionIndex];
1280*f6dc9357SAndroid Build Coastguard Worker           const UInt64 offset = ((UInt64)partition.Pos << SecLogSize) +
1281*f6dc9357SAndroid Build Coastguard Worker               (UInt64)logBlockNumber * vol.BlockSize;
1282*f6dc9357SAndroid Build Coastguard Worker           UpdatePhySize(offset + len);
1283*f6dc9357SAndroid Build Coastguard Worker         }
1284*f6dc9357SAndroid Build Coastguard Worker       }
1285*f6dc9357SAndroid Build Coastguard Worker     }
1286*f6dc9357SAndroid Build Coastguard Worker   }
1287*f6dc9357SAndroid Build Coastguard Worker 
1288*f6dc9357SAndroid Build Coastguard Worker   {
1289*f6dc9357SAndroid Build Coastguard Worker     const UInt32 secMask = ((UInt32)1 << SecLogSize) - 1;
1290*f6dc9357SAndroid Build Coastguard Worker     PhySize = (PhySize + secMask) & ~(UInt64)secMask;
1291*f6dc9357SAndroid Build Coastguard Worker   }
1292*f6dc9357SAndroid Build Coastguard Worker 
1293*f6dc9357SAndroid Build Coastguard Worker   NoEndAnchor = true;
1294*f6dc9357SAndroid Build Coastguard Worker 
1295*f6dc9357SAndroid Build Coastguard Worker   if (PhySize < fileSize)
1296*f6dc9357SAndroid Build Coastguard Worker   {
1297*f6dc9357SAndroid Build Coastguard Worker     UInt64 rem = fileSize - PhySize;
1298*f6dc9357SAndroid Build Coastguard Worker     const size_t secSize = (size_t)1 << SecLogSize;
1299*f6dc9357SAndroid Build Coastguard Worker 
1300*f6dc9357SAndroid Build Coastguard Worker     RINOK(InStream_SeekSet(_stream, PhySize))
1301*f6dc9357SAndroid Build Coastguard Worker 
1302*f6dc9357SAndroid Build Coastguard Worker     // some UDF images contain ZEROs before "Anchor Volume Descriptor Pointer" at the end
1303*f6dc9357SAndroid Build Coastguard Worker 
1304*f6dc9357SAndroid Build Coastguard Worker     for (unsigned sec = 0; sec < 1024; sec++)
1305*f6dc9357SAndroid Build Coastguard Worker     {
1306*f6dc9357SAndroid Build Coastguard Worker       if (rem == 0)
1307*f6dc9357SAndroid Build Coastguard Worker         break;
1308*f6dc9357SAndroid Build Coastguard Worker 
1309*f6dc9357SAndroid Build Coastguard Worker       size_t readSize = secSize;
1310*f6dc9357SAndroid Build Coastguard Worker       if (readSize > rem)
1311*f6dc9357SAndroid Build Coastguard Worker         readSize = (size_t)rem;
1312*f6dc9357SAndroid Build Coastguard Worker 
1313*f6dc9357SAndroid Build Coastguard Worker       RINOK(ReadStream(_stream, buf, &readSize))
1314*f6dc9357SAndroid Build Coastguard Worker 
1315*f6dc9357SAndroid Build Coastguard Worker       if (readSize == 0)
1316*f6dc9357SAndroid Build Coastguard Worker         break;
1317*f6dc9357SAndroid Build Coastguard Worker 
1318*f6dc9357SAndroid Build Coastguard Worker       // some udf contain many EndAnchors
1319*f6dc9357SAndroid Build Coastguard Worker       if (readSize == secSize /* && NoEndAnchor */)
1320*f6dc9357SAndroid Build Coastguard Worker       {
1321*f6dc9357SAndroid Build Coastguard Worker         CTag tag;
1322*f6dc9357SAndroid Build Coastguard Worker         if (tag.Parse(buf, readSize) == S_OK
1323*f6dc9357SAndroid Build Coastguard Worker             && tag.Id == DESC_TYPE_AnchorVolPtr
1324*f6dc9357SAndroid Build Coastguard Worker             && Get32(buf + 12) == (UInt32)((fileSize - rem) >> SecLogSize))
1325*f6dc9357SAndroid Build Coastguard Worker         {
1326*f6dc9357SAndroid Build Coastguard Worker           NoEndAnchor = false;
1327*f6dc9357SAndroid Build Coastguard Worker           rem -= readSize;
1328*f6dc9357SAndroid Build Coastguard Worker           PhySize = fileSize - rem;
1329*f6dc9357SAndroid Build Coastguard Worker           continue;
1330*f6dc9357SAndroid Build Coastguard Worker         }
1331*f6dc9357SAndroid Build Coastguard Worker       }
1332*f6dc9357SAndroid Build Coastguard Worker 
1333*f6dc9357SAndroid Build Coastguard Worker       size_t i;
1334*f6dc9357SAndroid Build Coastguard Worker       for (i = 0; i < readSize && buf[i] == 0; i++);
1335*f6dc9357SAndroid Build Coastguard Worker       if (i != readSize)
1336*f6dc9357SAndroid Build Coastguard Worker         break;
1337*f6dc9357SAndroid Build Coastguard Worker       rem -= readSize;
1338*f6dc9357SAndroid Build Coastguard Worker     }
1339*f6dc9357SAndroid Build Coastguard Worker 
1340*f6dc9357SAndroid Build Coastguard Worker     if (rem == 0)
1341*f6dc9357SAndroid Build Coastguard Worker       PhySize = fileSize;
1342*f6dc9357SAndroid Build Coastguard Worker   }
1343*f6dc9357SAndroid Build Coastguard Worker 
1344*f6dc9357SAndroid Build Coastguard Worker   return S_OK;
1345*f6dc9357SAndroid Build Coastguard Worker }
1346*f6dc9357SAndroid Build Coastguard Worker 
1347*f6dc9357SAndroid Build Coastguard Worker 
Open(IInStream * inStream,CProgressVirt * progress)1348*f6dc9357SAndroid Build Coastguard Worker HRESULT CInArchive::Open(IInStream *inStream, CProgressVirt *progress)
1349*f6dc9357SAndroid Build Coastguard Worker {
1350*f6dc9357SAndroid Build Coastguard Worker   _progress = progress;
1351*f6dc9357SAndroid Build Coastguard Worker   _stream = inStream;
1352*f6dc9357SAndroid Build Coastguard Worker   HRESULT res = Open2();
1353*f6dc9357SAndroid Build Coastguard Worker   if (res == S_FALSE && IsArc && !UnexpectedEnd)
1354*f6dc9357SAndroid Build Coastguard Worker     Unsupported = true;
1355*f6dc9357SAndroid Build Coastguard Worker   return res;
1356*f6dc9357SAndroid Build Coastguard Worker 
1357*f6dc9357SAndroid Build Coastguard Worker   /*
1358*f6dc9357SAndroid Build Coastguard Worker   HRESULT res;
1359*f6dc9357SAndroid Build Coastguard Worker   try
1360*f6dc9357SAndroid Build Coastguard Worker   {
1361*f6dc9357SAndroid Build Coastguard Worker     res = Open2();
1362*f6dc9357SAndroid Build Coastguard Worker   }
1363*f6dc9357SAndroid Build Coastguard Worker   catch(...)
1364*f6dc9357SAndroid Build Coastguard Worker   {
1365*f6dc9357SAndroid Build Coastguard Worker     // Clear();
1366*f6dc9357SAndroid Build Coastguard Worker     // res = S_FALSE;
1367*f6dc9357SAndroid Build Coastguard Worker     _stream.Release();
1368*f6dc9357SAndroid Build Coastguard Worker     throw;
1369*f6dc9357SAndroid Build Coastguard Worker   }
1370*f6dc9357SAndroid Build Coastguard Worker   _stream.Release();
1371*f6dc9357SAndroid Build Coastguard Worker   return res;
1372*f6dc9357SAndroid Build Coastguard Worker   */
1373*f6dc9357SAndroid Build Coastguard Worker }
1374*f6dc9357SAndroid Build Coastguard Worker 
Clear()1375*f6dc9357SAndroid Build Coastguard Worker void CInArchive::Clear()
1376*f6dc9357SAndroid Build Coastguard Worker {
1377*f6dc9357SAndroid Build Coastguard Worker   IsArc = false;
1378*f6dc9357SAndroid Build Coastguard Worker   Unsupported = false;
1379*f6dc9357SAndroid Build Coastguard Worker   UnexpectedEnd = false;
1380*f6dc9357SAndroid Build Coastguard Worker   NoEndAnchor = false;
1381*f6dc9357SAndroid Build Coastguard Worker 
1382*f6dc9357SAndroid Build Coastguard Worker   PhySize = 0;
1383*f6dc9357SAndroid Build Coastguard Worker   FileSize = 0;
1384*f6dc9357SAndroid Build Coastguard Worker 
1385*f6dc9357SAndroid Build Coastguard Worker   Partitions.Clear();
1386*f6dc9357SAndroid Build Coastguard Worker   LogVols.Clear();
1387*f6dc9357SAndroid Build Coastguard Worker   PrimeVols.Clear();
1388*f6dc9357SAndroid Build Coastguard Worker   Items.Clear();
1389*f6dc9357SAndroid Build Coastguard Worker   Files.Clear();
1390*f6dc9357SAndroid Build Coastguard Worker   _fileNameLengthTotal = 0;
1391*f6dc9357SAndroid Build Coastguard Worker   _numRefs = 0;
1392*f6dc9357SAndroid Build Coastguard Worker   _numExtents = 0;
1393*f6dc9357SAndroid Build Coastguard Worker   _inlineExtentsSize = 0;
1394*f6dc9357SAndroid Build Coastguard Worker   _processedProgressBytes = 0;
1395*f6dc9357SAndroid Build Coastguard Worker }
1396*f6dc9357SAndroid Build Coastguard Worker 
1397*f6dc9357SAndroid Build Coastguard Worker 
1398*f6dc9357SAndroid Build Coastguard Worker static const char * const g_PartitionTypes[] =
1399*f6dc9357SAndroid Build Coastguard Worker {
1400*f6dc9357SAndroid Build Coastguard Worker     "Pseudo-Overwritable" // UDF
1401*f6dc9357SAndroid Build Coastguard Worker   , "Read-Only"
1402*f6dc9357SAndroid Build Coastguard Worker   , "Write-Once"
1403*f6dc9357SAndroid Build Coastguard Worker   , "Rewritable"
1404*f6dc9357SAndroid Build Coastguard Worker   , "Overwritable"
1405*f6dc9357SAndroid Build Coastguard Worker };
1406*f6dc9357SAndroid Build Coastguard Worker 
1407*f6dc9357SAndroid Build Coastguard Worker 
AddComment_Align(UString & s)1408*f6dc9357SAndroid Build Coastguard Worker static void AddComment_Align(UString &s)
1409*f6dc9357SAndroid Build Coastguard Worker {
1410*f6dc9357SAndroid Build Coastguard Worker   s += "  ";
1411*f6dc9357SAndroid Build Coastguard Worker }
1412*f6dc9357SAndroid Build Coastguard Worker 
AddComment_PropName(UString & s,const char * name)1413*f6dc9357SAndroid Build Coastguard Worker static void AddComment_PropName(UString &s, const char *name)
1414*f6dc9357SAndroid Build Coastguard Worker {
1415*f6dc9357SAndroid Build Coastguard Worker   AddComment_Align(s);
1416*f6dc9357SAndroid Build Coastguard Worker   s += name;
1417*f6dc9357SAndroid Build Coastguard Worker   s += ": ";
1418*f6dc9357SAndroid Build Coastguard Worker }
1419*f6dc9357SAndroid Build Coastguard Worker 
AddComment_UInt32(UString & s,const char * name,UInt32 val)1420*f6dc9357SAndroid Build Coastguard Worker static void AddComment_UInt32(UString &s, const char *name, UInt32 val)
1421*f6dc9357SAndroid Build Coastguard Worker {
1422*f6dc9357SAndroid Build Coastguard Worker   AddComment_PropName(s, name);
1423*f6dc9357SAndroid Build Coastguard Worker   s.Add_UInt32(val);
1424*f6dc9357SAndroid Build Coastguard Worker   s.Add_LF();
1425*f6dc9357SAndroid Build Coastguard Worker }
1426*f6dc9357SAndroid Build Coastguard Worker 
AddComment_UInt32_2(UString & s,const char * name,UInt32 val)1427*f6dc9357SAndroid Build Coastguard Worker static void AddComment_UInt32_2(UString &s, const char *name, UInt32 val)
1428*f6dc9357SAndroid Build Coastguard Worker {
1429*f6dc9357SAndroid Build Coastguard Worker   AddComment_Align(s);
1430*f6dc9357SAndroid Build Coastguard Worker   AddComment_UInt32(s, name, val);
1431*f6dc9357SAndroid Build Coastguard Worker }
1432*f6dc9357SAndroid Build Coastguard Worker 
1433*f6dc9357SAndroid Build Coastguard Worker 
AddComment_UInt64(UString & s,const char * name,UInt64 val)1434*f6dc9357SAndroid Build Coastguard Worker static void AddComment_UInt64(UString &s, const char *name, UInt64 val)
1435*f6dc9357SAndroid Build Coastguard Worker {
1436*f6dc9357SAndroid Build Coastguard Worker   AddComment_PropName(s, name);
1437*f6dc9357SAndroid Build Coastguard Worker   s.Add_UInt64(val);
1438*f6dc9357SAndroid Build Coastguard Worker   s.Add_LF();
1439*f6dc9357SAndroid Build Coastguard Worker }
1440*f6dc9357SAndroid Build Coastguard Worker 
AddComment_RegId(UString & s,const char * name,const CRegId & ri)1441*f6dc9357SAndroid Build Coastguard Worker static void AddComment_RegId(UString &s, const char *name, const CRegId &ri)
1442*f6dc9357SAndroid Build Coastguard Worker {
1443*f6dc9357SAndroid Build Coastguard Worker   AddComment_PropName(s, name);
1444*f6dc9357SAndroid Build Coastguard Worker   ri.AddCommentTo(s);
1445*f6dc9357SAndroid Build Coastguard Worker   s.Add_LF();
1446*f6dc9357SAndroid Build Coastguard Worker }
1447*f6dc9357SAndroid Build Coastguard Worker 
AddComment_RegId_Domain(UString & s,const char * name,const CRegId & ri)1448*f6dc9357SAndroid Build Coastguard Worker static void AddComment_RegId_Domain(UString &s, const char *name, const CRegId &ri)
1449*f6dc9357SAndroid Build Coastguard Worker {
1450*f6dc9357SAndroid Build Coastguard Worker   AddComment_PropName(s, name);
1451*f6dc9357SAndroid Build Coastguard Worker   ri.AddCommentTo(s);
1452*f6dc9357SAndroid Build Coastguard Worker   {
1453*f6dc9357SAndroid Build Coastguard Worker     UString s2;
1454*f6dc9357SAndroid Build Coastguard Worker     ri.AddUdfVersionTo(s2);
1455*f6dc9357SAndroid Build Coastguard Worker     if (!s2.IsEmpty())
1456*f6dc9357SAndroid Build Coastguard Worker     {
1457*f6dc9357SAndroid Build Coastguard Worker       s += "::";
1458*f6dc9357SAndroid Build Coastguard Worker       s += s2;
1459*f6dc9357SAndroid Build Coastguard Worker     }
1460*f6dc9357SAndroid Build Coastguard Worker   }
1461*f6dc9357SAndroid Build Coastguard Worker   s.Add_LF();
1462*f6dc9357SAndroid Build Coastguard Worker }
1463*f6dc9357SAndroid Build Coastguard Worker 
1464*f6dc9357SAndroid Build Coastguard Worker 
1465*f6dc9357SAndroid Build Coastguard Worker // UDF 6.3.1 OS Class
1466*f6dc9357SAndroid Build Coastguard Worker 
1467*f6dc9357SAndroid Build Coastguard Worker static const char * const g_OsClasses[] =
1468*f6dc9357SAndroid Build Coastguard Worker {
1469*f6dc9357SAndroid Build Coastguard Worker     NULL
1470*f6dc9357SAndroid Build Coastguard Worker   , "DOS"
1471*f6dc9357SAndroid Build Coastguard Worker   , "OS/2"
1472*f6dc9357SAndroid Build Coastguard Worker   , "Macintosh OS"
1473*f6dc9357SAndroid Build Coastguard Worker   , "UNIX"
1474*f6dc9357SAndroid Build Coastguard Worker   , "Windows 9x"
1475*f6dc9357SAndroid Build Coastguard Worker   , "Windows NT"
1476*f6dc9357SAndroid Build Coastguard Worker   , "OS/400"
1477*f6dc9357SAndroid Build Coastguard Worker   , "BeOS"
1478*f6dc9357SAndroid Build Coastguard Worker   , "Windows CE"
1479*f6dc9357SAndroid Build Coastguard Worker };
1480*f6dc9357SAndroid Build Coastguard Worker 
1481*f6dc9357SAndroid Build Coastguard Worker // UDF 6.3.2 OS Identifier
1482*f6dc9357SAndroid Build Coastguard Worker 
1483*f6dc9357SAndroid Build Coastguard Worker static const char * const g_OsIds_Unix[] =
1484*f6dc9357SAndroid Build Coastguard Worker {
1485*f6dc9357SAndroid Build Coastguard Worker     NULL // "Generic"
1486*f6dc9357SAndroid Build Coastguard Worker   , "AIX"
1487*f6dc9357SAndroid Build Coastguard Worker   , "SUN OS / Solaris"
1488*f6dc9357SAndroid Build Coastguard Worker   , "HP/UX"
1489*f6dc9357SAndroid Build Coastguard Worker   , "Silicon Graphics Irix"
1490*f6dc9357SAndroid Build Coastguard Worker   , "Linux"
1491*f6dc9357SAndroid Build Coastguard Worker   , "MKLinux"
1492*f6dc9357SAndroid Build Coastguard Worker   , "FreeBSD"
1493*f6dc9357SAndroid Build Coastguard Worker   , "NetBSD"
1494*f6dc9357SAndroid Build Coastguard Worker };
1495*f6dc9357SAndroid Build Coastguard Worker 
AddOs_Class_Id(UString & s,const Byte * p)1496*f6dc9357SAndroid Build Coastguard Worker static void AddOs_Class_Id(UString &s, const Byte *p)
1497*f6dc9357SAndroid Build Coastguard Worker {
1498*f6dc9357SAndroid Build Coastguard Worker   // UDF 2.1.5.3 Implementation Identifier Suffix
1499*f6dc9357SAndroid Build Coastguard Worker   // Appendix 6.3 Operating System Identifiers.
1500*f6dc9357SAndroid Build Coastguard Worker   const Byte osClass = p[0];
1501*f6dc9357SAndroid Build Coastguard Worker   if (osClass != 0)
1502*f6dc9357SAndroid Build Coastguard Worker   {
1503*f6dc9357SAndroid Build Coastguard Worker     s += "::";
1504*f6dc9357SAndroid Build Coastguard Worker     s += TypeToString(g_OsClasses, Z7_ARRAY_SIZE(g_OsClasses), osClass);
1505*f6dc9357SAndroid Build Coastguard Worker   }
1506*f6dc9357SAndroid Build Coastguard Worker   const Byte osId = p[1];
1507*f6dc9357SAndroid Build Coastguard Worker   if (osId != 0)
1508*f6dc9357SAndroid Build Coastguard Worker   {
1509*f6dc9357SAndroid Build Coastguard Worker     s += "::";
1510*f6dc9357SAndroid Build Coastguard Worker     if (osClass == 4) // unix
1511*f6dc9357SAndroid Build Coastguard Worker     {
1512*f6dc9357SAndroid Build Coastguard Worker       s += TypeToString(g_OsIds_Unix, Z7_ARRAY_SIZE(g_OsIds_Unix), osId);
1513*f6dc9357SAndroid Build Coastguard Worker     }
1514*f6dc9357SAndroid Build Coastguard Worker     else
1515*f6dc9357SAndroid Build Coastguard Worker       s.Add_UInt32(osId);
1516*f6dc9357SAndroid Build Coastguard Worker   }
1517*f6dc9357SAndroid Build Coastguard Worker }
1518*f6dc9357SAndroid Build Coastguard Worker 
1519*f6dc9357SAndroid Build Coastguard Worker 
AddComment_RegId_Impl(UString & s,const char * name,const CRegId & ri)1520*f6dc9357SAndroid Build Coastguard Worker static void AddComment_RegId_Impl(UString &s, const char *name, const CRegId &ri)
1521*f6dc9357SAndroid Build Coastguard Worker {
1522*f6dc9357SAndroid Build Coastguard Worker   AddComment_PropName(s, name);
1523*f6dc9357SAndroid Build Coastguard Worker   ri.AddCommentTo(s);
1524*f6dc9357SAndroid Build Coastguard Worker   {
1525*f6dc9357SAndroid Build Coastguard Worker     AddOs_Class_Id(s, ri.Suffix);
1526*f6dc9357SAndroid Build Coastguard Worker   }
1527*f6dc9357SAndroid Build Coastguard Worker   s.Add_LF();
1528*f6dc9357SAndroid Build Coastguard Worker }
1529*f6dc9357SAndroid Build Coastguard Worker 
1530*f6dc9357SAndroid Build Coastguard Worker 
AddComment_RegId_UdfId(UString & s,const char * name,const CRegId & ri)1531*f6dc9357SAndroid Build Coastguard Worker static void AddComment_RegId_UdfId(UString &s, const char *name, const CRegId &ri)
1532*f6dc9357SAndroid Build Coastguard Worker {
1533*f6dc9357SAndroid Build Coastguard Worker   AddComment_PropName(s, name);
1534*f6dc9357SAndroid Build Coastguard Worker   ri.AddCommentTo(s);
1535*f6dc9357SAndroid Build Coastguard Worker   {
1536*f6dc9357SAndroid Build Coastguard Worker     // UDF 2.1.5.3
1537*f6dc9357SAndroid Build Coastguard Worker     // UDF Identifier Suffix format
1538*f6dc9357SAndroid Build Coastguard Worker     UString s2;
1539*f6dc9357SAndroid Build Coastguard Worker     ri.AddUdfVersionTo(s2);
1540*f6dc9357SAndroid Build Coastguard Worker     if (!s2.IsEmpty())
1541*f6dc9357SAndroid Build Coastguard Worker     {
1542*f6dc9357SAndroid Build Coastguard Worker       s += "::";
1543*f6dc9357SAndroid Build Coastguard Worker       s += s2;
1544*f6dc9357SAndroid Build Coastguard Worker     }
1545*f6dc9357SAndroid Build Coastguard Worker     AddOs_Class_Id(s, &ri.Suffix[2]);
1546*f6dc9357SAndroid Build Coastguard Worker   }
1547*f6dc9357SAndroid Build Coastguard Worker   s.Add_LF();
1548*f6dc9357SAndroid Build Coastguard Worker }
1549*f6dc9357SAndroid Build Coastguard Worker 
AddComment_DString32(UString & s,const char * name,const CDString32 & d)1550*f6dc9357SAndroid Build Coastguard Worker static void AddComment_DString32(UString &s, const char *name, const CDString32 &d)
1551*f6dc9357SAndroid Build Coastguard Worker {
1552*f6dc9357SAndroid Build Coastguard Worker   AddComment_Align(s);
1553*f6dc9357SAndroid Build Coastguard Worker   AddComment_PropName(s, name);
1554*f6dc9357SAndroid Build Coastguard Worker   s += d.GetString();
1555*f6dc9357SAndroid Build Coastguard Worker   s.Add_LF();
1556*f6dc9357SAndroid Build Coastguard Worker }
1557*f6dc9357SAndroid Build Coastguard Worker 
GetComment() const1558*f6dc9357SAndroid Build Coastguard Worker UString CInArchive::GetComment() const
1559*f6dc9357SAndroid Build Coastguard Worker {
1560*f6dc9357SAndroid Build Coastguard Worker   UString s;
1561*f6dc9357SAndroid Build Coastguard Worker   {
1562*f6dc9357SAndroid Build Coastguard Worker     s += "Primary Volumes:";
1563*f6dc9357SAndroid Build Coastguard Worker     s.Add_LF();
1564*f6dc9357SAndroid Build Coastguard Worker     FOR_VECTOR (i, PrimeVols)
1565*f6dc9357SAndroid Build Coastguard Worker     {
1566*f6dc9357SAndroid Build Coastguard Worker       if (i != 0)
1567*f6dc9357SAndroid Build Coastguard Worker         s.Add_LF();
1568*f6dc9357SAndroid Build Coastguard Worker       const CPrimeVol &pv = PrimeVols[i];
1569*f6dc9357SAndroid Build Coastguard Worker       // AddComment_UInt32(s, "VolumeDescriptorSequenceNumber", pv.VolumeDescriptorSequenceNumber);
1570*f6dc9357SAndroid Build Coastguard Worker       // if (PrimeVols.Size() != 1 || pv.PrimaryVolumeDescriptorNumber != 0)
1571*f6dc9357SAndroid Build Coastguard Worker         AddComment_UInt32(s, "PrimaryVolumeDescriptorNumber", pv.PrimaryVolumeDescriptorNumber);
1572*f6dc9357SAndroid Build Coastguard Worker       // if (pv.MaximumVolumeSequenceNumber != 1 || pv.VolumeSequenceNumber != 1)
1573*f6dc9357SAndroid Build Coastguard Worker         AddComment_UInt32(s, "VolumeSequenceNumber", pv.VolumeSequenceNumber);
1574*f6dc9357SAndroid Build Coastguard Worker       if (pv.MaximumVolumeSequenceNumber != 1)
1575*f6dc9357SAndroid Build Coastguard Worker         AddComment_UInt32(s, "MaximumVolumeSequenceNumber", pv.MaximumVolumeSequenceNumber);
1576*f6dc9357SAndroid Build Coastguard Worker       AddComment_PropName(s, "VolumeId");
1577*f6dc9357SAndroid Build Coastguard Worker       s += pv.VolumeId.GetString();
1578*f6dc9357SAndroid Build Coastguard Worker       s.Add_LF();
1579*f6dc9357SAndroid Build Coastguard Worker       AddComment_PropName(s, "VolumeSetId");
1580*f6dc9357SAndroid Build Coastguard Worker       s += pv.VolumeSetId.GetString();
1581*f6dc9357SAndroid Build Coastguard Worker       s.Add_LF();
1582*f6dc9357SAndroid Build Coastguard Worker       // AddComment_UInt32(s, "InterchangeLevel", pv.InterchangeLevel);
1583*f6dc9357SAndroid Build Coastguard Worker       // AddComment_UInt32(s, "MaximumInterchangeLevel", pv.MaximumInterchangeLevel);
1584*f6dc9357SAndroid Build Coastguard Worker       AddComment_RegId(s, "ApplicationId", pv.ApplicationId);
1585*f6dc9357SAndroid Build Coastguard Worker       AddComment_RegId_Impl(s, "ImplementationId", pv.ImplId);
1586*f6dc9357SAndroid Build Coastguard Worker     }
1587*f6dc9357SAndroid Build Coastguard Worker   }
1588*f6dc9357SAndroid Build Coastguard Worker   {
1589*f6dc9357SAndroid Build Coastguard Worker     s += "Partitions:";
1590*f6dc9357SAndroid Build Coastguard Worker     s.Add_LF();
1591*f6dc9357SAndroid Build Coastguard Worker     FOR_VECTOR (i, Partitions)
1592*f6dc9357SAndroid Build Coastguard Worker     {
1593*f6dc9357SAndroid Build Coastguard Worker       if (i != 0)
1594*f6dc9357SAndroid Build Coastguard Worker         s.Add_LF();
1595*f6dc9357SAndroid Build Coastguard Worker       const CPartition &part = Partitions[i];
1596*f6dc9357SAndroid Build Coastguard Worker       AddComment_UInt32(s, "PartitionIndex", i);
1597*f6dc9357SAndroid Build Coastguard Worker       AddComment_UInt32(s, "PartitionNumber", part.Number);
1598*f6dc9357SAndroid Build Coastguard Worker       if (part.IsMetadata)
1599*f6dc9357SAndroid Build Coastguard Worker         AddComment_UInt32(s, "IsMetadata", 1);
1600*f6dc9357SAndroid Build Coastguard Worker       else
1601*f6dc9357SAndroid Build Coastguard Worker       {
1602*f6dc9357SAndroid Build Coastguard Worker         AddComment_RegId(s, "ContentsId", part.ContentsId);
1603*f6dc9357SAndroid Build Coastguard Worker         AddComment_RegId_Impl(s, "ImplementationId", part.ImplId);
1604*f6dc9357SAndroid Build Coastguard Worker         AddComment_PropName(s, "AccessType");
1605*f6dc9357SAndroid Build Coastguard Worker         s += TypeToString(g_PartitionTypes, Z7_ARRAY_SIZE(g_PartitionTypes), part.AccessType);
1606*f6dc9357SAndroid Build Coastguard Worker         s.Add_LF();
1607*f6dc9357SAndroid Build Coastguard Worker       }
1608*f6dc9357SAndroid Build Coastguard Worker       AddComment_UInt64(s, "Size", (UInt64)part.Len << SecLogSize);
1609*f6dc9357SAndroid Build Coastguard Worker       AddComment_UInt64(s, "Pos", (UInt64)part.Pos << SecLogSize);
1610*f6dc9357SAndroid Build Coastguard Worker     }
1611*f6dc9357SAndroid Build Coastguard Worker   }
1612*f6dc9357SAndroid Build Coastguard Worker   s += "Logical Volumes:";
1613*f6dc9357SAndroid Build Coastguard Worker   s.Add_LF();
1614*f6dc9357SAndroid Build Coastguard Worker   {
1615*f6dc9357SAndroid Build Coastguard Worker     FOR_VECTOR (i, LogVols)
1616*f6dc9357SAndroid Build Coastguard Worker     {
1617*f6dc9357SAndroid Build Coastguard Worker       if (i != 0)
1618*f6dc9357SAndroid Build Coastguard Worker         s.Add_LF();
1619*f6dc9357SAndroid Build Coastguard Worker       const CLogVol &vol = LogVols[i];
1620*f6dc9357SAndroid Build Coastguard Worker       if (LogVols.Size() != 1)
1621*f6dc9357SAndroid Build Coastguard Worker         AddComment_UInt32(s, "Number", i);
1622*f6dc9357SAndroid Build Coastguard Worker       AddComment_PropName(s, "Id");
1623*f6dc9357SAndroid Build Coastguard Worker       s += vol.Id.GetString();
1624*f6dc9357SAndroid Build Coastguard Worker       s.Add_LF();
1625*f6dc9357SAndroid Build Coastguard Worker       AddComment_UInt32(s, "BlockSize", vol.BlockSize);
1626*f6dc9357SAndroid Build Coastguard Worker       AddComment_RegId_Domain(s, "DomainId", vol.DomainId);
1627*f6dc9357SAndroid Build Coastguard Worker       AddComment_RegId_Impl(s, "ImplementationId", vol.ImplId);
1628*f6dc9357SAndroid Build Coastguard Worker       // AddComment_UInt64(s, "IntegritySequenceExtent_Len", vol.IntegritySequenceExtent.Len);
1629*f6dc9357SAndroid Build Coastguard Worker       // AddComment_UInt64(s, "IntegritySequenceExtent_Pos", (UInt64)vol.IntegritySequenceExtent.Pos << SecLogSize);
1630*f6dc9357SAndroid Build Coastguard Worker 
1631*f6dc9357SAndroid Build Coastguard Worker       s += "  Partition Maps:";
1632*f6dc9357SAndroid Build Coastguard Worker       s.Add_LF();
1633*f6dc9357SAndroid Build Coastguard Worker       {
1634*f6dc9357SAndroid Build Coastguard Worker         FOR_VECTOR (j, vol.PartitionMaps)
1635*f6dc9357SAndroid Build Coastguard Worker         {
1636*f6dc9357SAndroid Build Coastguard Worker           if (j != 0)
1637*f6dc9357SAndroid Build Coastguard Worker             s.Add_LF();
1638*f6dc9357SAndroid Build Coastguard Worker           const CPartitionMap &pm = vol.PartitionMaps[j];
1639*f6dc9357SAndroid Build Coastguard Worker           AddComment_UInt32_2(s, "PartitionMap", j);
1640*f6dc9357SAndroid Build Coastguard Worker           AddComment_UInt32_2(s, "Type", pm.Type);
1641*f6dc9357SAndroid Build Coastguard Worker           AddComment_UInt32_2(s, "VolumeSequenceNumber", pm.VolumeSequenceNumber);
1642*f6dc9357SAndroid Build Coastguard Worker           AddComment_UInt32_2(s, "PartitionNumber", pm.PartitionNumber);
1643*f6dc9357SAndroid Build Coastguard Worker           if (pm.Type == 2)
1644*f6dc9357SAndroid Build Coastguard Worker           {
1645*f6dc9357SAndroid Build Coastguard Worker             AddComment_UInt32_2(s, "MetadataFileLocation", pm.MetadataFileLocation);
1646*f6dc9357SAndroid Build Coastguard Worker             // AddComment_UInt32_2(s, "MetadataMirrorFileLocation", pm.MetadataMirrorFileLocation);
1647*f6dc9357SAndroid Build Coastguard Worker             // AddComment_UInt32_2(s, "MetadataBitmapFileLocation", pm.MetadataBitmapFileLocation);
1648*f6dc9357SAndroid Build Coastguard Worker             // AddComment_UInt32_2(s, "AllocationUnitSize", pm.AllocationUnitSize);
1649*f6dc9357SAndroid Build Coastguard Worker             // AddComment_UInt32_2(s, "AlignmentUnitSize", pm.AlignmentUnitSize);
1650*f6dc9357SAndroid Build Coastguard Worker             // AddComment_UInt32_2(s, "Flags", pm.Flags);
1651*f6dc9357SAndroid Build Coastguard Worker             AddComment_Align(s); AddComment_RegId_UdfId(s, "PartitionTypeId", pm.PartitionTypeId);
1652*f6dc9357SAndroid Build Coastguard Worker           }
1653*f6dc9357SAndroid Build Coastguard Worker         }
1654*f6dc9357SAndroid Build Coastguard Worker       }
1655*f6dc9357SAndroid Build Coastguard Worker       s += "  File Sets:";
1656*f6dc9357SAndroid Build Coastguard Worker       s.Add_LF();
1657*f6dc9357SAndroid Build Coastguard Worker       {
1658*f6dc9357SAndroid Build Coastguard Worker         FOR_VECTOR (j, vol.FileSets)
1659*f6dc9357SAndroid Build Coastguard Worker         {
1660*f6dc9357SAndroid Build Coastguard Worker           if (j != 0)
1661*f6dc9357SAndroid Build Coastguard Worker             s.Add_LF();
1662*f6dc9357SAndroid Build Coastguard Worker           const CFileSet &fs = vol.FileSets[j];
1663*f6dc9357SAndroid Build Coastguard Worker           AddComment_Align(s); AddComment_UInt32(s, "FileSetNumber", fs.FileSetNumber);
1664*f6dc9357SAndroid Build Coastguard Worker           AddComment_Align(s); AddComment_UInt32(s, "FileSetDescNumber", fs.FileSetDescNumber);
1665*f6dc9357SAndroid Build Coastguard Worker 
1666*f6dc9357SAndroid Build Coastguard Worker           AddComment_Align(s);
1667*f6dc9357SAndroid Build Coastguard Worker           AddComment_PropName(s, "LogicalVolumeId");
1668*f6dc9357SAndroid Build Coastguard Worker           s += fs.LogicalVolumeId.GetString();
1669*f6dc9357SAndroid Build Coastguard Worker           s.Add_LF();
1670*f6dc9357SAndroid Build Coastguard Worker 
1671*f6dc9357SAndroid Build Coastguard Worker           AddComment_DString32(s, "Id", fs.Id);
1672*f6dc9357SAndroid Build Coastguard Worker           AddComment_DString32(s, "CopyrightId", fs.CopyrightId);
1673*f6dc9357SAndroid Build Coastguard Worker           AddComment_DString32(s, "AbstractId", fs.AbstractId);
1674*f6dc9357SAndroid Build Coastguard Worker 
1675*f6dc9357SAndroid Build Coastguard Worker           AddComment_Align(s);
1676*f6dc9357SAndroid Build Coastguard Worker           AddComment_RegId_Domain(s, "DomainId", fs.DomainId);
1677*f6dc9357SAndroid Build Coastguard Worker         }
1678*f6dc9357SAndroid Build Coastguard Worker       }
1679*f6dc9357SAndroid Build Coastguard Worker     }
1680*f6dc9357SAndroid Build Coastguard Worker   }
1681*f6dc9357SAndroid Build Coastguard Worker   return s;
1682*f6dc9357SAndroid Build Coastguard Worker }
1683*f6dc9357SAndroid Build Coastguard Worker 
GetSpecName(const UString & name)1684*f6dc9357SAndroid Build Coastguard Worker static UString GetSpecName(const UString &name)
1685*f6dc9357SAndroid Build Coastguard Worker {
1686*f6dc9357SAndroid Build Coastguard Worker   UString name2 = name;
1687*f6dc9357SAndroid Build Coastguard Worker   name2.Trim();
1688*f6dc9357SAndroid Build Coastguard Worker   if (name2.IsEmpty())
1689*f6dc9357SAndroid Build Coastguard Worker     return UString("[]");
1690*f6dc9357SAndroid Build Coastguard Worker   return name;
1691*f6dc9357SAndroid Build Coastguard Worker }
1692*f6dc9357SAndroid Build Coastguard Worker 
UpdateWithName(UString & res,const UString & addString)1693*f6dc9357SAndroid Build Coastguard Worker static void UpdateWithName(UString &res, const UString &addString)
1694*f6dc9357SAndroid Build Coastguard Worker {
1695*f6dc9357SAndroid Build Coastguard Worker   if (res.IsEmpty())
1696*f6dc9357SAndroid Build Coastguard Worker     res = addString;
1697*f6dc9357SAndroid Build Coastguard Worker   else
1698*f6dc9357SAndroid Build Coastguard Worker     res.Insert(0, addString + WCHAR_PATH_SEPARATOR);
1699*f6dc9357SAndroid Build Coastguard Worker }
1700*f6dc9357SAndroid Build Coastguard Worker 
GetItemPath(unsigned volIndex,unsigned fsIndex,unsigned refIndex,bool showVolName,bool showFsName) const1701*f6dc9357SAndroid Build Coastguard Worker UString CInArchive::GetItemPath(unsigned volIndex, unsigned fsIndex, unsigned refIndex,
1702*f6dc9357SAndroid Build Coastguard Worker     bool showVolName, bool showFsName) const
1703*f6dc9357SAndroid Build Coastguard Worker {
1704*f6dc9357SAndroid Build Coastguard Worker   // showVolName = true;
1705*f6dc9357SAndroid Build Coastguard Worker   const CLogVol &vol = LogVols[volIndex];
1706*f6dc9357SAndroid Build Coastguard Worker   const CFileSet &fs = vol.FileSets[fsIndex];
1707*f6dc9357SAndroid Build Coastguard Worker 
1708*f6dc9357SAndroid Build Coastguard Worker   UString name;
1709*f6dc9357SAndroid Build Coastguard Worker 
1710*f6dc9357SAndroid Build Coastguard Worker   for (;;)
1711*f6dc9357SAndroid Build Coastguard Worker   {
1712*f6dc9357SAndroid Build Coastguard Worker     const CRef &ref = fs.Refs[refIndex];
1713*f6dc9357SAndroid Build Coastguard Worker     // we break on root file (that probably has empty name)
1714*f6dc9357SAndroid Build Coastguard Worker     if (ref.Parent < 0)
1715*f6dc9357SAndroid Build Coastguard Worker       break;
1716*f6dc9357SAndroid Build Coastguard Worker     refIndex = (unsigned)ref.Parent;
1717*f6dc9357SAndroid Build Coastguard Worker     UpdateWithName(name, GetSpecName(Files[ref.FileIndex].GetName()));
1718*f6dc9357SAndroid Build Coastguard Worker   }
1719*f6dc9357SAndroid Build Coastguard Worker 
1720*f6dc9357SAndroid Build Coastguard Worker   if (showFsName)
1721*f6dc9357SAndroid Build Coastguard Worker   {
1722*f6dc9357SAndroid Build Coastguard Worker     UString newName ("File Set ");
1723*f6dc9357SAndroid Build Coastguard Worker     newName.Add_UInt32(fsIndex);
1724*f6dc9357SAndroid Build Coastguard Worker     UpdateWithName(name, newName);
1725*f6dc9357SAndroid Build Coastguard Worker   }
1726*f6dc9357SAndroid Build Coastguard Worker 
1727*f6dc9357SAndroid Build Coastguard Worker   if (showVolName)
1728*f6dc9357SAndroid Build Coastguard Worker   {
1729*f6dc9357SAndroid Build Coastguard Worker     UString newName;
1730*f6dc9357SAndroid Build Coastguard Worker     newName.Add_UInt32(volIndex);
1731*f6dc9357SAndroid Build Coastguard Worker     UString newName2 = vol.GetName();
1732*f6dc9357SAndroid Build Coastguard Worker     if (newName2.IsEmpty())
1733*f6dc9357SAndroid Build Coastguard Worker       newName2 = "Volume";
1734*f6dc9357SAndroid Build Coastguard Worker     newName.Add_Minus();
1735*f6dc9357SAndroid Build Coastguard Worker     newName += newName2;
1736*f6dc9357SAndroid Build Coastguard Worker     UpdateWithName(name, newName);
1737*f6dc9357SAndroid Build Coastguard Worker   }
1738*f6dc9357SAndroid Build Coastguard Worker   return name;
1739*f6dc9357SAndroid Build Coastguard Worker }
1740*f6dc9357SAndroid Build Coastguard Worker 
1741*f6dc9357SAndroid Build Coastguard Worker }}
1742