xref: /aosp_15_r20/external/lzma/CPP/7zip/Archive/GptHandler.cpp (revision f6dc9357d832569d4d1f5d24eacdb3935a1ae8e6)
1*f6dc9357SAndroid Build Coastguard Worker // GptHandler.cpp
2*f6dc9357SAndroid Build Coastguard Worker 
3*f6dc9357SAndroid Build Coastguard Worker #include "StdAfx.h"
4*f6dc9357SAndroid Build Coastguard Worker 
5*f6dc9357SAndroid Build Coastguard Worker #include "../../../C/7zCrc.h"
6*f6dc9357SAndroid Build Coastguard Worker #include "../../../C/CpuArch.h"
7*f6dc9357SAndroid Build Coastguard Worker 
8*f6dc9357SAndroid Build Coastguard Worker #include "../../Common/ComTry.h"
9*f6dc9357SAndroid Build Coastguard Worker #include "../../Common/IntToString.h"
10*f6dc9357SAndroid Build Coastguard Worker #include "../../Common/MyBuffer.h"
11*f6dc9357SAndroid Build Coastguard Worker 
12*f6dc9357SAndroid Build Coastguard Worker #include "../../Windows/PropVariantUtils.h"
13*f6dc9357SAndroid Build Coastguard Worker 
14*f6dc9357SAndroid Build Coastguard Worker #include "../Common/RegisterArc.h"
15*f6dc9357SAndroid Build Coastguard Worker #include "../Common/StreamUtils.h"
16*f6dc9357SAndroid Build Coastguard Worker 
17*f6dc9357SAndroid Build Coastguard Worker #include "HandlerCont.h"
18*f6dc9357SAndroid Build Coastguard Worker 
19*f6dc9357SAndroid Build Coastguard Worker #define Get16(p) GetUi16(p)
20*f6dc9357SAndroid Build Coastguard Worker #define Get32(p) GetUi32(p)
21*f6dc9357SAndroid Build Coastguard Worker #define Get64(p) GetUi64(p)
22*f6dc9357SAndroid Build Coastguard Worker 
23*f6dc9357SAndroid Build Coastguard Worker using namespace NWindows;
24*f6dc9357SAndroid Build Coastguard Worker 
25*f6dc9357SAndroid Build Coastguard Worker namespace NArchive {
26*f6dc9357SAndroid Build Coastguard Worker 
27*f6dc9357SAndroid Build Coastguard Worker namespace NMbr {
28*f6dc9357SAndroid Build Coastguard Worker const char *GetFileSystem(ISequentialInStream *stream, UInt64 partitionSize);
29*f6dc9357SAndroid Build Coastguard Worker }
30*f6dc9357SAndroid Build Coastguard Worker 
31*f6dc9357SAndroid Build Coastguard Worker namespace NFat {
32*f6dc9357SAndroid Build Coastguard Worker API_FUNC_IsArc IsArc_Fat(const Byte *p, size_t size);
33*f6dc9357SAndroid Build Coastguard Worker }
34*f6dc9357SAndroid Build Coastguard Worker 
35*f6dc9357SAndroid Build Coastguard Worker namespace NGpt {
36*f6dc9357SAndroid Build Coastguard Worker 
37*f6dc9357SAndroid Build Coastguard Worker static const unsigned k_SignatureSize = 12;
38*f6dc9357SAndroid Build Coastguard Worker static const Byte k_Signature[k_SignatureSize] =
39*f6dc9357SAndroid Build Coastguard Worker     { 'E', 'F', 'I', ' ', 'P', 'A', 'R', 'T', 0, 0, 1, 0 };
40*f6dc9357SAndroid Build Coastguard Worker 
41*f6dc9357SAndroid Build Coastguard Worker static const CUInt32PCharPair g_PartitionFlags[] =
42*f6dc9357SAndroid Build Coastguard Worker {
43*f6dc9357SAndroid Build Coastguard Worker   { 0, "Sys" },
44*f6dc9357SAndroid Build Coastguard Worker   { 1, "Ignore" },
45*f6dc9357SAndroid Build Coastguard Worker   { 2, "Legacy" },
46*f6dc9357SAndroid Build Coastguard Worker   { 60, "Win-Read-only" },
47*f6dc9357SAndroid Build Coastguard Worker   { 62, "Win-Hidden" },
48*f6dc9357SAndroid Build Coastguard Worker   { 63, "Win-Not-Automount" }
49*f6dc9357SAndroid Build Coastguard Worker };
50*f6dc9357SAndroid Build Coastguard Worker 
51*f6dc9357SAndroid Build Coastguard Worker static const unsigned kNameLen = 36;
52*f6dc9357SAndroid Build Coastguard Worker 
53*f6dc9357SAndroid Build Coastguard Worker struct CPartition
54*f6dc9357SAndroid Build Coastguard Worker {
55*f6dc9357SAndroid Build Coastguard Worker   Byte Type[16];
56*f6dc9357SAndroid Build Coastguard Worker   Byte Id[16];
57*f6dc9357SAndroid Build Coastguard Worker   UInt64 FirstLba;
58*f6dc9357SAndroid Build Coastguard Worker   UInt64 LastLba;
59*f6dc9357SAndroid Build Coastguard Worker   UInt64 Flags;
60*f6dc9357SAndroid Build Coastguard Worker   const char *Ext; // detected later
61*f6dc9357SAndroid Build Coastguard Worker   Byte Name[kNameLen * 2];
62*f6dc9357SAndroid Build Coastguard Worker 
IsUnusedNArchive::NGpt::CPartition63*f6dc9357SAndroid Build Coastguard Worker   bool IsUnused() const
64*f6dc9357SAndroid Build Coastguard Worker   {
65*f6dc9357SAndroid Build Coastguard Worker     for (unsigned i = 0; i < 16; i++)
66*f6dc9357SAndroid Build Coastguard Worker       if (Type[i] != 0)
67*f6dc9357SAndroid Build Coastguard Worker         return false;
68*f6dc9357SAndroid Build Coastguard Worker     return true;
69*f6dc9357SAndroid Build Coastguard Worker   }
70*f6dc9357SAndroid Build Coastguard Worker 
GetSizeNArchive::NGpt::CPartition71*f6dc9357SAndroid Build Coastguard Worker   UInt64 GetSize(unsigned sectorSizeLog) const { return (LastLba - FirstLba + 1) << sectorSizeLog; }
GetPosNArchive::NGpt::CPartition72*f6dc9357SAndroid Build Coastguard Worker   UInt64 GetPos(unsigned sectorSizeLog) const { return FirstLba << sectorSizeLog; }
GetEndNArchive::NGpt::CPartition73*f6dc9357SAndroid Build Coastguard Worker   UInt64 GetEnd(unsigned sectorSizeLog) const { return (LastLba + 1) << sectorSizeLog; }
74*f6dc9357SAndroid Build Coastguard Worker 
ParseNArchive::NGpt::CPartition75*f6dc9357SAndroid Build Coastguard Worker   void Parse(const Byte *p)
76*f6dc9357SAndroid Build Coastguard Worker   {
77*f6dc9357SAndroid Build Coastguard Worker     memcpy(Type, p, 16);
78*f6dc9357SAndroid Build Coastguard Worker     memcpy(Id, p + 16, 16);
79*f6dc9357SAndroid Build Coastguard Worker     FirstLba = Get64(p + 32);
80*f6dc9357SAndroid Build Coastguard Worker     LastLba = Get64(p + 40);
81*f6dc9357SAndroid Build Coastguard Worker     Flags = Get64(p + 48);
82*f6dc9357SAndroid Build Coastguard Worker     memcpy(Name, p + 56, kNameLen * 2);
83*f6dc9357SAndroid Build Coastguard Worker     Ext = NULL;
84*f6dc9357SAndroid Build Coastguard Worker   }
85*f6dc9357SAndroid Build Coastguard Worker };
86*f6dc9357SAndroid Build Coastguard Worker 
87*f6dc9357SAndroid Build Coastguard Worker 
88*f6dc9357SAndroid Build Coastguard Worker struct CPartType
89*f6dc9357SAndroid Build Coastguard Worker {
90*f6dc9357SAndroid Build Coastguard Worker   UInt32 Id;
91*f6dc9357SAndroid Build Coastguard Worker   const char *Ext;
92*f6dc9357SAndroid Build Coastguard Worker   const char *Type;
93*f6dc9357SAndroid Build Coastguard Worker };
94*f6dc9357SAndroid Build Coastguard Worker 
95*f6dc9357SAndroid Build Coastguard Worker static const CPartType kPartTypes[] =
96*f6dc9357SAndroid Build Coastguard Worker {
97*f6dc9357SAndroid Build Coastguard Worker   // { 0x0, NULL, "Unused" },
98*f6dc9357SAndroid Build Coastguard Worker 
99*f6dc9357SAndroid Build Coastguard Worker   { 0x21686148, NULL, "BIOS Boot" },
100*f6dc9357SAndroid Build Coastguard Worker 
101*f6dc9357SAndroid Build Coastguard Worker   { 0xC12A7328, NULL, "EFI System" },
102*f6dc9357SAndroid Build Coastguard Worker   { 0x024DEE41, NULL, "MBR" },
103*f6dc9357SAndroid Build Coastguard Worker 
104*f6dc9357SAndroid Build Coastguard Worker   { 0xE3C9E316, NULL, "Windows MSR" },
105*f6dc9357SAndroid Build Coastguard Worker   { 0xEBD0A0A2, NULL, "Windows BDP" },
106*f6dc9357SAndroid Build Coastguard Worker   { 0x5808C8AA, NULL, "Windows LDM Metadata" },
107*f6dc9357SAndroid Build Coastguard Worker   { 0xAF9B60A0, NULL, "Windows LDM Data" },
108*f6dc9357SAndroid Build Coastguard Worker   { 0xDE94BBA4, NULL, "Windows Recovery" },
109*f6dc9357SAndroid Build Coastguard Worker   // { 0x37AFFC90, NULL, "IBM GPFS" },
110*f6dc9357SAndroid Build Coastguard Worker   // { 0xE75CAF8F, NULL, "Windows Storage Spaces" },
111*f6dc9357SAndroid Build Coastguard Worker 
112*f6dc9357SAndroid Build Coastguard Worker   { 0x0FC63DAF, NULL, "Linux Data" },
113*f6dc9357SAndroid Build Coastguard Worker   { 0x0657FD6D, NULL, "Linux Swap" },
114*f6dc9357SAndroid Build Coastguard Worker   { 0x44479540, NULL, "Linux root (x86)" },
115*f6dc9357SAndroid Build Coastguard Worker   { 0x4F68BCE3, NULL, "Linux root (x86-64)" },
116*f6dc9357SAndroid Build Coastguard Worker   { 0x69DAD710, NULL, "Linux root (ARM)" },
117*f6dc9357SAndroid Build Coastguard Worker   { 0xB921B045, NULL, "Linux root (ARM64)" },
118*f6dc9357SAndroid Build Coastguard Worker   { 0x993D8D3D, NULL, "Linux root (IA-64)" },
119*f6dc9357SAndroid Build Coastguard Worker 
120*f6dc9357SAndroid Build Coastguard Worker 
121*f6dc9357SAndroid Build Coastguard Worker   { 0x83BD6B9D, NULL, "FreeBSD Boot" },
122*f6dc9357SAndroid Build Coastguard Worker   { 0x516E7CB4, NULL, "FreeBSD Data" },
123*f6dc9357SAndroid Build Coastguard Worker   { 0x516E7CB5, NULL, "FreeBSD Swap" },
124*f6dc9357SAndroid Build Coastguard Worker   { 0x516E7CB6, "ufs", "FreeBSD UFS" },
125*f6dc9357SAndroid Build Coastguard Worker   { 0x516E7CB8, NULL, "FreeBSD Vinum" },
126*f6dc9357SAndroid Build Coastguard Worker   { 0x516E7CB8, "zfs", "FreeBSD ZFS" },
127*f6dc9357SAndroid Build Coastguard Worker 
128*f6dc9357SAndroid Build Coastguard Worker   { 0x48465300, "hfsx", "HFS+" },
129*f6dc9357SAndroid Build Coastguard Worker   { 0x7C3457EF, "apfs", "APFS" },
130*f6dc9357SAndroid Build Coastguard Worker };
131*f6dc9357SAndroid Build Coastguard Worker 
FindPartType(const Byte * guid)132*f6dc9357SAndroid Build Coastguard Worker static int FindPartType(const Byte *guid)
133*f6dc9357SAndroid Build Coastguard Worker {
134*f6dc9357SAndroid Build Coastguard Worker   const UInt32 val = Get32(guid);
135*f6dc9357SAndroid Build Coastguard Worker   for (unsigned i = 0; i < Z7_ARRAY_SIZE(kPartTypes); i++)
136*f6dc9357SAndroid Build Coastguard Worker     if (kPartTypes[i].Id == val)
137*f6dc9357SAndroid Build Coastguard Worker       return (int)i;
138*f6dc9357SAndroid Build Coastguard Worker   return -1;
139*f6dc9357SAndroid Build Coastguard Worker }
140*f6dc9357SAndroid Build Coastguard Worker 
141*f6dc9357SAndroid Build Coastguard Worker 
RawLeGuidToString_Upper(const Byte * g,char * s)142*f6dc9357SAndroid Build Coastguard Worker static void RawLeGuidToString_Upper(const Byte *g, char *s)
143*f6dc9357SAndroid Build Coastguard Worker {
144*f6dc9357SAndroid Build Coastguard Worker   RawLeGuidToString(g, s);
145*f6dc9357SAndroid Build Coastguard Worker   // MyStringUpper_Ascii(s);
146*f6dc9357SAndroid Build Coastguard Worker }
147*f6dc9357SAndroid Build Coastguard Worker 
148*f6dc9357SAndroid Build Coastguard Worker 
149*f6dc9357SAndroid Build Coastguard Worker Z7_class_CHandler_final: public CHandlerCont
150*f6dc9357SAndroid Build Coastguard Worker {
151*f6dc9357SAndroid Build Coastguard Worker   Z7_IFACE_COM7_IMP(IInArchive_Cont)
152*f6dc9357SAndroid Build Coastguard Worker 
153*f6dc9357SAndroid Build Coastguard Worker   CRecordVector<CPartition> _items;
154*f6dc9357SAndroid Build Coastguard Worker   UInt64 _totalSize;
155*f6dc9357SAndroid Build Coastguard Worker   unsigned _sectorSizeLog;
156*f6dc9357SAndroid Build Coastguard Worker   Byte Guid[16];
157*f6dc9357SAndroid Build Coastguard Worker 
158*f6dc9357SAndroid Build Coastguard Worker   CByteBuffer _buffer;
159*f6dc9357SAndroid Build Coastguard Worker 
160*f6dc9357SAndroid Build Coastguard Worker   HRESULT Open2(IInStream *stream);
161*f6dc9357SAndroid Build Coastguard Worker 
162*f6dc9357SAndroid Build Coastguard Worker   virtual int GetItem_ExtractInfo(UInt32 index, UInt64 &pos, UInt64 &size) const Z7_override
163*f6dc9357SAndroid Build Coastguard Worker   {
164*f6dc9357SAndroid Build Coastguard Worker     const CPartition &item = _items[index];
165*f6dc9357SAndroid Build Coastguard Worker     pos = item.GetPos(_sectorSizeLog);
166*f6dc9357SAndroid Build Coastguard Worker     size = item.GetSize(_sectorSizeLog);
167*f6dc9357SAndroid Build Coastguard Worker     return NExtract::NOperationResult::kOK;
168*f6dc9357SAndroid Build Coastguard Worker   }
169*f6dc9357SAndroid Build Coastguard Worker };
170*f6dc9357SAndroid Build Coastguard Worker 
171*f6dc9357SAndroid Build Coastguard Worker 
172*f6dc9357SAndroid Build Coastguard Worker HRESULT CHandler::Open2(IInStream *stream)
173*f6dc9357SAndroid Build Coastguard Worker {
174*f6dc9357SAndroid Build Coastguard Worker   const unsigned kBufSize = 2 << 12;
175*f6dc9357SAndroid Build Coastguard Worker   _buffer.Alloc(kBufSize);
176*f6dc9357SAndroid Build Coastguard Worker   RINOK(ReadStream_FALSE(stream, _buffer, kBufSize))
177*f6dc9357SAndroid Build Coastguard Worker   const Byte *buf = _buffer;
178*f6dc9357SAndroid Build Coastguard Worker   if (buf[0x1FE] != 0x55 || buf[0x1FF] != 0xAA)
179*f6dc9357SAndroid Build Coastguard Worker     return S_FALSE;
180*f6dc9357SAndroid Build Coastguard Worker   {
181*f6dc9357SAndroid Build Coastguard Worker     for (unsigned sectorSizeLog = 9;; sectorSizeLog += 3)
182*f6dc9357SAndroid Build Coastguard Worker     {
183*f6dc9357SAndroid Build Coastguard Worker       if (sectorSizeLog > 12)
184*f6dc9357SAndroid Build Coastguard Worker         return S_FALSE;
185*f6dc9357SAndroid Build Coastguard Worker       if (memcmp(buf + ((size_t)1 << sectorSizeLog), k_Signature, k_SignatureSize) == 0)
186*f6dc9357SAndroid Build Coastguard Worker       {
187*f6dc9357SAndroid Build Coastguard Worker         buf += ((size_t)1 << sectorSizeLog);
188*f6dc9357SAndroid Build Coastguard Worker         _sectorSizeLog = sectorSizeLog;
189*f6dc9357SAndroid Build Coastguard Worker         break;
190*f6dc9357SAndroid Build Coastguard Worker       }
191*f6dc9357SAndroid Build Coastguard Worker     }
192*f6dc9357SAndroid Build Coastguard Worker   }
193*f6dc9357SAndroid Build Coastguard Worker   const UInt32 kSectorSize = 1u << _sectorSizeLog;
194*f6dc9357SAndroid Build Coastguard Worker   {
195*f6dc9357SAndroid Build Coastguard Worker     // if (Get32(buf + 8) != 0x10000) return S_FALSE; // revision
196*f6dc9357SAndroid Build Coastguard Worker     const UInt32 headerSize = Get32(buf + 12); // = 0x5C usually
197*f6dc9357SAndroid Build Coastguard Worker     if (headerSize > kSectorSize)
198*f6dc9357SAndroid Build Coastguard Worker       return S_FALSE;
199*f6dc9357SAndroid Build Coastguard Worker     const UInt32 crc = Get32(buf + 0x10);
200*f6dc9357SAndroid Build Coastguard Worker     SetUi32(_buffer + kSectorSize + 0x10, 0)
201*f6dc9357SAndroid Build Coastguard Worker     if (CrcCalc(_buffer + kSectorSize, headerSize) != crc)
202*f6dc9357SAndroid Build Coastguard Worker       return S_FALSE;
203*f6dc9357SAndroid Build Coastguard Worker   }
204*f6dc9357SAndroid Build Coastguard Worker   // UInt32 reserved = Get32(buf + 0x14);
205*f6dc9357SAndroid Build Coastguard Worker   const UInt64 curLba = Get64(buf + 0x18);
206*f6dc9357SAndroid Build Coastguard Worker   if (curLba != 1)
207*f6dc9357SAndroid Build Coastguard Worker     return S_FALSE;
208*f6dc9357SAndroid Build Coastguard Worker   const UInt64 backupLba = Get64(buf + 0x20);
209*f6dc9357SAndroid Build Coastguard Worker   // UInt64 firstUsableLba = Get64(buf + 0x28);
210*f6dc9357SAndroid Build Coastguard Worker   // UInt64 lastUsableLba = Get64(buf + 0x30);
211*f6dc9357SAndroid Build Coastguard Worker   memcpy(Guid, buf + 0x38, 16);
212*f6dc9357SAndroid Build Coastguard Worker   const UInt64 tableLba = Get64(buf + 0x48);
213*f6dc9357SAndroid Build Coastguard Worker   if (tableLba < 2 || (tableLba >> (63 - _sectorSizeLog)) != 0)
214*f6dc9357SAndroid Build Coastguard Worker     return S_FALSE;
215*f6dc9357SAndroid Build Coastguard Worker   const UInt32 numEntries = Get32(buf + 0x50);
216*f6dc9357SAndroid Build Coastguard Worker   if (numEntries > (1 << 16))
217*f6dc9357SAndroid Build Coastguard Worker     return S_FALSE;
218*f6dc9357SAndroid Build Coastguard Worker   const UInt32 entrySize = Get32(buf + 0x54); // = 128 usually
219*f6dc9357SAndroid Build Coastguard Worker   if (entrySize < 128 || entrySize > (1 << 12))
220*f6dc9357SAndroid Build Coastguard Worker     return S_FALSE;
221*f6dc9357SAndroid Build Coastguard Worker   const UInt32 entriesCrc = Get32(buf + 0x58);
222*f6dc9357SAndroid Build Coastguard Worker 
223*f6dc9357SAndroid Build Coastguard Worker   const UInt32 tableSize = entrySize * numEntries;
224*f6dc9357SAndroid Build Coastguard Worker   const UInt32 tableSizeAligned = (tableSize + kSectorSize - 1) & ~(kSectorSize - 1);
225*f6dc9357SAndroid Build Coastguard Worker   _buffer.Alloc(tableSizeAligned);
226*f6dc9357SAndroid Build Coastguard Worker   const UInt64 tableOffset = tableLba * kSectorSize;
227*f6dc9357SAndroid Build Coastguard Worker   RINOK(InStream_SeekSet(stream, tableOffset))
228*f6dc9357SAndroid Build Coastguard Worker   RINOK(ReadStream_FALSE(stream, _buffer, tableSizeAligned))
229*f6dc9357SAndroid Build Coastguard Worker 
230*f6dc9357SAndroid Build Coastguard Worker   if (CrcCalc(_buffer, tableSize) != entriesCrc)
231*f6dc9357SAndroid Build Coastguard Worker     return S_FALSE;
232*f6dc9357SAndroid Build Coastguard Worker 
233*f6dc9357SAndroid Build Coastguard Worker   _totalSize = tableOffset + tableSizeAligned;
234*f6dc9357SAndroid Build Coastguard Worker 
235*f6dc9357SAndroid Build Coastguard Worker   for (UInt32 i = 0; i < numEntries; i++)
236*f6dc9357SAndroid Build Coastguard Worker   {
237*f6dc9357SAndroid Build Coastguard Worker     CPartition item;
238*f6dc9357SAndroid Build Coastguard Worker     item.Parse(_buffer + i * entrySize);
239*f6dc9357SAndroid Build Coastguard Worker     if (item.IsUnused())
240*f6dc9357SAndroid Build Coastguard Worker       continue;
241*f6dc9357SAndroid Build Coastguard Worker     if (item.LastLba < item.FirstLba)
242*f6dc9357SAndroid Build Coastguard Worker       return S_FALSE;
243*f6dc9357SAndroid Build Coastguard Worker     if ((item.LastLba >> (63 - _sectorSizeLog)) != 0)
244*f6dc9357SAndroid Build Coastguard Worker       return S_FALSE;
245*f6dc9357SAndroid Build Coastguard Worker     const UInt64 endPos = item.GetEnd(_sectorSizeLog);
246*f6dc9357SAndroid Build Coastguard Worker     if (_totalSize < endPos)
247*f6dc9357SAndroid Build Coastguard Worker       _totalSize = endPos;
248*f6dc9357SAndroid Build Coastguard Worker     _items.Add(item);
249*f6dc9357SAndroid Build Coastguard Worker   }
250*f6dc9357SAndroid Build Coastguard Worker 
251*f6dc9357SAndroid Build Coastguard Worker   _buffer.Free();
252*f6dc9357SAndroid Build Coastguard Worker   {
253*f6dc9357SAndroid Build Coastguard Worker     if ((backupLba >> (63 - _sectorSizeLog)) != 0)
254*f6dc9357SAndroid Build Coastguard Worker       return S_FALSE;
255*f6dc9357SAndroid Build Coastguard Worker     const UInt64 end = (backupLba + 1) * kSectorSize;
256*f6dc9357SAndroid Build Coastguard Worker     if (_totalSize < end)
257*f6dc9357SAndroid Build Coastguard Worker       _totalSize = end;
258*f6dc9357SAndroid Build Coastguard Worker   }
259*f6dc9357SAndroid Build Coastguard Worker   {
260*f6dc9357SAndroid Build Coastguard Worker     UInt64 fileEnd;
261*f6dc9357SAndroid Build Coastguard Worker     RINOK(InStream_GetSize_SeekToEnd(stream, fileEnd))
262*f6dc9357SAndroid Build Coastguard Worker 
263*f6dc9357SAndroid Build Coastguard Worker     if (_totalSize < fileEnd)
264*f6dc9357SAndroid Build Coastguard Worker     {
265*f6dc9357SAndroid Build Coastguard Worker       const UInt64 rem = fileEnd - _totalSize;
266*f6dc9357SAndroid Build Coastguard Worker       const UInt64 kRemMax = 1 << 22;
267*f6dc9357SAndroid Build Coastguard Worker       if (rem <= kRemMax)
268*f6dc9357SAndroid Build Coastguard Worker       {
269*f6dc9357SAndroid Build Coastguard Worker         RINOK(InStream_SeekSet(stream, _totalSize))
270*f6dc9357SAndroid Build Coastguard Worker         bool areThereNonZeros = false;
271*f6dc9357SAndroid Build Coastguard Worker         UInt64 numZeros = 0;
272*f6dc9357SAndroid Build Coastguard Worker         if (ReadZeroTail(stream, areThereNonZeros, numZeros, kRemMax) == S_OK)
273*f6dc9357SAndroid Build Coastguard Worker           if (!areThereNonZeros)
274*f6dc9357SAndroid Build Coastguard Worker             _totalSize += numZeros;
275*f6dc9357SAndroid Build Coastguard Worker       }
276*f6dc9357SAndroid Build Coastguard Worker     }
277*f6dc9357SAndroid Build Coastguard Worker   }
278*f6dc9357SAndroid Build Coastguard Worker 
279*f6dc9357SAndroid Build Coastguard Worker   return S_OK;
280*f6dc9357SAndroid Build Coastguard Worker }
281*f6dc9357SAndroid Build Coastguard Worker 
282*f6dc9357SAndroid Build Coastguard Worker 
283*f6dc9357SAndroid Build Coastguard Worker Z7_COM7F_IMF(CHandler::Open(IInStream *stream,
284*f6dc9357SAndroid Build Coastguard Worker     const UInt64 * /* maxCheckStartPosition */,
285*f6dc9357SAndroid Build Coastguard Worker     IArchiveOpenCallback * /* openArchiveCallback */))
286*f6dc9357SAndroid Build Coastguard Worker {
287*f6dc9357SAndroid Build Coastguard Worker   COM_TRY_BEGIN
288*f6dc9357SAndroid Build Coastguard Worker   Close();
289*f6dc9357SAndroid Build Coastguard Worker   RINOK(Open2(stream))
290*f6dc9357SAndroid Build Coastguard Worker   _stream = stream;
291*f6dc9357SAndroid Build Coastguard Worker 
292*f6dc9357SAndroid Build Coastguard Worker   FOR_VECTOR (fileIndex, _items)
293*f6dc9357SAndroid Build Coastguard Worker   {
294*f6dc9357SAndroid Build Coastguard Worker     CPartition &item = _items[fileIndex];
295*f6dc9357SAndroid Build Coastguard Worker     const int typeIndex = FindPartType(item.Type);
296*f6dc9357SAndroid Build Coastguard Worker     if (typeIndex < 0)
297*f6dc9357SAndroid Build Coastguard Worker       continue;
298*f6dc9357SAndroid Build Coastguard Worker     const CPartType &t = kPartTypes[(unsigned)typeIndex];
299*f6dc9357SAndroid Build Coastguard Worker     if (t.Ext)
300*f6dc9357SAndroid Build Coastguard Worker     {
301*f6dc9357SAndroid Build Coastguard Worker       item.Ext = t.Ext;
302*f6dc9357SAndroid Build Coastguard Worker       continue;
303*f6dc9357SAndroid Build Coastguard Worker     }
304*f6dc9357SAndroid Build Coastguard Worker     if (t.Type && IsString1PrefixedByString2_NoCase_Ascii(t.Type, "Windows"))
305*f6dc9357SAndroid Build Coastguard Worker     {
306*f6dc9357SAndroid Build Coastguard Worker       CMyComPtr<ISequentialInStream> inStream;
307*f6dc9357SAndroid Build Coastguard Worker       if (
308*f6dc9357SAndroid Build Coastguard Worker           // ((IInArchiveGetStream *)this)->
309*f6dc9357SAndroid Build Coastguard Worker           GetStream(fileIndex, &inStream) == S_OK && inStream)
310*f6dc9357SAndroid Build Coastguard Worker       {
311*f6dc9357SAndroid Build Coastguard Worker         const char *fs = NMbr::GetFileSystem(inStream, item.GetSize(_sectorSizeLog));
312*f6dc9357SAndroid Build Coastguard Worker         if (fs)
313*f6dc9357SAndroid Build Coastguard Worker           item.Ext = fs;
314*f6dc9357SAndroid Build Coastguard Worker       }
315*f6dc9357SAndroid Build Coastguard Worker     }
316*f6dc9357SAndroid Build Coastguard Worker   }
317*f6dc9357SAndroid Build Coastguard Worker 
318*f6dc9357SAndroid Build Coastguard Worker   return S_OK;
319*f6dc9357SAndroid Build Coastguard Worker   COM_TRY_END
320*f6dc9357SAndroid Build Coastguard Worker }
321*f6dc9357SAndroid Build Coastguard Worker 
322*f6dc9357SAndroid Build Coastguard Worker Z7_COM7F_IMF(CHandler::Close())
323*f6dc9357SAndroid Build Coastguard Worker {
324*f6dc9357SAndroid Build Coastguard Worker   _sectorSizeLog = 0;
325*f6dc9357SAndroid Build Coastguard Worker   _totalSize = 0;
326*f6dc9357SAndroid Build Coastguard Worker   memset(Guid, 0, sizeof(Guid));
327*f6dc9357SAndroid Build Coastguard Worker   _items.Clear();
328*f6dc9357SAndroid Build Coastguard Worker   _stream.Release();
329*f6dc9357SAndroid Build Coastguard Worker   return S_OK;
330*f6dc9357SAndroid Build Coastguard Worker }
331*f6dc9357SAndroid Build Coastguard Worker 
332*f6dc9357SAndroid Build Coastguard Worker static const Byte kProps[] =
333*f6dc9357SAndroid Build Coastguard Worker {
334*f6dc9357SAndroid Build Coastguard Worker   kpidPath,
335*f6dc9357SAndroid Build Coastguard Worker   kpidSize,
336*f6dc9357SAndroid Build Coastguard Worker   kpidFileSystem,
337*f6dc9357SAndroid Build Coastguard Worker   kpidCharacts,
338*f6dc9357SAndroid Build Coastguard Worker   kpidOffset,
339*f6dc9357SAndroid Build Coastguard Worker   kpidId
340*f6dc9357SAndroid Build Coastguard Worker };
341*f6dc9357SAndroid Build Coastguard Worker 
342*f6dc9357SAndroid Build Coastguard Worker static const Byte kArcProps[] =
343*f6dc9357SAndroid Build Coastguard Worker {
344*f6dc9357SAndroid Build Coastguard Worker   kpidSectorSize,
345*f6dc9357SAndroid Build Coastguard Worker   kpidId
346*f6dc9357SAndroid Build Coastguard Worker };
347*f6dc9357SAndroid Build Coastguard Worker 
348*f6dc9357SAndroid Build Coastguard Worker IMP_IInArchive_Props
349*f6dc9357SAndroid Build Coastguard Worker IMP_IInArchive_ArcProps
350*f6dc9357SAndroid Build Coastguard Worker 
351*f6dc9357SAndroid Build Coastguard Worker Z7_COM7F_IMF(CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value))
352*f6dc9357SAndroid Build Coastguard Worker {
353*f6dc9357SAndroid Build Coastguard Worker   COM_TRY_BEGIN
354*f6dc9357SAndroid Build Coastguard Worker   NCOM::CPropVariant prop;
355*f6dc9357SAndroid Build Coastguard Worker   switch (propID)
356*f6dc9357SAndroid Build Coastguard Worker   {
357*f6dc9357SAndroid Build Coastguard Worker     case kpidMainSubfile:
358*f6dc9357SAndroid Build Coastguard Worker     {
359*f6dc9357SAndroid Build Coastguard Worker       if (_items.Size() == 1)
360*f6dc9357SAndroid Build Coastguard Worker         prop = (UInt32)0;
361*f6dc9357SAndroid Build Coastguard Worker       break;
362*f6dc9357SAndroid Build Coastguard Worker     }
363*f6dc9357SAndroid Build Coastguard Worker     case kpidPhySize: prop = _totalSize; break;
364*f6dc9357SAndroid Build Coastguard Worker     case kpidSectorSize: prop = (UInt32)((UInt32)1 << _sectorSizeLog); break;
365*f6dc9357SAndroid Build Coastguard Worker     case kpidId:
366*f6dc9357SAndroid Build Coastguard Worker     {
367*f6dc9357SAndroid Build Coastguard Worker       char s[48];
368*f6dc9357SAndroid Build Coastguard Worker       RawLeGuidToString_Upper(Guid, s);
369*f6dc9357SAndroid Build Coastguard Worker       prop = s;
370*f6dc9357SAndroid Build Coastguard Worker       break;
371*f6dc9357SAndroid Build Coastguard Worker     }
372*f6dc9357SAndroid Build Coastguard Worker   }
373*f6dc9357SAndroid Build Coastguard Worker   prop.Detach(value);
374*f6dc9357SAndroid Build Coastguard Worker   return S_OK;
375*f6dc9357SAndroid Build Coastguard Worker   COM_TRY_END
376*f6dc9357SAndroid Build Coastguard Worker }
377*f6dc9357SAndroid Build Coastguard Worker 
378*f6dc9357SAndroid Build Coastguard Worker Z7_COM7F_IMF(CHandler::GetNumberOfItems(UInt32 *numItems))
379*f6dc9357SAndroid Build Coastguard Worker {
380*f6dc9357SAndroid Build Coastguard Worker   *numItems = _items.Size();
381*f6dc9357SAndroid Build Coastguard Worker   return S_OK;
382*f6dc9357SAndroid Build Coastguard Worker }
383*f6dc9357SAndroid Build Coastguard Worker 
384*f6dc9357SAndroid Build Coastguard Worker Z7_COM7F_IMF(CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *value))
385*f6dc9357SAndroid Build Coastguard Worker {
386*f6dc9357SAndroid Build Coastguard Worker   COM_TRY_BEGIN
387*f6dc9357SAndroid Build Coastguard Worker   NCOM::CPropVariant prop;
388*f6dc9357SAndroid Build Coastguard Worker 
389*f6dc9357SAndroid Build Coastguard Worker   const CPartition &item = _items[index];
390*f6dc9357SAndroid Build Coastguard Worker 
391*f6dc9357SAndroid Build Coastguard Worker   switch (propID)
392*f6dc9357SAndroid Build Coastguard Worker   {
393*f6dc9357SAndroid Build Coastguard Worker     case kpidPath:
394*f6dc9357SAndroid Build Coastguard Worker     {
395*f6dc9357SAndroid Build Coastguard Worker       // Windows BDP partitions can have identical names.
396*f6dc9357SAndroid Build Coastguard Worker       // So we add the partition number at front
397*f6dc9357SAndroid Build Coastguard Worker       UString s;
398*f6dc9357SAndroid Build Coastguard Worker       s.Add_UInt32(index);
399*f6dc9357SAndroid Build Coastguard Worker       {
400*f6dc9357SAndroid Build Coastguard Worker         UString s2;
401*f6dc9357SAndroid Build Coastguard Worker         for (unsigned i = 0; i < kNameLen; i++)
402*f6dc9357SAndroid Build Coastguard Worker         {
403*f6dc9357SAndroid Build Coastguard Worker           wchar_t c = (wchar_t)Get16(item.Name + i * 2);
404*f6dc9357SAndroid Build Coastguard Worker           if (c == 0)
405*f6dc9357SAndroid Build Coastguard Worker             break;
406*f6dc9357SAndroid Build Coastguard Worker           s2 += c;
407*f6dc9357SAndroid Build Coastguard Worker         }
408*f6dc9357SAndroid Build Coastguard Worker         if (!s2.IsEmpty())
409*f6dc9357SAndroid Build Coastguard Worker         {
410*f6dc9357SAndroid Build Coastguard Worker           s.Add_Dot();
411*f6dc9357SAndroid Build Coastguard Worker           s += s2;
412*f6dc9357SAndroid Build Coastguard Worker         }
413*f6dc9357SAndroid Build Coastguard Worker       }
414*f6dc9357SAndroid Build Coastguard Worker       {
415*f6dc9357SAndroid Build Coastguard Worker         s.Add_Dot();
416*f6dc9357SAndroid Build Coastguard Worker         if (item.Ext)
417*f6dc9357SAndroid Build Coastguard Worker         {
418*f6dc9357SAndroid Build Coastguard Worker           AString fs (item.Ext);
419*f6dc9357SAndroid Build Coastguard Worker           fs.MakeLower_Ascii();
420*f6dc9357SAndroid Build Coastguard Worker           s += fs;
421*f6dc9357SAndroid Build Coastguard Worker         }
422*f6dc9357SAndroid Build Coastguard Worker         else
423*f6dc9357SAndroid Build Coastguard Worker           s += "img";
424*f6dc9357SAndroid Build Coastguard Worker       }
425*f6dc9357SAndroid Build Coastguard Worker       prop = s;
426*f6dc9357SAndroid Build Coastguard Worker       break;
427*f6dc9357SAndroid Build Coastguard Worker     }
428*f6dc9357SAndroid Build Coastguard Worker 
429*f6dc9357SAndroid Build Coastguard Worker     case kpidSize:
430*f6dc9357SAndroid Build Coastguard Worker     case kpidPackSize: prop = item.GetSize(_sectorSizeLog); break;
431*f6dc9357SAndroid Build Coastguard Worker     case kpidOffset: prop = item.GetPos(_sectorSizeLog); break;
432*f6dc9357SAndroid Build Coastguard Worker 
433*f6dc9357SAndroid Build Coastguard Worker     case kpidFileSystem:
434*f6dc9357SAndroid Build Coastguard Worker     {
435*f6dc9357SAndroid Build Coastguard Worker       char s[48];
436*f6dc9357SAndroid Build Coastguard Worker       const char *res;
437*f6dc9357SAndroid Build Coastguard Worker       const int typeIndex = FindPartType(item.Type);
438*f6dc9357SAndroid Build Coastguard Worker       if (typeIndex >= 0 && kPartTypes[(unsigned)typeIndex].Type)
439*f6dc9357SAndroid Build Coastguard Worker         res = kPartTypes[(unsigned)typeIndex].Type;
440*f6dc9357SAndroid Build Coastguard Worker       else
441*f6dc9357SAndroid Build Coastguard Worker       {
442*f6dc9357SAndroid Build Coastguard Worker         RawLeGuidToString_Upper(item.Type, s);
443*f6dc9357SAndroid Build Coastguard Worker         res = s;
444*f6dc9357SAndroid Build Coastguard Worker       }
445*f6dc9357SAndroid Build Coastguard Worker       prop = res;
446*f6dc9357SAndroid Build Coastguard Worker       break;
447*f6dc9357SAndroid Build Coastguard Worker     }
448*f6dc9357SAndroid Build Coastguard Worker 
449*f6dc9357SAndroid Build Coastguard Worker     case kpidId:
450*f6dc9357SAndroid Build Coastguard Worker     {
451*f6dc9357SAndroid Build Coastguard Worker       char s[48];
452*f6dc9357SAndroid Build Coastguard Worker       RawLeGuidToString_Upper(item.Id, s);
453*f6dc9357SAndroid Build Coastguard Worker       prop = s;
454*f6dc9357SAndroid Build Coastguard Worker       break;
455*f6dc9357SAndroid Build Coastguard Worker     }
456*f6dc9357SAndroid Build Coastguard Worker 
457*f6dc9357SAndroid Build Coastguard Worker     case kpidCharacts: FLAGS64_TO_PROP(g_PartitionFlags, item.Flags, prop); break;
458*f6dc9357SAndroid Build Coastguard Worker   }
459*f6dc9357SAndroid Build Coastguard Worker 
460*f6dc9357SAndroid Build Coastguard Worker   prop.Detach(value);
461*f6dc9357SAndroid Build Coastguard Worker   return S_OK;
462*f6dc9357SAndroid Build Coastguard Worker   COM_TRY_END
463*f6dc9357SAndroid Build Coastguard Worker }
464*f6dc9357SAndroid Build Coastguard Worker 
465*f6dc9357SAndroid Build Coastguard Worker // we suppport signature only for 512-bytes sector.
466*f6dc9357SAndroid Build Coastguard Worker REGISTER_ARC_I(
467*f6dc9357SAndroid Build Coastguard Worker   "GPT", "gpt mbr", NULL, 0xCB,
468*f6dc9357SAndroid Build Coastguard Worker   k_Signature,
469*f6dc9357SAndroid Build Coastguard Worker   1 << 9,
470*f6dc9357SAndroid Build Coastguard Worker   0,
471*f6dc9357SAndroid Build Coastguard Worker   NULL)
472*f6dc9357SAndroid Build Coastguard Worker 
473*f6dc9357SAndroid Build Coastguard Worker }}
474