1*f6dc9357SAndroid Build Coastguard Worker // LpHandler.cpp
2*f6dc9357SAndroid Build Coastguard Worker
3*f6dc9357SAndroid Build Coastguard Worker #include "StdAfx.h"
4*f6dc9357SAndroid Build Coastguard Worker
5*f6dc9357SAndroid Build Coastguard Worker #include "../../../C/CpuArch.h"
6*f6dc9357SAndroid Build Coastguard Worker #include "../../../C/Sha256.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/LimitedStreams.h"
15*f6dc9357SAndroid Build Coastguard Worker #include "../Common/ProgressUtils.h"
16*f6dc9357SAndroid Build Coastguard Worker #include "../Common/RegisterArc.h"
17*f6dc9357SAndroid Build Coastguard Worker #include "../Common/StreamUtils.h"
18*f6dc9357SAndroid Build Coastguard Worker
19*f6dc9357SAndroid Build Coastguard Worker #include "../Compress/CopyCoder.h"
20*f6dc9357SAndroid Build Coastguard Worker
21*f6dc9357SAndroid Build Coastguard Worker #define Get16(p) GetUi16(p)
22*f6dc9357SAndroid Build Coastguard Worker #define Get32(p) GetUi32(p)
23*f6dc9357SAndroid Build Coastguard Worker #define Get64(p) GetUi64(p)
24*f6dc9357SAndroid Build Coastguard Worker
25*f6dc9357SAndroid Build Coastguard Worker #define G16(_offs_, dest) dest = Get16(p + (_offs_));
26*f6dc9357SAndroid Build Coastguard Worker #define G32(_offs_, dest) dest = Get32(p + (_offs_));
27*f6dc9357SAndroid Build Coastguard Worker #define G64(_offs_, dest) dest = Get64(p + (_offs_));
28*f6dc9357SAndroid Build Coastguard Worker
29*f6dc9357SAndroid Build Coastguard Worker using namespace NWindows;
30*f6dc9357SAndroid Build Coastguard Worker
31*f6dc9357SAndroid Build Coastguard Worker namespace NArchive {
32*f6dc9357SAndroid Build Coastguard Worker
33*f6dc9357SAndroid Build Coastguard Worker namespace NExt {
34*f6dc9357SAndroid Build Coastguard Worker API_FUNC_IsArc IsArc_Ext_PhySize(const Byte *p, size_t size, UInt64 *phySize);
35*f6dc9357SAndroid Build Coastguard Worker }
36*f6dc9357SAndroid Build Coastguard Worker
37*f6dc9357SAndroid Build Coastguard Worker namespace NLp {
38*f6dc9357SAndroid Build Coastguard Worker
39*f6dc9357SAndroid Build Coastguard Worker /*
40*f6dc9357SAndroid Build Coastguard Worker Android 10+ use Android's Dynamic Partitions to allow the
41*f6dc9357SAndroid Build Coastguard Worker different read-only system partitions (e.g. system, vendor, product)
42*f6dc9357SAndroid Build Coastguard Worker to share the same pool of storage space (as LVM in Linux).
43*f6dc9357SAndroid Build Coastguard Worker Name for partition: "super" (for GPT) or "super.img" (for file).
44*f6dc9357SAndroid Build Coastguard Worker Dynamic Partition Tools: lpmake
45*f6dc9357SAndroid Build Coastguard Worker All partitions that are A/B-ed should be named as follows (slots are always named a, b, etc.):
46*f6dc9357SAndroid Build Coastguard Worker boot_a, boot_b, system_a, system_b, vendor_a, vendor_b.
47*f6dc9357SAndroid Build Coastguard Worker */
48*f6dc9357SAndroid Build Coastguard Worker
49*f6dc9357SAndroid Build Coastguard Worker #define LP_METADATA_MAJOR_VERSION 10
50*f6dc9357SAndroid Build Coastguard Worker // #define LP_METADATA_MINOR_VERSION_MIN 0
51*f6dc9357SAndroid Build Coastguard Worker // #define LP_METADATA_MINOR_VERSION_MAX 2
52*f6dc9357SAndroid Build Coastguard Worker
53*f6dc9357SAndroid Build Coastguard Worker // #define LP_SECTOR_SIZE 512
54*f6dc9357SAndroid Build Coastguard Worker static const unsigned kSectorSizeLog = 9;
55*f6dc9357SAndroid Build Coastguard Worker
56*f6dc9357SAndroid Build Coastguard Worker /* Amount of space reserved at the start of every super partition to avoid
57*f6dc9357SAndroid Build Coastguard Worker * creating an accidental boot sector. */
58*f6dc9357SAndroid Build Coastguard Worker #define LP_PARTITION_RESERVED_BYTES 4096
59*f6dc9357SAndroid Build Coastguard Worker #define LP_METADATA_GEOMETRY_SIZE 4096
60*f6dc9357SAndroid Build Coastguard Worker #define LP_METADATA_HEADER_MAGIC 0x414C5030
61*f6dc9357SAndroid Build Coastguard Worker
62*f6dc9357SAndroid Build Coastguard Worker static const unsigned k_SignatureSize = 8;
63*f6dc9357SAndroid Build Coastguard Worker static const Byte k_Signature[k_SignatureSize] =
64*f6dc9357SAndroid Build Coastguard Worker { 0x67, 0x44, 0x6c, 0x61, 0x34, 0, 0, 0 };
65*f6dc9357SAndroid Build Coastguard Worker
66*f6dc9357SAndroid Build Coastguard Worker // The length (36) is the same as the maximum length of a GPT partition name.
67*f6dc9357SAndroid Build Coastguard Worker static const unsigned kNameLen = 36;
68*f6dc9357SAndroid Build Coastguard Worker
AddName36ToString(AString & s,const char * name,bool strictConvert)69*f6dc9357SAndroid Build Coastguard Worker static void AddName36ToString(AString &s, const char *name, bool strictConvert)
70*f6dc9357SAndroid Build Coastguard Worker {
71*f6dc9357SAndroid Build Coastguard Worker for (unsigned i = 0; i < kNameLen; i++)
72*f6dc9357SAndroid Build Coastguard Worker {
73*f6dc9357SAndroid Build Coastguard Worker char c = name[i];
74*f6dc9357SAndroid Build Coastguard Worker if (c == 0)
75*f6dc9357SAndroid Build Coastguard Worker return;
76*f6dc9357SAndroid Build Coastguard Worker if (strictConvert && c < 32)
77*f6dc9357SAndroid Build Coastguard Worker c = '_';
78*f6dc9357SAndroid Build Coastguard Worker s += c;
79*f6dc9357SAndroid Build Coastguard Worker }
80*f6dc9357SAndroid Build Coastguard Worker }
81*f6dc9357SAndroid Build Coastguard Worker
82*f6dc9357SAndroid Build Coastguard Worker
83*f6dc9357SAndroid Build Coastguard Worker static const unsigned k_Geometry_Size = 0x34;
84*f6dc9357SAndroid Build Coastguard Worker
85*f6dc9357SAndroid Build Coastguard Worker // LpMetadataGeometry
86*f6dc9357SAndroid Build Coastguard Worker struct CGeometry
87*f6dc9357SAndroid Build Coastguard Worker {
88*f6dc9357SAndroid Build Coastguard Worker // UInt32 magic;
89*f6dc9357SAndroid Build Coastguard Worker // UInt32 struct_size;
90*f6dc9357SAndroid Build Coastguard Worker // Byte checksum[32]; /* SHA256 checksum of this struct, with this field set to 0. */
91*f6dc9357SAndroid Build Coastguard Worker
92*f6dc9357SAndroid Build Coastguard Worker /* Maximum amount of space a single copy of the metadata can use,
93*f6dc9357SAndroid Build Coastguard Worker a multiple of LP_SECTOR_SIZE. */
94*f6dc9357SAndroid Build Coastguard Worker UInt32 metadata_max_size;
95*f6dc9357SAndroid Build Coastguard Worker
96*f6dc9357SAndroid Build Coastguard Worker /* Number of copies of the metadata to keep.
97*f6dc9357SAndroid Build Coastguard Worker For Non-A/B: 1, For A/B: 2, for A/B/C: 3.
98*f6dc9357SAndroid Build Coastguard Worker A backup copy of each slot is kept */
99*f6dc9357SAndroid Build Coastguard Worker UInt32 metadata_slot_count;
100*f6dc9357SAndroid Build Coastguard Worker
101*f6dc9357SAndroid Build Coastguard Worker /* minimal alignment for partition and extent sizes, a multiple of LP_SECTOR_SIZE. */
102*f6dc9357SAndroid Build Coastguard Worker UInt32 logical_block_size;
103*f6dc9357SAndroid Build Coastguard Worker
ParseNArchive::NLp::CGeometry104*f6dc9357SAndroid Build Coastguard Worker bool Parse(const Byte *p)
105*f6dc9357SAndroid Build Coastguard Worker {
106*f6dc9357SAndroid Build Coastguard Worker G32 (40, metadata_max_size)
107*f6dc9357SAndroid Build Coastguard Worker G32 (44, metadata_slot_count)
108*f6dc9357SAndroid Build Coastguard Worker G32 (48, logical_block_size)
109*f6dc9357SAndroid Build Coastguard Worker if (metadata_slot_count == 0 || metadata_slot_count >= ((UInt32)1 << 20))
110*f6dc9357SAndroid Build Coastguard Worker return false;
111*f6dc9357SAndroid Build Coastguard Worker if (metadata_max_size == 0)
112*f6dc9357SAndroid Build Coastguard Worker return false;
113*f6dc9357SAndroid Build Coastguard Worker if ((metadata_max_size & (((UInt32)1 << kSectorSizeLog) - 1)) != 0)
114*f6dc9357SAndroid Build Coastguard Worker return false;
115*f6dc9357SAndroid Build Coastguard Worker return true;
116*f6dc9357SAndroid Build Coastguard Worker }
117*f6dc9357SAndroid Build Coastguard Worker
GetTotalMetadataSizeNArchive::NLp::CGeometry118*f6dc9357SAndroid Build Coastguard Worker UInt64 GetTotalMetadataSize() const
119*f6dc9357SAndroid Build Coastguard Worker {
120*f6dc9357SAndroid Build Coastguard Worker // there are 2 copies of GEOMETRY and METADATA slots
121*f6dc9357SAndroid Build Coastguard Worker return LP_PARTITION_RESERVED_BYTES +
122*f6dc9357SAndroid Build Coastguard Worker LP_METADATA_GEOMETRY_SIZE * 2 +
123*f6dc9357SAndroid Build Coastguard Worker ((UInt64)metadata_max_size * metadata_slot_count) * 2;
124*f6dc9357SAndroid Build Coastguard Worker }
125*f6dc9357SAndroid Build Coastguard Worker };
126*f6dc9357SAndroid Build Coastguard Worker
127*f6dc9357SAndroid Build Coastguard Worker
128*f6dc9357SAndroid Build Coastguard Worker
129*f6dc9357SAndroid Build Coastguard Worker // LpMetadataTableDescriptor
130*f6dc9357SAndroid Build Coastguard Worker struct CDescriptor
131*f6dc9357SAndroid Build Coastguard Worker {
132*f6dc9357SAndroid Build Coastguard Worker UInt32 offset; /* Location of the table, relative to end of the metadata header. */
133*f6dc9357SAndroid Build Coastguard Worker UInt32 num_entries; /* Number of entries in the table. */
134*f6dc9357SAndroid Build Coastguard Worker UInt32 entry_size; /* Size of each entry in the table, in bytes. */
135*f6dc9357SAndroid Build Coastguard Worker
ParseNArchive::NLp::CDescriptor136*f6dc9357SAndroid Build Coastguard Worker void Parse(const Byte *p)
137*f6dc9357SAndroid Build Coastguard Worker {
138*f6dc9357SAndroid Build Coastguard Worker G32 (0, offset)
139*f6dc9357SAndroid Build Coastguard Worker G32 (4, num_entries)
140*f6dc9357SAndroid Build Coastguard Worker G32 (8, entry_size)
141*f6dc9357SAndroid Build Coastguard Worker }
142*f6dc9357SAndroid Build Coastguard Worker
CheckLimitsNArchive::NLp::CDescriptor143*f6dc9357SAndroid Build Coastguard Worker bool CheckLimits(UInt32 limit) const
144*f6dc9357SAndroid Build Coastguard Worker {
145*f6dc9357SAndroid Build Coastguard Worker if (entry_size == 0)
146*f6dc9357SAndroid Build Coastguard Worker return false;
147*f6dc9357SAndroid Build Coastguard Worker const UInt32 size = num_entries * entry_size;
148*f6dc9357SAndroid Build Coastguard Worker if (size / entry_size != num_entries)
149*f6dc9357SAndroid Build Coastguard Worker return false;
150*f6dc9357SAndroid Build Coastguard Worker if (offset > limit || limit - offset < size)
151*f6dc9357SAndroid Build Coastguard Worker return false;
152*f6dc9357SAndroid Build Coastguard Worker return true;
153*f6dc9357SAndroid Build Coastguard Worker }
154*f6dc9357SAndroid Build Coastguard Worker };
155*f6dc9357SAndroid Build Coastguard Worker
156*f6dc9357SAndroid Build Coastguard Worker
157*f6dc9357SAndroid Build Coastguard Worker // #define LP_PARTITION_ATTR_NONE 0x0
158*f6dc9357SAndroid Build Coastguard Worker // #define LP_PARTITION_ATTR_READONLY (1 << 0)
159*f6dc9357SAndroid Build Coastguard Worker
160*f6dc9357SAndroid Build Coastguard Worker /* This flag is only intended to be used with super_empty.img and super.img on
161*f6dc9357SAndroid Build Coastguard Worker * retrofit devices. On these devices there are A and B super partitions, and
162*f6dc9357SAndroid Build Coastguard Worker * we don't know ahead of time which slot the image will be applied to.
163*f6dc9357SAndroid Build Coastguard Worker *
164*f6dc9357SAndroid Build Coastguard Worker * If set, the partition name needs a slot suffix applied. The slot suffix is
165*f6dc9357SAndroid Build Coastguard Worker * determined by the metadata slot number (0 = _a, 1 = _b).
166*f6dc9357SAndroid Build Coastguard Worker */
167*f6dc9357SAndroid Build Coastguard Worker // #define LP_PARTITION_ATTR_SLOT_SUFFIXED (1 << 1)
168*f6dc9357SAndroid Build Coastguard Worker
169*f6dc9357SAndroid Build Coastguard Worker /* This flag is applied automatically when using MetadataBuilder::NewForUpdate.
170*f6dc9357SAndroid Build Coastguard Worker * It signals that the partition was created (or modified) for a snapshot-based
171*f6dc9357SAndroid Build Coastguard Worker * update. If this flag is not present, the partition was likely flashed via
172*f6dc9357SAndroid Build Coastguard Worker * fastboot.
173*f6dc9357SAndroid Build Coastguard Worker */
174*f6dc9357SAndroid Build Coastguard Worker // #define LP_PARTITION_ATTR_UPDATED (1 << 2)
175*f6dc9357SAndroid Build Coastguard Worker
176*f6dc9357SAndroid Build Coastguard Worker /* This flag marks a partition as disabled. It should not be used or mapped. */
177*f6dc9357SAndroid Build Coastguard Worker // #define LP_PARTITION_ATTR_DISABLED (1 << 3)
178*f6dc9357SAndroid Build Coastguard Worker
179*f6dc9357SAndroid Build Coastguard Worker static const char * const g_PartitionAttr[] =
180*f6dc9357SAndroid Build Coastguard Worker {
181*f6dc9357SAndroid Build Coastguard Worker "READONLY"
182*f6dc9357SAndroid Build Coastguard Worker , "SLOT_SUFFIXED"
183*f6dc9357SAndroid Build Coastguard Worker , "UPDATED"
184*f6dc9357SAndroid Build Coastguard Worker , "DISABLED"
185*f6dc9357SAndroid Build Coastguard Worker };
186*f6dc9357SAndroid Build Coastguard Worker
187*f6dc9357SAndroid Build Coastguard Worker static unsigned const k_MetaPartition_Size = 52;
188*f6dc9357SAndroid Build Coastguard Worker
189*f6dc9357SAndroid Build Coastguard Worker // LpMetadataPartition
190*f6dc9357SAndroid Build Coastguard Worker struct CPartition
191*f6dc9357SAndroid Build Coastguard Worker {
192*f6dc9357SAndroid Build Coastguard Worker /* ASCII characters: alphanumeric or _. at least one ASCII character,
193*f6dc9357SAndroid Build Coastguard Worker (name) must be unique across all partition names. */
194*f6dc9357SAndroid Build Coastguard Worker char name[kNameLen];
195*f6dc9357SAndroid Build Coastguard Worker
196*f6dc9357SAndroid Build Coastguard Worker UInt32 attributes; /* (LP_PARTITION_ATTR_*). */
197*f6dc9357SAndroid Build Coastguard Worker
198*f6dc9357SAndroid Build Coastguard Worker /* Index of the first extent owned by this partition. The extent will
199*f6dc9357SAndroid Build Coastguard Worker * start at logical sector 0. Gaps between extents are not allowed. */
200*f6dc9357SAndroid Build Coastguard Worker UInt32 first_extent_index;
201*f6dc9357SAndroid Build Coastguard Worker
202*f6dc9357SAndroid Build Coastguard Worker /* Number of extents in the partition. Every partition must have at least one extent. */
203*f6dc9357SAndroid Build Coastguard Worker UInt32 num_extents;
204*f6dc9357SAndroid Build Coastguard Worker
205*f6dc9357SAndroid Build Coastguard Worker /* Group this partition belongs to. */
206*f6dc9357SAndroid Build Coastguard Worker UInt32 group_index;
207*f6dc9357SAndroid Build Coastguard Worker
ParseNArchive::NLp::CPartition208*f6dc9357SAndroid Build Coastguard Worker void Parse(const Byte *p)
209*f6dc9357SAndroid Build Coastguard Worker {
210*f6dc9357SAndroid Build Coastguard Worker memcpy(name, p, kNameLen);
211*f6dc9357SAndroid Build Coastguard Worker G32 (36, attributes)
212*f6dc9357SAndroid Build Coastguard Worker G32 (40, first_extent_index)
213*f6dc9357SAndroid Build Coastguard Worker G32 (44, num_extents)
214*f6dc9357SAndroid Build Coastguard Worker G32 (48, group_index)
215*f6dc9357SAndroid Build Coastguard Worker }
216*f6dc9357SAndroid Build Coastguard Worker
217*f6dc9357SAndroid Build Coastguard Worker // calced properties:
218*f6dc9357SAndroid Build Coastguard Worker UInt32 MethodsMask;
219*f6dc9357SAndroid Build Coastguard Worker UInt64 NumSectors;
220*f6dc9357SAndroid Build Coastguard Worker UInt64 NumSectors_Pack;
221*f6dc9357SAndroid Build Coastguard Worker const char *Ext;
222*f6dc9357SAndroid Build Coastguard Worker
GetSizeNArchive::NLp::CPartition223*f6dc9357SAndroid Build Coastguard Worker UInt64 GetSize() const { return NumSectors << kSectorSizeLog; }
GetPackSizeNArchive::NLp::CPartition224*f6dc9357SAndroid Build Coastguard Worker UInt64 GetPackSize() const { return NumSectors_Pack << kSectorSizeLog; }
225*f6dc9357SAndroid Build Coastguard Worker
CPartitionNArchive::NLp::CPartition226*f6dc9357SAndroid Build Coastguard Worker CPartition():
227*f6dc9357SAndroid Build Coastguard Worker MethodsMask(0),
228*f6dc9357SAndroid Build Coastguard Worker NumSectors(0),
229*f6dc9357SAndroid Build Coastguard Worker NumSectors_Pack(0),
230*f6dc9357SAndroid Build Coastguard Worker Ext(NULL)
231*f6dc9357SAndroid Build Coastguard Worker {}
232*f6dc9357SAndroid Build Coastguard Worker };
233*f6dc9357SAndroid Build Coastguard Worker
234*f6dc9357SAndroid Build Coastguard Worker
235*f6dc9357SAndroid Build Coastguard Worker
236*f6dc9357SAndroid Build Coastguard Worker
237*f6dc9357SAndroid Build Coastguard Worker #define LP_TARGET_TYPE_LINEAR 0
238*f6dc9357SAndroid Build Coastguard Worker /* This extent is a dm-zero target. The index is ignored and must be 0. */
239*f6dc9357SAndroid Build Coastguard Worker #define LP_TARGET_TYPE_ZERO 1
240*f6dc9357SAndroid Build Coastguard Worker
241*f6dc9357SAndroid Build Coastguard Worker static const char * const g_Methods[] =
242*f6dc9357SAndroid Build Coastguard Worker {
243*f6dc9357SAndroid Build Coastguard Worker "RAW" // "LINEAR"
244*f6dc9357SAndroid Build Coastguard Worker , "ZERO"
245*f6dc9357SAndroid Build Coastguard Worker };
246*f6dc9357SAndroid Build Coastguard Worker
247*f6dc9357SAndroid Build Coastguard Worker static unsigned const k_MetaExtent_Size = 24;
248*f6dc9357SAndroid Build Coastguard Worker
249*f6dc9357SAndroid Build Coastguard Worker // LpMetadataExtent
250*f6dc9357SAndroid Build Coastguard Worker struct CExtent
251*f6dc9357SAndroid Build Coastguard Worker {
252*f6dc9357SAndroid Build Coastguard Worker UInt64 num_sectors; /* Length in 512-byte sectors. */
253*f6dc9357SAndroid Build Coastguard Worker UInt32 target_type; /* Target type for device-mapper (LP_TARGET_TYPE_*). */
254*f6dc9357SAndroid Build Coastguard Worker
255*f6dc9357SAndroid Build Coastguard Worker /* for LINEAR: The sector on the physical partition that this extent maps onto.
256*f6dc9357SAndroid Build Coastguard Worker for ZERO: must be 0. */
257*f6dc9357SAndroid Build Coastguard Worker UInt64 target_data;
258*f6dc9357SAndroid Build Coastguard Worker
259*f6dc9357SAndroid Build Coastguard Worker /* for LINEAR: index into the block devices table.
260*f6dc9357SAndroid Build Coastguard Worker for ZERO: must be 0. */
261*f6dc9357SAndroid Build Coastguard Worker UInt32 target_source;
262*f6dc9357SAndroid Build Coastguard Worker
IsRAWNArchive::NLp::CExtent263*f6dc9357SAndroid Build Coastguard Worker bool IsRAW() const { return target_type == LP_TARGET_TYPE_LINEAR; }
264*f6dc9357SAndroid Build Coastguard Worker
ParseNArchive::NLp::CExtent265*f6dc9357SAndroid Build Coastguard Worker void Parse(const Byte *p)
266*f6dc9357SAndroid Build Coastguard Worker {
267*f6dc9357SAndroid Build Coastguard Worker G64 (0, num_sectors)
268*f6dc9357SAndroid Build Coastguard Worker G32 (8, target_type)
269*f6dc9357SAndroid Build Coastguard Worker G64 (12, target_data)
270*f6dc9357SAndroid Build Coastguard Worker G32 (20, target_source)
271*f6dc9357SAndroid Build Coastguard Worker }
272*f6dc9357SAndroid Build Coastguard Worker };
273*f6dc9357SAndroid Build Coastguard Worker
274*f6dc9357SAndroid Build Coastguard Worker
275*f6dc9357SAndroid Build Coastguard Worker /* This flag is only intended to be used with super_empty.img and super.img on
276*f6dc9357SAndroid Build Coastguard Worker * retrofit devices. If set, the group needs a slot suffix to be interpreted
277*f6dc9357SAndroid Build Coastguard Worker * correctly. The suffix is automatically applied by ReadMetadata().
278*f6dc9357SAndroid Build Coastguard Worker */
279*f6dc9357SAndroid Build Coastguard Worker // #define LP_GROUP_SLOT_SUFFIXED (1 << 0)
280*f6dc9357SAndroid Build Coastguard Worker static unsigned const k_Group_Size = 48;
281*f6dc9357SAndroid Build Coastguard Worker
282*f6dc9357SAndroid Build Coastguard Worker // LpMetadataPartitionGroup
283*f6dc9357SAndroid Build Coastguard Worker struct CGroup
284*f6dc9357SAndroid Build Coastguard Worker {
285*f6dc9357SAndroid Build Coastguard Worker char name[kNameLen];
286*f6dc9357SAndroid Build Coastguard Worker UInt32 flags; /* (LP_GROUP_*). */
287*f6dc9357SAndroid Build Coastguard Worker UInt64 maximum_size; /* Maximum size in bytes. If 0, the group has no maximum size. */
288*f6dc9357SAndroid Build Coastguard Worker
ParseNArchive::NLp::CGroup289*f6dc9357SAndroid Build Coastguard Worker void Parse(const Byte *p)
290*f6dc9357SAndroid Build Coastguard Worker {
291*f6dc9357SAndroid Build Coastguard Worker memcpy(name, p, kNameLen);
292*f6dc9357SAndroid Build Coastguard Worker G32 (36, flags)
293*f6dc9357SAndroid Build Coastguard Worker G64 (40, maximum_size)
294*f6dc9357SAndroid Build Coastguard Worker }
295*f6dc9357SAndroid Build Coastguard Worker };
296*f6dc9357SAndroid Build Coastguard Worker
297*f6dc9357SAndroid Build Coastguard Worker
298*f6dc9357SAndroid Build Coastguard Worker
299*f6dc9357SAndroid Build Coastguard Worker
300*f6dc9357SAndroid Build Coastguard Worker /* This flag is only intended to be used with super_empty.img and super.img on
301*f6dc9357SAndroid Build Coastguard Worker * retrofit devices. On these devices there are A and B super partitions, and
302*f6dc9357SAndroid Build Coastguard Worker * we don't know ahead of time which slot the image will be applied to.
303*f6dc9357SAndroid Build Coastguard Worker *
304*f6dc9357SAndroid Build Coastguard Worker * If set, the block device needs a slot suffix applied before being used with
305*f6dc9357SAndroid Build Coastguard Worker * IPartitionOpener. The slot suffix is determined by the metadata slot number
306*f6dc9357SAndroid Build Coastguard Worker * (0 = _a, 1 = _b).
307*f6dc9357SAndroid Build Coastguard Worker */
308*f6dc9357SAndroid Build Coastguard Worker // #define LP_BLOCK_DEVICE_SLOT_SUFFIXED (1 << 0)
309*f6dc9357SAndroid Build Coastguard Worker
310*f6dc9357SAndroid Build Coastguard Worker static unsigned const k_Device_Size = 64;
311*f6dc9357SAndroid Build Coastguard Worker
312*f6dc9357SAndroid Build Coastguard Worker /* This struct defines an entry in the block_devices table. There must be at
313*f6dc9357SAndroid Build Coastguard Worker * least one device, and the first device must represent the partition holding
314*f6dc9357SAndroid Build Coastguard Worker * the super metadata.
315*f6dc9357SAndroid Build Coastguard Worker */
316*f6dc9357SAndroid Build Coastguard Worker // LpMetadataBlockDevice
317*f6dc9357SAndroid Build Coastguard Worker struct CDevice
318*f6dc9357SAndroid Build Coastguard Worker {
319*f6dc9357SAndroid Build Coastguard Worker /* 0: First usable sector for allocating logical partitions. this will be
320*f6dc9357SAndroid Build Coastguard Worker * the first sector after the initial geometry blocks, followed by the
321*f6dc9357SAndroid Build Coastguard Worker * space consumed by metadata_max_size*metadata_slot_count*2.
322*f6dc9357SAndroid Build Coastguard Worker */
323*f6dc9357SAndroid Build Coastguard Worker UInt64 first_logical_sector;
324*f6dc9357SAndroid Build Coastguard Worker
325*f6dc9357SAndroid Build Coastguard Worker /* 8: Alignment for defining partitions or partition extents. For example,
326*f6dc9357SAndroid Build Coastguard Worker * an alignment of 1MiB will require that all partitions have a size evenly
327*f6dc9357SAndroid Build Coastguard Worker * divisible by 1MiB, and that the smallest unit the partition can grow by
328*f6dc9357SAndroid Build Coastguard Worker * is 1MiB.
329*f6dc9357SAndroid Build Coastguard Worker *
330*f6dc9357SAndroid Build Coastguard Worker * Alignment is normally determined at runtime when growing or adding
331*f6dc9357SAndroid Build Coastguard Worker * partitions. If for some reason the alignment cannot be determined, then
332*f6dc9357SAndroid Build Coastguard Worker * this predefined alignment in the geometry is used instead. By default
333*f6dc9357SAndroid Build Coastguard Worker * it is set to 1MiB.
334*f6dc9357SAndroid Build Coastguard Worker */
335*f6dc9357SAndroid Build Coastguard Worker UInt32 alignment;
336*f6dc9357SAndroid Build Coastguard Worker
337*f6dc9357SAndroid Build Coastguard Worker /* 12: Alignment offset for "stacked" devices. For example, if the "super"
338*f6dc9357SAndroid Build Coastguard Worker * partition itself is not aligned within the parent block device's
339*f6dc9357SAndroid Build Coastguard Worker * partition table, then we adjust for this in deciding where to place
340*f6dc9357SAndroid Build Coastguard Worker * |first_logical_sector|.
341*f6dc9357SAndroid Build Coastguard Worker *
342*f6dc9357SAndroid Build Coastguard Worker * Similar to |alignment|, this will be derived from the operating system.
343*f6dc9357SAndroid Build Coastguard Worker * If it cannot be determined, it is assumed to be 0.
344*f6dc9357SAndroid Build Coastguard Worker */
345*f6dc9357SAndroid Build Coastguard Worker UInt32 alignment_offset;
346*f6dc9357SAndroid Build Coastguard Worker
347*f6dc9357SAndroid Build Coastguard Worker /* 16: Block device size, as specified when the metadata was created. This
348*f6dc9357SAndroid Build Coastguard Worker * can be used to verify the geometry against a target device.
349*f6dc9357SAndroid Build Coastguard Worker */
350*f6dc9357SAndroid Build Coastguard Worker UInt64 size;
351*f6dc9357SAndroid Build Coastguard Worker
352*f6dc9357SAndroid Build Coastguard Worker /* 24: Partition name in the GPT*/
353*f6dc9357SAndroid Build Coastguard Worker char partition_name[kNameLen];
354*f6dc9357SAndroid Build Coastguard Worker
355*f6dc9357SAndroid Build Coastguard Worker /* 60: Flags (see LP_BLOCK_DEVICE_* flags below). */
356*f6dc9357SAndroid Build Coastguard Worker UInt32 flags;
357*f6dc9357SAndroid Build Coastguard Worker
ParseNArchive::NLp::CDevice358*f6dc9357SAndroid Build Coastguard Worker void Parse(const Byte *p)
359*f6dc9357SAndroid Build Coastguard Worker {
360*f6dc9357SAndroid Build Coastguard Worker memcpy(partition_name, p + 24, kNameLen);
361*f6dc9357SAndroid Build Coastguard Worker G64 (0, first_logical_sector)
362*f6dc9357SAndroid Build Coastguard Worker G32 (8, alignment)
363*f6dc9357SAndroid Build Coastguard Worker G32 (12, alignment_offset)
364*f6dc9357SAndroid Build Coastguard Worker G64 (16, size)
365*f6dc9357SAndroid Build Coastguard Worker G32 (60, flags)
366*f6dc9357SAndroid Build Coastguard Worker }
367*f6dc9357SAndroid Build Coastguard Worker };
368*f6dc9357SAndroid Build Coastguard Worker
369*f6dc9357SAndroid Build Coastguard Worker
370*f6dc9357SAndroid Build Coastguard Worker /* This device uses Virtual A/B. Note that on retrofit devices, the expanded
371*f6dc9357SAndroid Build Coastguard Worker * header may not be present.
372*f6dc9357SAndroid Build Coastguard Worker */
373*f6dc9357SAndroid Build Coastguard Worker // #define LP_HEADER_FLAG_VIRTUAL_AB_DEVICE 0x1
374*f6dc9357SAndroid Build Coastguard Worker
375*f6dc9357SAndroid Build Coastguard Worker static const char * const g_Header_Flags[] =
376*f6dc9357SAndroid Build Coastguard Worker {
377*f6dc9357SAndroid Build Coastguard Worker "VIRTUAL_AB"
378*f6dc9357SAndroid Build Coastguard Worker };
379*f6dc9357SAndroid Build Coastguard Worker
380*f6dc9357SAndroid Build Coastguard Worker
381*f6dc9357SAndroid Build Coastguard Worker static const unsigned k_LpMetadataHeader10_size = 128;
382*f6dc9357SAndroid Build Coastguard Worker static const unsigned k_LpMetadataHeader12_size = 256;
383*f6dc9357SAndroid Build Coastguard Worker
384*f6dc9357SAndroid Build Coastguard Worker struct LpMetadataHeader
385*f6dc9357SAndroid Build Coastguard Worker {
386*f6dc9357SAndroid Build Coastguard Worker /* 0: Four bytes equal to LP_METADATA_HEADER_MAGIC. */
387*f6dc9357SAndroid Build Coastguard Worker UInt32 magic;
388*f6dc9357SAndroid Build Coastguard Worker
389*f6dc9357SAndroid Build Coastguard Worker /* 4: Version number required to read this metadata. If the version is not
390*f6dc9357SAndroid Build Coastguard Worker * equal to the library version, the metadata should be considered
391*f6dc9357SAndroid Build Coastguard Worker * incompatible.
392*f6dc9357SAndroid Build Coastguard Worker */
393*f6dc9357SAndroid Build Coastguard Worker UInt16 major_version;
394*f6dc9357SAndroid Build Coastguard Worker
395*f6dc9357SAndroid Build Coastguard Worker /* 6: Minor version. A library supporting newer features should be able to
396*f6dc9357SAndroid Build Coastguard Worker * read metadata with an older minor version. However, an older library
397*f6dc9357SAndroid Build Coastguard Worker * should not support reading metadata if its minor version is higher.
398*f6dc9357SAndroid Build Coastguard Worker */
399*f6dc9357SAndroid Build Coastguard Worker UInt16 minor_version;
400*f6dc9357SAndroid Build Coastguard Worker
401*f6dc9357SAndroid Build Coastguard Worker /* 8: The size of this header struct. */
402*f6dc9357SAndroid Build Coastguard Worker UInt32 header_size;
403*f6dc9357SAndroid Build Coastguard Worker
404*f6dc9357SAndroid Build Coastguard Worker /* 12: SHA256 checksum of the header, up to |header_size| bytes, computed as
405*f6dc9357SAndroid Build Coastguard Worker * if this field were set to 0.
406*f6dc9357SAndroid Build Coastguard Worker */
407*f6dc9357SAndroid Build Coastguard Worker // Byte header_checksum[32];
408*f6dc9357SAndroid Build Coastguard Worker
409*f6dc9357SAndroid Build Coastguard Worker /* 44: The total size of all tables. This size is contiguous; tables may not
410*f6dc9357SAndroid Build Coastguard Worker * have gaps in between, and they immediately follow the header.
411*f6dc9357SAndroid Build Coastguard Worker */
412*f6dc9357SAndroid Build Coastguard Worker UInt32 tables_size;
413*f6dc9357SAndroid Build Coastguard Worker
414*f6dc9357SAndroid Build Coastguard Worker /* 48: SHA256 checksum of all table contents. */
415*f6dc9357SAndroid Build Coastguard Worker Byte tables_checksum[32];
416*f6dc9357SAndroid Build Coastguard Worker
417*f6dc9357SAndroid Build Coastguard Worker /* 80: Partition table descriptor. */
418*f6dc9357SAndroid Build Coastguard Worker CDescriptor partitions;
419*f6dc9357SAndroid Build Coastguard Worker /* 92: Extent table descriptor. */
420*f6dc9357SAndroid Build Coastguard Worker CDescriptor extents;
421*f6dc9357SAndroid Build Coastguard Worker /* 104: Updateable group descriptor. */
422*f6dc9357SAndroid Build Coastguard Worker CDescriptor groups;
423*f6dc9357SAndroid Build Coastguard Worker /* 116: Block device table. */
424*f6dc9357SAndroid Build Coastguard Worker CDescriptor block_devices;
425*f6dc9357SAndroid Build Coastguard Worker
426*f6dc9357SAndroid Build Coastguard Worker /* Everything past here is header version 1.2+, and is only included if
427*f6dc9357SAndroid Build Coastguard Worker * needed. When liblp supporting >= 1.2 reads a < 1.2 header, it must
428*f6dc9357SAndroid Build Coastguard Worker * zero these additional fields.
429*f6dc9357SAndroid Build Coastguard Worker */
430*f6dc9357SAndroid Build Coastguard Worker
431*f6dc9357SAndroid Build Coastguard Worker /* 128: See LP_HEADER_FLAG_ constants for possible values. Header flags are
432*f6dc9357SAndroid Build Coastguard Worker * independent of the version number and intended to be informational only.
433*f6dc9357SAndroid Build Coastguard Worker * New flags can be added without bumping the version.
434*f6dc9357SAndroid Build Coastguard Worker */
435*f6dc9357SAndroid Build Coastguard Worker // UInt32 flags;
436*f6dc9357SAndroid Build Coastguard Worker
437*f6dc9357SAndroid Build Coastguard Worker /* 132: Reserved (zero), pad to 256 bytes. */
438*f6dc9357SAndroid Build Coastguard Worker // Byte reserved[124];
439*f6dc9357SAndroid Build Coastguard Worker
Parse128NArchive::NLp::LpMetadataHeader440*f6dc9357SAndroid Build Coastguard Worker void Parse128(const Byte *p)
441*f6dc9357SAndroid Build Coastguard Worker {
442*f6dc9357SAndroid Build Coastguard Worker G32 (0, magic)
443*f6dc9357SAndroid Build Coastguard Worker G16 (4, major_version)
444*f6dc9357SAndroid Build Coastguard Worker G16 (6, minor_version)
445*f6dc9357SAndroid Build Coastguard Worker G32 (8, header_size)
446*f6dc9357SAndroid Build Coastguard Worker // Byte header_checksum[32];
447*f6dc9357SAndroid Build Coastguard Worker G32 (44, tables_size)
448*f6dc9357SAndroid Build Coastguard Worker memcpy (tables_checksum, p + 48, 32);
449*f6dc9357SAndroid Build Coastguard Worker partitions.Parse(p + 80);
450*f6dc9357SAndroid Build Coastguard Worker extents.Parse(p + 92);
451*f6dc9357SAndroid Build Coastguard Worker groups.Parse(p + 104);
452*f6dc9357SAndroid Build Coastguard Worker block_devices.Parse(p + 116);
453*f6dc9357SAndroid Build Coastguard Worker /* Everything past here is header version 1.2+, and is only included if
454*f6dc9357SAndroid Build Coastguard Worker * needed. When liblp supporting >= 1.2 reads a < 1.2 header, it must
455*f6dc9357SAndroid Build Coastguard Worker * zero these additional fields.
456*f6dc9357SAndroid Build Coastguard Worker */
457*f6dc9357SAndroid Build Coastguard Worker }
458*f6dc9357SAndroid Build Coastguard Worker };
459*f6dc9357SAndroid Build Coastguard Worker
460*f6dc9357SAndroid Build Coastguard Worker
CheckSha256(const Byte * data,size_t size,const Byte * checksum)461*f6dc9357SAndroid Build Coastguard Worker static bool CheckSha256(const Byte *data, size_t size, const Byte *checksum)
462*f6dc9357SAndroid Build Coastguard Worker {
463*f6dc9357SAndroid Build Coastguard Worker MY_ALIGN (16)
464*f6dc9357SAndroid Build Coastguard Worker CSha256 sha;
465*f6dc9357SAndroid Build Coastguard Worker Sha256_Init(&sha);
466*f6dc9357SAndroid Build Coastguard Worker Sha256_Update(&sha, data, size);
467*f6dc9357SAndroid Build Coastguard Worker MY_ALIGN (16)
468*f6dc9357SAndroid Build Coastguard Worker Byte calced[32];
469*f6dc9357SAndroid Build Coastguard Worker Sha256_Final(&sha, calced);
470*f6dc9357SAndroid Build Coastguard Worker return memcmp(checksum, calced, 32) == 0;
471*f6dc9357SAndroid Build Coastguard Worker }
472*f6dc9357SAndroid Build Coastguard Worker
CheckSha256_csOffset(Byte * data,size_t size,unsigned hashOffset)473*f6dc9357SAndroid Build Coastguard Worker static bool CheckSha256_csOffset(Byte *data, size_t size, unsigned hashOffset)
474*f6dc9357SAndroid Build Coastguard Worker {
475*f6dc9357SAndroid Build Coastguard Worker MY_ALIGN (4)
476*f6dc9357SAndroid Build Coastguard Worker Byte checksum[32];
477*f6dc9357SAndroid Build Coastguard Worker Byte *shaData = &data[hashOffset];
478*f6dc9357SAndroid Build Coastguard Worker memcpy(checksum, shaData, 32);
479*f6dc9357SAndroid Build Coastguard Worker memset(shaData, 0, 32);
480*f6dc9357SAndroid Build Coastguard Worker return CheckSha256(data, size, checksum);
481*f6dc9357SAndroid Build Coastguard Worker }
482*f6dc9357SAndroid Build Coastguard Worker
483*f6dc9357SAndroid Build Coastguard Worker
484*f6dc9357SAndroid Build Coastguard Worker
485*f6dc9357SAndroid Build Coastguard Worker Z7_CLASS_IMP_CHandler_IInArchive_1(
486*f6dc9357SAndroid Build Coastguard Worker IInArchiveGetStream
487*f6dc9357SAndroid Build Coastguard Worker )
488*f6dc9357SAndroid Build Coastguard Worker CRecordVector<CPartition> _items;
489*f6dc9357SAndroid Build Coastguard Worker CRecordVector<CExtent> Extents;
490*f6dc9357SAndroid Build Coastguard Worker
491*f6dc9357SAndroid Build Coastguard Worker CMyComPtr<IInStream> _stream;
492*f6dc9357SAndroid Build Coastguard Worker UInt64 _totalSize;
493*f6dc9357SAndroid Build Coastguard Worker // UInt64 _usedSize;
494*f6dc9357SAndroid Build Coastguard Worker // UInt64 _headersSize;
495*f6dc9357SAndroid Build Coastguard Worker
496*f6dc9357SAndroid Build Coastguard Worker CGeometry geom;
497*f6dc9357SAndroid Build Coastguard Worker UInt16 Major_version;
498*f6dc9357SAndroid Build Coastguard Worker UInt16 Minor_version;
499*f6dc9357SAndroid Build Coastguard Worker UInt32 Flags;
500*f6dc9357SAndroid Build Coastguard Worker
501*f6dc9357SAndroid Build Coastguard Worker Int32 _mainFileIndex;
502*f6dc9357SAndroid Build Coastguard Worker UInt32 MethodsMask;
503*f6dc9357SAndroid Build Coastguard Worker bool _headerWarning;
504*f6dc9357SAndroid Build Coastguard Worker AString GroupsString;
505*f6dc9357SAndroid Build Coastguard Worker AString DevicesString;
506*f6dc9357SAndroid Build Coastguard Worker AString DeviceArcName;
507*f6dc9357SAndroid Build Coastguard Worker
508*f6dc9357SAndroid Build Coastguard Worker HRESULT Open2(IInStream *stream);
509*f6dc9357SAndroid Build Coastguard Worker };
510*f6dc9357SAndroid Build Coastguard Worker
511*f6dc9357SAndroid Build Coastguard Worker
AddComment_UInt64(AString & s,const char * name,UInt64 val)512*f6dc9357SAndroid Build Coastguard Worker static void AddComment_UInt64(AString &s, const char *name, UInt64 val)
513*f6dc9357SAndroid Build Coastguard Worker {
514*f6dc9357SAndroid Build Coastguard Worker s.Add_Space();
515*f6dc9357SAndroid Build Coastguard Worker s += name;
516*f6dc9357SAndroid Build Coastguard Worker s += '=';
517*f6dc9357SAndroid Build Coastguard Worker s.Add_UInt64(val);
518*f6dc9357SAndroid Build Coastguard Worker }
519*f6dc9357SAndroid Build Coastguard Worker
520*f6dc9357SAndroid Build Coastguard Worker
IsBufZero(const Byte * data,size_t size)521*f6dc9357SAndroid Build Coastguard Worker static bool IsBufZero(const Byte *data, size_t size)
522*f6dc9357SAndroid Build Coastguard Worker {
523*f6dc9357SAndroid Build Coastguard Worker for (size_t i = 0; i < size; i += 4)
524*f6dc9357SAndroid Build Coastguard Worker if (*(const UInt32 *)(const void *)(data + i) != 0)
525*f6dc9357SAndroid Build Coastguard Worker return false;
526*f6dc9357SAndroid Build Coastguard Worker return true;
527*f6dc9357SAndroid Build Coastguard Worker }
528*f6dc9357SAndroid Build Coastguard Worker
529*f6dc9357SAndroid Build Coastguard Worker
Open2(IInStream * stream)530*f6dc9357SAndroid Build Coastguard Worker HRESULT CHandler::Open2(IInStream *stream)
531*f6dc9357SAndroid Build Coastguard Worker {
532*f6dc9357SAndroid Build Coastguard Worker RINOK(InStream_SeekSet(stream, LP_PARTITION_RESERVED_BYTES))
533*f6dc9357SAndroid Build Coastguard Worker {
534*f6dc9357SAndroid Build Coastguard Worker MY_ALIGN (4)
535*f6dc9357SAndroid Build Coastguard Worker Byte buf[k_Geometry_Size];
536*f6dc9357SAndroid Build Coastguard Worker RINOK(ReadStream_FALSE(stream, buf, k_Geometry_Size))
537*f6dc9357SAndroid Build Coastguard Worker if (memcmp(buf, k_Signature, k_SignatureSize) != 0)
538*f6dc9357SAndroid Build Coastguard Worker return S_FALSE;
539*f6dc9357SAndroid Build Coastguard Worker if (!geom.Parse(buf))
540*f6dc9357SAndroid Build Coastguard Worker return S_FALSE;
541*f6dc9357SAndroid Build Coastguard Worker if (!CheckSha256_csOffset(buf, k_Geometry_Size, 8))
542*f6dc9357SAndroid Build Coastguard Worker return S_FALSE;
543*f6dc9357SAndroid Build Coastguard Worker }
544*f6dc9357SAndroid Build Coastguard Worker
545*f6dc9357SAndroid Build Coastguard Worker CByteBuffer buffer;
546*f6dc9357SAndroid Build Coastguard Worker RINOK(InStream_SeekToBegin(stream))
547*f6dc9357SAndroid Build Coastguard Worker buffer.Alloc(LP_METADATA_GEOMETRY_SIZE * 2);
548*f6dc9357SAndroid Build Coastguard Worker {
549*f6dc9357SAndroid Build Coastguard Worker // buffer.Size() >= LP_PARTITION_RESERVED_BYTES
550*f6dc9357SAndroid Build Coastguard Worker RINOK(ReadStream_FALSE(stream, buffer, LP_PARTITION_RESERVED_BYTES))
551*f6dc9357SAndroid Build Coastguard Worker if (!IsBufZero(buffer, LP_PARTITION_RESERVED_BYTES))
552*f6dc9357SAndroid Build Coastguard Worker {
553*f6dc9357SAndroid Build Coastguard Worker _headerWarning = true;
554*f6dc9357SAndroid Build Coastguard Worker // return S_FALSE;
555*f6dc9357SAndroid Build Coastguard Worker }
556*f6dc9357SAndroid Build Coastguard Worker }
557*f6dc9357SAndroid Build Coastguard Worker
558*f6dc9357SAndroid Build Coastguard Worker RINOK(ReadStream_FALSE(stream, buffer, LP_METADATA_GEOMETRY_SIZE * 2))
559*f6dc9357SAndroid Build Coastguard Worker // we check that 2 copies of GEOMETRY are identical:
560*f6dc9357SAndroid Build Coastguard Worker if (memcmp(buffer, buffer + LP_METADATA_GEOMETRY_SIZE, LP_METADATA_GEOMETRY_SIZE) != 0
561*f6dc9357SAndroid Build Coastguard Worker || !IsBufZero(buffer + k_Geometry_Size, LP_METADATA_GEOMETRY_SIZE - k_Geometry_Size))
562*f6dc9357SAndroid Build Coastguard Worker {
563*f6dc9357SAndroid Build Coastguard Worker _headerWarning = true;
564*f6dc9357SAndroid Build Coastguard Worker // return S_FALSE;
565*f6dc9357SAndroid Build Coastguard Worker }
566*f6dc9357SAndroid Build Coastguard Worker
567*f6dc9357SAndroid Build Coastguard Worker RINOK(ReadStream_FALSE(stream, buffer, k_LpMetadataHeader10_size))
568*f6dc9357SAndroid Build Coastguard Worker LpMetadataHeader header;
569*f6dc9357SAndroid Build Coastguard Worker header.Parse128(buffer);
570*f6dc9357SAndroid Build Coastguard Worker if (header.magic != LP_METADATA_HEADER_MAGIC ||
571*f6dc9357SAndroid Build Coastguard Worker header.major_version != LP_METADATA_MAJOR_VERSION ||
572*f6dc9357SAndroid Build Coastguard Worker header.header_size < k_LpMetadataHeader10_size)
573*f6dc9357SAndroid Build Coastguard Worker return S_FALSE;
574*f6dc9357SAndroid Build Coastguard Worker Flags = 0;
575*f6dc9357SAndroid Build Coastguard Worker if (header.header_size > k_LpMetadataHeader10_size)
576*f6dc9357SAndroid Build Coastguard Worker {
577*f6dc9357SAndroid Build Coastguard Worker if (header.header_size != k_LpMetadataHeader12_size)
578*f6dc9357SAndroid Build Coastguard Worker return S_FALSE;
579*f6dc9357SAndroid Build Coastguard Worker RINOK(ReadStream_FALSE(stream, buffer + k_LpMetadataHeader10_size,
580*f6dc9357SAndroid Build Coastguard Worker header.header_size - k_LpMetadataHeader10_size))
581*f6dc9357SAndroid Build Coastguard Worker Flags = Get32(buffer + k_LpMetadataHeader10_size);
582*f6dc9357SAndroid Build Coastguard Worker }
583*f6dc9357SAndroid Build Coastguard Worker Major_version = header.major_version;
584*f6dc9357SAndroid Build Coastguard Worker Minor_version = header.minor_version;
585*f6dc9357SAndroid Build Coastguard Worker
586*f6dc9357SAndroid Build Coastguard Worker if (!CheckSha256_csOffset(buffer, header.header_size, 12))
587*f6dc9357SAndroid Build Coastguard Worker return S_FALSE;
588*f6dc9357SAndroid Build Coastguard Worker
589*f6dc9357SAndroid Build Coastguard Worker if (geom.metadata_max_size < header.tables_size ||
590*f6dc9357SAndroid Build Coastguard Worker geom.metadata_max_size - header.tables_size < header.header_size)
591*f6dc9357SAndroid Build Coastguard Worker return S_FALSE;
592*f6dc9357SAndroid Build Coastguard Worker
593*f6dc9357SAndroid Build Coastguard Worker buffer.AllocAtLeast(header.tables_size);
594*f6dc9357SAndroid Build Coastguard Worker RINOK(ReadStream_FALSE(stream, buffer, header.tables_size))
595*f6dc9357SAndroid Build Coastguard Worker
596*f6dc9357SAndroid Build Coastguard Worker const UInt64 totalMetaSize = geom.GetTotalMetadataSize();
597*f6dc9357SAndroid Build Coastguard Worker // _headersSize = _totalSize;
598*f6dc9357SAndroid Build Coastguard Worker _totalSize = totalMetaSize;
599*f6dc9357SAndroid Build Coastguard Worker
600*f6dc9357SAndroid Build Coastguard Worker if (!CheckSha256(buffer, header.tables_size, header.tables_checksum))
601*f6dc9357SAndroid Build Coastguard Worker return S_FALSE;
602*f6dc9357SAndroid Build Coastguard Worker
603*f6dc9357SAndroid Build Coastguard Worker {
604*f6dc9357SAndroid Build Coastguard Worker const CDescriptor &d = header.partitions;
605*f6dc9357SAndroid Build Coastguard Worker if (!d.CheckLimits(header.tables_size))
606*f6dc9357SAndroid Build Coastguard Worker return S_FALSE;
607*f6dc9357SAndroid Build Coastguard Worker if (d.entry_size != k_MetaPartition_Size)
608*f6dc9357SAndroid Build Coastguard Worker return S_FALSE;
609*f6dc9357SAndroid Build Coastguard Worker for (UInt32 i = 0; i < d.num_entries; i++)
610*f6dc9357SAndroid Build Coastguard Worker {
611*f6dc9357SAndroid Build Coastguard Worker CPartition part;
612*f6dc9357SAndroid Build Coastguard Worker part.Parse(buffer + d.offset + i * d.entry_size);
613*f6dc9357SAndroid Build Coastguard Worker const UInt32 extLimit = part.first_extent_index + part.num_extents;
614*f6dc9357SAndroid Build Coastguard Worker if (extLimit < part.first_extent_index ||
615*f6dc9357SAndroid Build Coastguard Worker extLimit > header.extents.num_entries ||
616*f6dc9357SAndroid Build Coastguard Worker part.group_index >= header.groups.num_entries)
617*f6dc9357SAndroid Build Coastguard Worker return S_FALSE;
618*f6dc9357SAndroid Build Coastguard Worker _items.Add(part);
619*f6dc9357SAndroid Build Coastguard Worker }
620*f6dc9357SAndroid Build Coastguard Worker }
621*f6dc9357SAndroid Build Coastguard Worker {
622*f6dc9357SAndroid Build Coastguard Worker const CDescriptor &d = header.extents;
623*f6dc9357SAndroid Build Coastguard Worker if (!d.CheckLimits(header.tables_size))
624*f6dc9357SAndroid Build Coastguard Worker return S_FALSE;
625*f6dc9357SAndroid Build Coastguard Worker if (d.entry_size != k_MetaExtent_Size)
626*f6dc9357SAndroid Build Coastguard Worker return S_FALSE;
627*f6dc9357SAndroid Build Coastguard Worker for (UInt32 i = 0; i < d.num_entries; i++)
628*f6dc9357SAndroid Build Coastguard Worker {
629*f6dc9357SAndroid Build Coastguard Worker CExtent e;
630*f6dc9357SAndroid Build Coastguard Worker e.Parse(buffer + d.offset + i * d.entry_size);
631*f6dc9357SAndroid Build Coastguard Worker // if (e.target_type > LP_TARGET_TYPE_ZERO) return S_FALSE;
632*f6dc9357SAndroid Build Coastguard Worker if (e.IsRAW())
633*f6dc9357SAndroid Build Coastguard Worker {
634*f6dc9357SAndroid Build Coastguard Worker if (e.target_source >= header.block_devices.num_entries)
635*f6dc9357SAndroid Build Coastguard Worker return S_FALSE;
636*f6dc9357SAndroid Build Coastguard Worker const UInt64 endSector = e.target_data + e.num_sectors;
637*f6dc9357SAndroid Build Coastguard Worker const UInt64 endOffset = endSector << kSectorSizeLog;
638*f6dc9357SAndroid Build Coastguard Worker if (_totalSize < endOffset)
639*f6dc9357SAndroid Build Coastguard Worker _totalSize = endOffset;
640*f6dc9357SAndroid Build Coastguard Worker }
641*f6dc9357SAndroid Build Coastguard Worker MethodsMask |= (UInt32)1 << e.target_type;
642*f6dc9357SAndroid Build Coastguard Worker Extents.Add(e);
643*f6dc9357SAndroid Build Coastguard Worker }
644*f6dc9357SAndroid Build Coastguard Worker }
645*f6dc9357SAndroid Build Coastguard Worker
646*f6dc9357SAndroid Build Coastguard Worker // _usedSize = _totalSize;
647*f6dc9357SAndroid Build Coastguard Worker {
648*f6dc9357SAndroid Build Coastguard Worker const CDescriptor &d = header.groups;
649*f6dc9357SAndroid Build Coastguard Worker if (!d.CheckLimits(header.tables_size))
650*f6dc9357SAndroid Build Coastguard Worker return S_FALSE;
651*f6dc9357SAndroid Build Coastguard Worker if (d.entry_size != k_Group_Size)
652*f6dc9357SAndroid Build Coastguard Worker return S_FALSE;
653*f6dc9357SAndroid Build Coastguard Worker AString s;
654*f6dc9357SAndroid Build Coastguard Worker for (UInt32 i = 0; i < d.num_entries; i++)
655*f6dc9357SAndroid Build Coastguard Worker {
656*f6dc9357SAndroid Build Coastguard Worker CGroup g;
657*f6dc9357SAndroid Build Coastguard Worker g.Parse(buffer + d.offset + i * d.entry_size);
658*f6dc9357SAndroid Build Coastguard Worker if (_totalSize < g.maximum_size)
659*f6dc9357SAndroid Build Coastguard Worker _totalSize = g.maximum_size;
660*f6dc9357SAndroid Build Coastguard Worker s += " ";
661*f6dc9357SAndroid Build Coastguard Worker AddName36ToString(s, g.name, true);
662*f6dc9357SAndroid Build Coastguard Worker AddComment_UInt64(s, "maximum_size", g.maximum_size);
663*f6dc9357SAndroid Build Coastguard Worker AddComment_UInt64(s, "flags", g.flags);
664*f6dc9357SAndroid Build Coastguard Worker s.Add_LF();
665*f6dc9357SAndroid Build Coastguard Worker }
666*f6dc9357SAndroid Build Coastguard Worker GroupsString = s;
667*f6dc9357SAndroid Build Coastguard Worker }
668*f6dc9357SAndroid Build Coastguard Worker
669*f6dc9357SAndroid Build Coastguard Worker {
670*f6dc9357SAndroid Build Coastguard Worker const CDescriptor &d = header.block_devices;
671*f6dc9357SAndroid Build Coastguard Worker if (!d.CheckLimits(header.tables_size))
672*f6dc9357SAndroid Build Coastguard Worker return S_FALSE;
673*f6dc9357SAndroid Build Coastguard Worker if (d.entry_size != k_Device_Size)
674*f6dc9357SAndroid Build Coastguard Worker return S_FALSE;
675*f6dc9357SAndroid Build Coastguard Worker AString s;
676*f6dc9357SAndroid Build Coastguard Worker // CRecordVector<CDevice> devices;
677*f6dc9357SAndroid Build Coastguard Worker for (UInt32 i = 0; i < d.num_entries; i++)
678*f6dc9357SAndroid Build Coastguard Worker {
679*f6dc9357SAndroid Build Coastguard Worker CDevice v;
680*f6dc9357SAndroid Build Coastguard Worker v.Parse(buffer + d.offset + i * d.entry_size);
681*f6dc9357SAndroid Build Coastguard Worker // if (i == 0)
682*f6dc9357SAndroid Build Coastguard Worker {
683*f6dc9357SAndroid Build Coastguard Worker // it's super_device is first device;
684*f6dc9357SAndroid Build Coastguard Worker if (totalMetaSize > (v.first_logical_sector << kSectorSizeLog))
685*f6dc9357SAndroid Build Coastguard Worker return S_FALSE;
686*f6dc9357SAndroid Build Coastguard Worker }
687*f6dc9357SAndroid Build Coastguard Worker if (_totalSize < v.size)
688*f6dc9357SAndroid Build Coastguard Worker _totalSize = v.size;
689*f6dc9357SAndroid Build Coastguard Worker s += " ";
690*f6dc9357SAndroid Build Coastguard Worker if (i == 0)
691*f6dc9357SAndroid Build Coastguard Worker AddName36ToString(DeviceArcName, v.partition_name, true);
692*f6dc9357SAndroid Build Coastguard Worker // devices.Add(v);
693*f6dc9357SAndroid Build Coastguard Worker AddName36ToString(s, v.partition_name, true);
694*f6dc9357SAndroid Build Coastguard Worker AddComment_UInt64(s, "size", v.size);
695*f6dc9357SAndroid Build Coastguard Worker AddComment_UInt64(s, "first_logical_sector", v.first_logical_sector);
696*f6dc9357SAndroid Build Coastguard Worker AddComment_UInt64(s, "alignment", v.alignment);
697*f6dc9357SAndroid Build Coastguard Worker AddComment_UInt64(s, "alignment_offset", v.alignment_offset);
698*f6dc9357SAndroid Build Coastguard Worker AddComment_UInt64(s, "flags", v.flags);
699*f6dc9357SAndroid Build Coastguard Worker s.Add_LF();
700*f6dc9357SAndroid Build Coastguard Worker }
701*f6dc9357SAndroid Build Coastguard Worker DevicesString = s;
702*f6dc9357SAndroid Build Coastguard Worker }
703*f6dc9357SAndroid Build Coastguard Worker
704*f6dc9357SAndroid Build Coastguard Worker {
705*f6dc9357SAndroid Build Coastguard Worker FOR_VECTOR (i, _items)
706*f6dc9357SAndroid Build Coastguard Worker {
707*f6dc9357SAndroid Build Coastguard Worker CPartition &part = _items[i];
708*f6dc9357SAndroid Build Coastguard Worker if (part.first_extent_index > Extents.Size() ||
709*f6dc9357SAndroid Build Coastguard Worker part.num_extents > Extents.Size() - part.first_extent_index)
710*f6dc9357SAndroid Build Coastguard Worker return S_FALSE;
711*f6dc9357SAndroid Build Coastguard Worker
712*f6dc9357SAndroid Build Coastguard Worker UInt64 numSectors = 0;
713*f6dc9357SAndroid Build Coastguard Worker UInt64 numSectors_Pack = 0;
714*f6dc9357SAndroid Build Coastguard Worker UInt32 methods = 0;
715*f6dc9357SAndroid Build Coastguard Worker for (UInt32 k = 0; k < part.num_extents; k++)
716*f6dc9357SAndroid Build Coastguard Worker {
717*f6dc9357SAndroid Build Coastguard Worker const CExtent &e = Extents[part.first_extent_index + k];
718*f6dc9357SAndroid Build Coastguard Worker numSectors += e.num_sectors;
719*f6dc9357SAndroid Build Coastguard Worker if (e.IsRAW())
720*f6dc9357SAndroid Build Coastguard Worker numSectors_Pack += e.num_sectors;
721*f6dc9357SAndroid Build Coastguard Worker methods |= (UInt32)1 << e.target_type;
722*f6dc9357SAndroid Build Coastguard Worker }
723*f6dc9357SAndroid Build Coastguard Worker part.NumSectors = numSectors;
724*f6dc9357SAndroid Build Coastguard Worker part.NumSectors_Pack = numSectors_Pack;
725*f6dc9357SAndroid Build Coastguard Worker part.MethodsMask = methods;
726*f6dc9357SAndroid Build Coastguard Worker }
727*f6dc9357SAndroid Build Coastguard Worker }
728*f6dc9357SAndroid Build Coastguard Worker
729*f6dc9357SAndroid Build Coastguard Worker return S_OK;
730*f6dc9357SAndroid Build Coastguard Worker }
731*f6dc9357SAndroid Build Coastguard Worker
732*f6dc9357SAndroid Build Coastguard Worker
Z7_COM7F_IMF(CHandler::Open (IInStream * stream,const UInt64 *,IArchiveOpenCallback *))733*f6dc9357SAndroid Build Coastguard Worker Z7_COM7F_IMF(CHandler::Open(IInStream *stream,
734*f6dc9357SAndroid Build Coastguard Worker const UInt64 * /* maxCheckStartPosition */,
735*f6dc9357SAndroid Build Coastguard Worker IArchiveOpenCallback * /* openArchiveCallback */))
736*f6dc9357SAndroid Build Coastguard Worker {
737*f6dc9357SAndroid Build Coastguard Worker COM_TRY_BEGIN
738*f6dc9357SAndroid Build Coastguard Worker Close();
739*f6dc9357SAndroid Build Coastguard Worker RINOK(Open2(stream))
740*f6dc9357SAndroid Build Coastguard Worker _stream = stream;
741*f6dc9357SAndroid Build Coastguard Worker
742*f6dc9357SAndroid Build Coastguard Worker int mainFileIndex = -1;
743*f6dc9357SAndroid Build Coastguard Worker unsigned numNonEmptyParts = 0;
744*f6dc9357SAndroid Build Coastguard Worker
745*f6dc9357SAndroid Build Coastguard Worker FOR_VECTOR (fileIndex, _items)
746*f6dc9357SAndroid Build Coastguard Worker {
747*f6dc9357SAndroid Build Coastguard Worker CPartition &item = _items[fileIndex];
748*f6dc9357SAndroid Build Coastguard Worker if (item.NumSectors != 0)
749*f6dc9357SAndroid Build Coastguard Worker {
750*f6dc9357SAndroid Build Coastguard Worker mainFileIndex = (int)fileIndex;
751*f6dc9357SAndroid Build Coastguard Worker numNonEmptyParts++;
752*f6dc9357SAndroid Build Coastguard Worker CMyComPtr<ISequentialInStream> parseStream;
753*f6dc9357SAndroid Build Coastguard Worker if (GetStream(fileIndex, &parseStream) == S_OK && parseStream)
754*f6dc9357SAndroid Build Coastguard Worker {
755*f6dc9357SAndroid Build Coastguard Worker const size_t kParseSize = 1 << 11;
756*f6dc9357SAndroid Build Coastguard Worker Byte buf[kParseSize];
757*f6dc9357SAndroid Build Coastguard Worker if (ReadStream_FAIL(parseStream, buf, kParseSize) == S_OK)
758*f6dc9357SAndroid Build Coastguard Worker {
759*f6dc9357SAndroid Build Coastguard Worker UInt64 extSize;
760*f6dc9357SAndroid Build Coastguard Worker if (NExt::IsArc_Ext_PhySize(buf, kParseSize, &extSize) == k_IsArc_Res_YES)
761*f6dc9357SAndroid Build Coastguard Worker if (extSize == item.GetSize())
762*f6dc9357SAndroid Build Coastguard Worker item.Ext = "ext";
763*f6dc9357SAndroid Build Coastguard Worker }
764*f6dc9357SAndroid Build Coastguard Worker }
765*f6dc9357SAndroid Build Coastguard Worker }
766*f6dc9357SAndroid Build Coastguard Worker }
767*f6dc9357SAndroid Build Coastguard Worker if (numNonEmptyParts == 1)
768*f6dc9357SAndroid Build Coastguard Worker _mainFileIndex = mainFileIndex;
769*f6dc9357SAndroid Build Coastguard Worker
770*f6dc9357SAndroid Build Coastguard Worker return S_OK;
771*f6dc9357SAndroid Build Coastguard Worker COM_TRY_END
772*f6dc9357SAndroid Build Coastguard Worker }
773*f6dc9357SAndroid Build Coastguard Worker
774*f6dc9357SAndroid Build Coastguard Worker
Z7_COM7F_IMF(CHandler::Close ())775*f6dc9357SAndroid Build Coastguard Worker Z7_COM7F_IMF(CHandler::Close())
776*f6dc9357SAndroid Build Coastguard Worker {
777*f6dc9357SAndroid Build Coastguard Worker _totalSize = 0;
778*f6dc9357SAndroid Build Coastguard Worker // _usedSize = 0;
779*f6dc9357SAndroid Build Coastguard Worker // _headersSize = 0;
780*f6dc9357SAndroid Build Coastguard Worker _items.Clear();
781*f6dc9357SAndroid Build Coastguard Worker Extents.Clear();
782*f6dc9357SAndroid Build Coastguard Worker _stream.Release();
783*f6dc9357SAndroid Build Coastguard Worker _mainFileIndex = -1;
784*f6dc9357SAndroid Build Coastguard Worker _headerWarning = false;
785*f6dc9357SAndroid Build Coastguard Worker MethodsMask = 0;
786*f6dc9357SAndroid Build Coastguard Worker GroupsString.Empty();
787*f6dc9357SAndroid Build Coastguard Worker DevicesString.Empty();
788*f6dc9357SAndroid Build Coastguard Worker DeviceArcName.Empty();
789*f6dc9357SAndroid Build Coastguard Worker return S_OK;
790*f6dc9357SAndroid Build Coastguard Worker }
791*f6dc9357SAndroid Build Coastguard Worker
792*f6dc9357SAndroid Build Coastguard Worker
793*f6dc9357SAndroid Build Coastguard Worker static const Byte kProps[] =
794*f6dc9357SAndroid Build Coastguard Worker {
795*f6dc9357SAndroid Build Coastguard Worker kpidPath,
796*f6dc9357SAndroid Build Coastguard Worker kpidSize,
797*f6dc9357SAndroid Build Coastguard Worker kpidPackSize,
798*f6dc9357SAndroid Build Coastguard Worker kpidCharacts,
799*f6dc9357SAndroid Build Coastguard Worker kpidMethod,
800*f6dc9357SAndroid Build Coastguard Worker kpidNumBlocks,
801*f6dc9357SAndroid Build Coastguard Worker kpidOffset
802*f6dc9357SAndroid Build Coastguard Worker };
803*f6dc9357SAndroid Build Coastguard Worker
804*f6dc9357SAndroid Build Coastguard Worker static const Byte kArcProps[] =
805*f6dc9357SAndroid Build Coastguard Worker {
806*f6dc9357SAndroid Build Coastguard Worker kpidUnpackVer,
807*f6dc9357SAndroid Build Coastguard Worker kpidMethod,
808*f6dc9357SAndroid Build Coastguard Worker kpidClusterSize,
809*f6dc9357SAndroid Build Coastguard Worker // kpidHeadersSize,
810*f6dc9357SAndroid Build Coastguard Worker // kpidFreeSpace,
811*f6dc9357SAndroid Build Coastguard Worker kpidName,
812*f6dc9357SAndroid Build Coastguard Worker kpidComment
813*f6dc9357SAndroid Build Coastguard Worker };
814*f6dc9357SAndroid Build Coastguard Worker
815*f6dc9357SAndroid Build Coastguard Worker IMP_IInArchive_Props
816*f6dc9357SAndroid Build Coastguard Worker IMP_IInArchive_ArcProps
817*f6dc9357SAndroid Build Coastguard Worker
Z7_COM7F_IMF(CHandler::GetArchiveProperty (PROPID propID,PROPVARIANT * value))818*f6dc9357SAndroid Build Coastguard Worker Z7_COM7F_IMF(CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value))
819*f6dc9357SAndroid Build Coastguard Worker {
820*f6dc9357SAndroid Build Coastguard Worker COM_TRY_BEGIN
821*f6dc9357SAndroid Build Coastguard Worker NCOM::CPropVariant prop;
822*f6dc9357SAndroid Build Coastguard Worker switch (propID)
823*f6dc9357SAndroid Build Coastguard Worker {
824*f6dc9357SAndroid Build Coastguard Worker case kpidMainSubfile:
825*f6dc9357SAndroid Build Coastguard Worker {
826*f6dc9357SAndroid Build Coastguard Worker if (_mainFileIndex >= 0)
827*f6dc9357SAndroid Build Coastguard Worker prop = (UInt32)_mainFileIndex;
828*f6dc9357SAndroid Build Coastguard Worker break;
829*f6dc9357SAndroid Build Coastguard Worker }
830*f6dc9357SAndroid Build Coastguard Worker case kpidPhySize: prop = _totalSize; break;
831*f6dc9357SAndroid Build Coastguard Worker
832*f6dc9357SAndroid Build Coastguard Worker // case kpidFreeSpace: if (_usedSize != 0) prop = _totalSize - _usedSize; break;
833*f6dc9357SAndroid Build Coastguard Worker // case kpidHeadersSize: prop = _headersSize; break;
834*f6dc9357SAndroid Build Coastguard Worker
835*f6dc9357SAndroid Build Coastguard Worker case kpidMethod:
836*f6dc9357SAndroid Build Coastguard Worker {
837*f6dc9357SAndroid Build Coastguard Worker const UInt32 m = MethodsMask;
838*f6dc9357SAndroid Build Coastguard Worker if (m != 0)
839*f6dc9357SAndroid Build Coastguard Worker {
840*f6dc9357SAndroid Build Coastguard Worker FLAGS_TO_PROP(g_Methods, m, prop);
841*f6dc9357SAndroid Build Coastguard Worker }
842*f6dc9357SAndroid Build Coastguard Worker break;
843*f6dc9357SAndroid Build Coastguard Worker }
844*f6dc9357SAndroid Build Coastguard Worker
845*f6dc9357SAndroid Build Coastguard Worker case kpidUnpackVer:
846*f6dc9357SAndroid Build Coastguard Worker {
847*f6dc9357SAndroid Build Coastguard Worker AString s;
848*f6dc9357SAndroid Build Coastguard Worker s.Add_UInt32(Major_version);
849*f6dc9357SAndroid Build Coastguard Worker s.Add_Dot();
850*f6dc9357SAndroid Build Coastguard Worker s.Add_UInt32(Minor_version);
851*f6dc9357SAndroid Build Coastguard Worker prop = s;
852*f6dc9357SAndroid Build Coastguard Worker break;
853*f6dc9357SAndroid Build Coastguard Worker }
854*f6dc9357SAndroid Build Coastguard Worker
855*f6dc9357SAndroid Build Coastguard Worker case kpidClusterSize:
856*f6dc9357SAndroid Build Coastguard Worker prop = geom.logical_block_size;
857*f6dc9357SAndroid Build Coastguard Worker break;
858*f6dc9357SAndroid Build Coastguard Worker
859*f6dc9357SAndroid Build Coastguard Worker case kpidComment:
860*f6dc9357SAndroid Build Coastguard Worker {
861*f6dc9357SAndroid Build Coastguard Worker AString s;
862*f6dc9357SAndroid Build Coastguard Worker
863*f6dc9357SAndroid Build Coastguard Worker s += "metadata_slot_count: ";
864*f6dc9357SAndroid Build Coastguard Worker s.Add_UInt32(geom.metadata_slot_count);
865*f6dc9357SAndroid Build Coastguard Worker s.Add_LF();
866*f6dc9357SAndroid Build Coastguard Worker
867*f6dc9357SAndroid Build Coastguard Worker s += "metadata_max_size: ";
868*f6dc9357SAndroid Build Coastguard Worker s.Add_UInt32(geom.metadata_max_size);
869*f6dc9357SAndroid Build Coastguard Worker s.Add_LF();
870*f6dc9357SAndroid Build Coastguard Worker
871*f6dc9357SAndroid Build Coastguard Worker if (Flags != 0)
872*f6dc9357SAndroid Build Coastguard Worker {
873*f6dc9357SAndroid Build Coastguard Worker s += "flags: ";
874*f6dc9357SAndroid Build Coastguard Worker s += FlagsToString(g_Header_Flags, Z7_ARRAY_SIZE(g_Header_Flags), Flags);
875*f6dc9357SAndroid Build Coastguard Worker s.Add_LF();
876*f6dc9357SAndroid Build Coastguard Worker }
877*f6dc9357SAndroid Build Coastguard Worker
878*f6dc9357SAndroid Build Coastguard Worker if (!GroupsString.IsEmpty())
879*f6dc9357SAndroid Build Coastguard Worker {
880*f6dc9357SAndroid Build Coastguard Worker s += "Groups:";
881*f6dc9357SAndroid Build Coastguard Worker s.Add_LF();
882*f6dc9357SAndroid Build Coastguard Worker s += GroupsString;
883*f6dc9357SAndroid Build Coastguard Worker }
884*f6dc9357SAndroid Build Coastguard Worker
885*f6dc9357SAndroid Build Coastguard Worker if (!DevicesString.IsEmpty())
886*f6dc9357SAndroid Build Coastguard Worker {
887*f6dc9357SAndroid Build Coastguard Worker s += "BlockDevices:";
888*f6dc9357SAndroid Build Coastguard Worker s.Add_LF();
889*f6dc9357SAndroid Build Coastguard Worker s += DevicesString;
890*f6dc9357SAndroid Build Coastguard Worker }
891*f6dc9357SAndroid Build Coastguard Worker
892*f6dc9357SAndroid Build Coastguard Worker if (!s.IsEmpty())
893*f6dc9357SAndroid Build Coastguard Worker prop = s;
894*f6dc9357SAndroid Build Coastguard Worker break;
895*f6dc9357SAndroid Build Coastguard Worker }
896*f6dc9357SAndroid Build Coastguard Worker
897*f6dc9357SAndroid Build Coastguard Worker case kpidName:
898*f6dc9357SAndroid Build Coastguard Worker if (!DeviceArcName.IsEmpty())
899*f6dc9357SAndroid Build Coastguard Worker prop = DeviceArcName + ".lpimg";
900*f6dc9357SAndroid Build Coastguard Worker break;
901*f6dc9357SAndroid Build Coastguard Worker
902*f6dc9357SAndroid Build Coastguard Worker case kpidWarningFlags:
903*f6dc9357SAndroid Build Coastguard Worker if (_headerWarning)
904*f6dc9357SAndroid Build Coastguard Worker {
905*f6dc9357SAndroid Build Coastguard Worker UInt32 v = kpv_ErrorFlags_HeadersError;
906*f6dc9357SAndroid Build Coastguard Worker prop = v;
907*f6dc9357SAndroid Build Coastguard Worker }
908*f6dc9357SAndroid Build Coastguard Worker break;
909*f6dc9357SAndroid Build Coastguard Worker }
910*f6dc9357SAndroid Build Coastguard Worker prop.Detach(value);
911*f6dc9357SAndroid Build Coastguard Worker return S_OK;
912*f6dc9357SAndroid Build Coastguard Worker COM_TRY_END
913*f6dc9357SAndroid Build Coastguard Worker }
914*f6dc9357SAndroid Build Coastguard Worker
915*f6dc9357SAndroid Build Coastguard Worker
Z7_COM7F_IMF(CHandler::GetNumberOfItems (UInt32 * numItems))916*f6dc9357SAndroid Build Coastguard Worker Z7_COM7F_IMF(CHandler::GetNumberOfItems(UInt32 *numItems))
917*f6dc9357SAndroid Build Coastguard Worker {
918*f6dc9357SAndroid Build Coastguard Worker *numItems = _items.Size();
919*f6dc9357SAndroid Build Coastguard Worker return S_OK;
920*f6dc9357SAndroid Build Coastguard Worker }
921*f6dc9357SAndroid Build Coastguard Worker
922*f6dc9357SAndroid Build Coastguard Worker
Z7_COM7F_IMF(CHandler::GetProperty (UInt32 index,PROPID propID,PROPVARIANT * value))923*f6dc9357SAndroid Build Coastguard Worker Z7_COM7F_IMF(CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *value))
924*f6dc9357SAndroid Build Coastguard Worker {
925*f6dc9357SAndroid Build Coastguard Worker COM_TRY_BEGIN
926*f6dc9357SAndroid Build Coastguard Worker NCOM::CPropVariant prop;
927*f6dc9357SAndroid Build Coastguard Worker
928*f6dc9357SAndroid Build Coastguard Worker const CPartition &item = _items[index];
929*f6dc9357SAndroid Build Coastguard Worker
930*f6dc9357SAndroid Build Coastguard Worker switch (propID)
931*f6dc9357SAndroid Build Coastguard Worker {
932*f6dc9357SAndroid Build Coastguard Worker case kpidPath:
933*f6dc9357SAndroid Build Coastguard Worker {
934*f6dc9357SAndroid Build Coastguard Worker AString s;
935*f6dc9357SAndroid Build Coastguard Worker AddName36ToString(s, item.name, false);
936*f6dc9357SAndroid Build Coastguard Worker if (s.IsEmpty())
937*f6dc9357SAndroid Build Coastguard Worker s.Add_UInt32(index);
938*f6dc9357SAndroid Build Coastguard Worker if (item.num_extents != 0)
939*f6dc9357SAndroid Build Coastguard Worker {
940*f6dc9357SAndroid Build Coastguard Worker s.Add_Dot();
941*f6dc9357SAndroid Build Coastguard Worker s += (item.Ext ? item.Ext : "img");
942*f6dc9357SAndroid Build Coastguard Worker }
943*f6dc9357SAndroid Build Coastguard Worker prop = s;
944*f6dc9357SAndroid Build Coastguard Worker break;
945*f6dc9357SAndroid Build Coastguard Worker }
946*f6dc9357SAndroid Build Coastguard Worker
947*f6dc9357SAndroid Build Coastguard Worker case kpidSize: prop = item.GetSize(); break;
948*f6dc9357SAndroid Build Coastguard Worker case kpidPackSize: prop = item.GetPackSize(); break;
949*f6dc9357SAndroid Build Coastguard Worker case kpidNumBlocks: prop = item.num_extents; break;
950*f6dc9357SAndroid Build Coastguard Worker case kpidMethod:
951*f6dc9357SAndroid Build Coastguard Worker {
952*f6dc9357SAndroid Build Coastguard Worker const UInt32 m = item.MethodsMask;
953*f6dc9357SAndroid Build Coastguard Worker if (m != 0)
954*f6dc9357SAndroid Build Coastguard Worker {
955*f6dc9357SAndroid Build Coastguard Worker FLAGS_TO_PROP(g_Methods, m, prop);
956*f6dc9357SAndroid Build Coastguard Worker }
957*f6dc9357SAndroid Build Coastguard Worker break;
958*f6dc9357SAndroid Build Coastguard Worker }
959*f6dc9357SAndroid Build Coastguard Worker case kpidOffset:
960*f6dc9357SAndroid Build Coastguard Worker if (item.num_extents != 0)
961*f6dc9357SAndroid Build Coastguard Worker if (item.first_extent_index < Extents.Size())
962*f6dc9357SAndroid Build Coastguard Worker prop = Extents[item.first_extent_index].target_data << kSectorSizeLog;
963*f6dc9357SAndroid Build Coastguard Worker break;
964*f6dc9357SAndroid Build Coastguard Worker
965*f6dc9357SAndroid Build Coastguard Worker case kpidCharacts:
966*f6dc9357SAndroid Build Coastguard Worker {
967*f6dc9357SAndroid Build Coastguard Worker AString s;
968*f6dc9357SAndroid Build Coastguard Worker s += "group:";
969*f6dc9357SAndroid Build Coastguard Worker s.Add_UInt32(item.group_index);
970*f6dc9357SAndroid Build Coastguard Worker s.Add_Space();
971*f6dc9357SAndroid Build Coastguard Worker s += FlagsToString(g_PartitionAttr, Z7_ARRAY_SIZE(g_PartitionAttr), item.attributes);
972*f6dc9357SAndroid Build Coastguard Worker prop = s;
973*f6dc9357SAndroid Build Coastguard Worker break;
974*f6dc9357SAndroid Build Coastguard Worker }
975*f6dc9357SAndroid Build Coastguard Worker }
976*f6dc9357SAndroid Build Coastguard Worker
977*f6dc9357SAndroid Build Coastguard Worker prop.Detach(value);
978*f6dc9357SAndroid Build Coastguard Worker return S_OK;
979*f6dc9357SAndroid Build Coastguard Worker COM_TRY_END
980*f6dc9357SAndroid Build Coastguard Worker }
981*f6dc9357SAndroid Build Coastguard Worker
982*f6dc9357SAndroid Build Coastguard Worker
983*f6dc9357SAndroid Build Coastguard Worker
Z7_COM7F_IMF(CHandler::GetStream (UInt32 index,ISequentialInStream ** stream))984*f6dc9357SAndroid Build Coastguard Worker Z7_COM7F_IMF(CHandler::GetStream(UInt32 index, ISequentialInStream **stream))
985*f6dc9357SAndroid Build Coastguard Worker {
986*f6dc9357SAndroid Build Coastguard Worker COM_TRY_BEGIN
987*f6dc9357SAndroid Build Coastguard Worker *stream = NULL;
988*f6dc9357SAndroid Build Coastguard Worker
989*f6dc9357SAndroid Build Coastguard Worker const CPartition &item = _items[index];
990*f6dc9357SAndroid Build Coastguard Worker
991*f6dc9357SAndroid Build Coastguard Worker if (item.first_extent_index > Extents.Size()
992*f6dc9357SAndroid Build Coastguard Worker || item.num_extents > Extents.Size() - item.first_extent_index)
993*f6dc9357SAndroid Build Coastguard Worker return S_FALSE;
994*f6dc9357SAndroid Build Coastguard Worker
995*f6dc9357SAndroid Build Coastguard Worker if (item.num_extents == 0)
996*f6dc9357SAndroid Build Coastguard Worker return CreateLimitedInStream(_stream, 0, 0, stream);
997*f6dc9357SAndroid Build Coastguard Worker
998*f6dc9357SAndroid Build Coastguard Worker if (item.num_extents == 1)
999*f6dc9357SAndroid Build Coastguard Worker {
1000*f6dc9357SAndroid Build Coastguard Worker const CExtent &e = Extents[item.first_extent_index];
1001*f6dc9357SAndroid Build Coastguard Worker if (e.IsRAW())
1002*f6dc9357SAndroid Build Coastguard Worker {
1003*f6dc9357SAndroid Build Coastguard Worker const UInt64 pos = e.target_data << kSectorSizeLog;
1004*f6dc9357SAndroid Build Coastguard Worker if ((pos >> kSectorSizeLog) != e.target_data)
1005*f6dc9357SAndroid Build Coastguard Worker return S_FALSE;
1006*f6dc9357SAndroid Build Coastguard Worker const UInt64 size = item.GetSize();
1007*f6dc9357SAndroid Build Coastguard Worker if (pos + size < pos)
1008*f6dc9357SAndroid Build Coastguard Worker return S_FALSE;
1009*f6dc9357SAndroid Build Coastguard Worker return CreateLimitedInStream(_stream, pos, size, stream);
1010*f6dc9357SAndroid Build Coastguard Worker }
1011*f6dc9357SAndroid Build Coastguard Worker }
1012*f6dc9357SAndroid Build Coastguard Worker
1013*f6dc9357SAndroid Build Coastguard Worker CExtentsStream *extentStreamSpec = new CExtentsStream();
1014*f6dc9357SAndroid Build Coastguard Worker CMyComPtr<ISequentialInStream> extentStream = extentStreamSpec;
1015*f6dc9357SAndroid Build Coastguard Worker
1016*f6dc9357SAndroid Build Coastguard Worker // const unsigned kNumDebugExtents = 10;
1017*f6dc9357SAndroid Build Coastguard Worker extentStreamSpec->Extents.Reserve(item.num_extents + 1
1018*f6dc9357SAndroid Build Coastguard Worker // + kNumDebugExtents
1019*f6dc9357SAndroid Build Coastguard Worker );
1020*f6dc9357SAndroid Build Coastguard Worker
1021*f6dc9357SAndroid Build Coastguard Worker UInt64 virt = 0;
1022*f6dc9357SAndroid Build Coastguard Worker for (UInt32 k = 0; k < item.num_extents; k++)
1023*f6dc9357SAndroid Build Coastguard Worker {
1024*f6dc9357SAndroid Build Coastguard Worker const CExtent &e = Extents[item.first_extent_index + k];
1025*f6dc9357SAndroid Build Coastguard Worker
1026*f6dc9357SAndroid Build Coastguard Worker CSeekExtent se;
1027*f6dc9357SAndroid Build Coastguard Worker {
1028*f6dc9357SAndroid Build Coastguard Worker const UInt64 numSectors = e.num_sectors;
1029*f6dc9357SAndroid Build Coastguard Worker if (numSectors == 0)
1030*f6dc9357SAndroid Build Coastguard Worker {
1031*f6dc9357SAndroid Build Coastguard Worker continue;
1032*f6dc9357SAndroid Build Coastguard Worker // return S_FALSE;
1033*f6dc9357SAndroid Build Coastguard Worker }
1034*f6dc9357SAndroid Build Coastguard Worker const UInt64 numBytes = numSectors << kSectorSizeLog;
1035*f6dc9357SAndroid Build Coastguard Worker if ((numBytes >> kSectorSizeLog) != numSectors)
1036*f6dc9357SAndroid Build Coastguard Worker return S_FALSE;
1037*f6dc9357SAndroid Build Coastguard Worker if (numBytes >= ((UInt64)1 << 63) - virt)
1038*f6dc9357SAndroid Build Coastguard Worker return S_FALSE;
1039*f6dc9357SAndroid Build Coastguard Worker
1040*f6dc9357SAndroid Build Coastguard Worker se.Virt = virt;
1041*f6dc9357SAndroid Build Coastguard Worker virt += numBytes;
1042*f6dc9357SAndroid Build Coastguard Worker }
1043*f6dc9357SAndroid Build Coastguard Worker
1044*f6dc9357SAndroid Build Coastguard Worker const UInt64 phySector = e.target_data;
1045*f6dc9357SAndroid Build Coastguard Worker if (e.target_type == LP_TARGET_TYPE_ZERO)
1046*f6dc9357SAndroid Build Coastguard Worker {
1047*f6dc9357SAndroid Build Coastguard Worker if (phySector != 0)
1048*f6dc9357SAndroid Build Coastguard Worker return S_FALSE;
1049*f6dc9357SAndroid Build Coastguard Worker se.SetAs_ZeroFill();
1050*f6dc9357SAndroid Build Coastguard Worker }
1051*f6dc9357SAndroid Build Coastguard Worker else if (e.target_type == LP_TARGET_TYPE_LINEAR)
1052*f6dc9357SAndroid Build Coastguard Worker {
1053*f6dc9357SAndroid Build Coastguard Worker se.Phy = phySector << kSectorSizeLog;
1054*f6dc9357SAndroid Build Coastguard Worker if ((se.Phy >> kSectorSizeLog) != phySector)
1055*f6dc9357SAndroid Build Coastguard Worker return S_FALSE;
1056*f6dc9357SAndroid Build Coastguard Worker if (se.Phy >= ((UInt64)1 << 63))
1057*f6dc9357SAndroid Build Coastguard Worker return S_FALSE;
1058*f6dc9357SAndroid Build Coastguard Worker }
1059*f6dc9357SAndroid Build Coastguard Worker else
1060*f6dc9357SAndroid Build Coastguard Worker return S_FALSE;
1061*f6dc9357SAndroid Build Coastguard Worker
1062*f6dc9357SAndroid Build Coastguard Worker extentStreamSpec->Extents.AddInReserved(se);
1063*f6dc9357SAndroid Build Coastguard Worker
1064*f6dc9357SAndroid Build Coastguard Worker /*
1065*f6dc9357SAndroid Build Coastguard Worker {
1066*f6dc9357SAndroid Build Coastguard Worker // for debug
1067*f6dc9357SAndroid Build Coastguard Worker const UInt64 kAdd = (e.num_sectors << kSectorSizeLog) / kNumDebugExtents;
1068*f6dc9357SAndroid Build Coastguard Worker for (unsigned i = 0; i < kNumDebugExtents; i++)
1069*f6dc9357SAndroid Build Coastguard Worker {
1070*f6dc9357SAndroid Build Coastguard Worker se.Phy += kAdd;
1071*f6dc9357SAndroid Build Coastguard Worker // se.Phy += (UInt64)1 << 63; // for debug
1072*f6dc9357SAndroid Build Coastguard Worker // se.Phy += 1; // for debug
1073*f6dc9357SAndroid Build Coastguard Worker se.Virt += kAdd;
1074*f6dc9357SAndroid Build Coastguard Worker extentStreamSpec->Extents.AddInReserved(se);
1075*f6dc9357SAndroid Build Coastguard Worker }
1076*f6dc9357SAndroid Build Coastguard Worker }
1077*f6dc9357SAndroid Build Coastguard Worker */
1078*f6dc9357SAndroid Build Coastguard Worker }
1079*f6dc9357SAndroid Build Coastguard Worker
1080*f6dc9357SAndroid Build Coastguard Worker CSeekExtent se;
1081*f6dc9357SAndroid Build Coastguard Worker se.Phy = 0;
1082*f6dc9357SAndroid Build Coastguard Worker se.Virt = virt;
1083*f6dc9357SAndroid Build Coastguard Worker extentStreamSpec->Extents.Add(se);
1084*f6dc9357SAndroid Build Coastguard Worker extentStreamSpec->Stream = _stream;
1085*f6dc9357SAndroid Build Coastguard Worker extentStreamSpec->Init();
1086*f6dc9357SAndroid Build Coastguard Worker *stream = extentStream.Detach();
1087*f6dc9357SAndroid Build Coastguard Worker
1088*f6dc9357SAndroid Build Coastguard Worker return S_OK;
1089*f6dc9357SAndroid Build Coastguard Worker COM_TRY_END
1090*f6dc9357SAndroid Build Coastguard Worker }
1091*f6dc9357SAndroid Build Coastguard Worker
1092*f6dc9357SAndroid Build Coastguard Worker
Z7_COM7F_IMF(CHandler::Extract (const UInt32 * indices,UInt32 numItems,Int32 testMode,IArchiveExtractCallback * extractCallback))1093*f6dc9357SAndroid Build Coastguard Worker Z7_COM7F_IMF(CHandler::Extract(const UInt32 *indices, UInt32 numItems,
1094*f6dc9357SAndroid Build Coastguard Worker Int32 testMode, IArchiveExtractCallback *extractCallback))
1095*f6dc9357SAndroid Build Coastguard Worker {
1096*f6dc9357SAndroid Build Coastguard Worker COM_TRY_BEGIN
1097*f6dc9357SAndroid Build Coastguard Worker const bool allFilesMode = (numItems == (UInt32)(Int32)-1);
1098*f6dc9357SAndroid Build Coastguard Worker if (allFilesMode)
1099*f6dc9357SAndroid Build Coastguard Worker numItems = _items.Size();
1100*f6dc9357SAndroid Build Coastguard Worker if (numItems == 0)
1101*f6dc9357SAndroid Build Coastguard Worker return S_OK;
1102*f6dc9357SAndroid Build Coastguard Worker UInt64 totalSize = 0;
1103*f6dc9357SAndroid Build Coastguard Worker UInt32 i;
1104*f6dc9357SAndroid Build Coastguard Worker for (i = 0; i < numItems; i++)
1105*f6dc9357SAndroid Build Coastguard Worker {
1106*f6dc9357SAndroid Build Coastguard Worker const UInt32 index = allFilesMode ? i : indices[i];
1107*f6dc9357SAndroid Build Coastguard Worker totalSize += _items[index].GetSize();
1108*f6dc9357SAndroid Build Coastguard Worker }
1109*f6dc9357SAndroid Build Coastguard Worker extractCallback->SetTotal(totalSize);
1110*f6dc9357SAndroid Build Coastguard Worker
1111*f6dc9357SAndroid Build Coastguard Worker totalSize = 0;
1112*f6dc9357SAndroid Build Coastguard Worker
1113*f6dc9357SAndroid Build Coastguard Worker NCompress::CCopyCoder *copyCoderSpec = new NCompress::CCopyCoder();
1114*f6dc9357SAndroid Build Coastguard Worker CMyComPtr<ICompressCoder> copyCoder = copyCoderSpec;
1115*f6dc9357SAndroid Build Coastguard Worker
1116*f6dc9357SAndroid Build Coastguard Worker CLocalProgress *lps = new CLocalProgress;
1117*f6dc9357SAndroid Build Coastguard Worker CMyComPtr<ICompressProgressInfo> progress = lps;
1118*f6dc9357SAndroid Build Coastguard Worker lps->Init(extractCallback, false);
1119*f6dc9357SAndroid Build Coastguard Worker
1120*f6dc9357SAndroid Build Coastguard Worker for (i = 0; i < numItems; i++)
1121*f6dc9357SAndroid Build Coastguard Worker {
1122*f6dc9357SAndroid Build Coastguard Worker lps->InSize = totalSize;
1123*f6dc9357SAndroid Build Coastguard Worker lps->OutSize = totalSize;
1124*f6dc9357SAndroid Build Coastguard Worker RINOK(lps->SetCur())
1125*f6dc9357SAndroid Build Coastguard Worker CMyComPtr<ISequentialOutStream> outStream;
1126*f6dc9357SAndroid Build Coastguard Worker const Int32 askMode = testMode ?
1127*f6dc9357SAndroid Build Coastguard Worker NExtract::NAskMode::kTest :
1128*f6dc9357SAndroid Build Coastguard Worker NExtract::NAskMode::kExtract;
1129*f6dc9357SAndroid Build Coastguard Worker const UInt32 index = allFilesMode ? i : indices[i];
1130*f6dc9357SAndroid Build Coastguard Worker
1131*f6dc9357SAndroid Build Coastguard Worker RINOK(extractCallback->GetStream(index, &outStream, askMode))
1132*f6dc9357SAndroid Build Coastguard Worker
1133*f6dc9357SAndroid Build Coastguard Worker const UInt64 size = _items[index].GetSize();
1134*f6dc9357SAndroid Build Coastguard Worker totalSize += size;
1135*f6dc9357SAndroid Build Coastguard Worker if (!testMode && !outStream)
1136*f6dc9357SAndroid Build Coastguard Worker continue;
1137*f6dc9357SAndroid Build Coastguard Worker
1138*f6dc9357SAndroid Build Coastguard Worker RINOK(extractCallback->PrepareOperation(askMode))
1139*f6dc9357SAndroid Build Coastguard Worker
1140*f6dc9357SAndroid Build Coastguard Worker CMyComPtr<ISequentialInStream> inStream;
1141*f6dc9357SAndroid Build Coastguard Worker const HRESULT hres = GetStream(index, &inStream);
1142*f6dc9357SAndroid Build Coastguard Worker int opRes = NExtract::NOperationResult::kUnsupportedMethod;
1143*f6dc9357SAndroid Build Coastguard Worker if (hres != S_FALSE)
1144*f6dc9357SAndroid Build Coastguard Worker {
1145*f6dc9357SAndroid Build Coastguard Worker if (hres != S_OK)
1146*f6dc9357SAndroid Build Coastguard Worker return hres;
1147*f6dc9357SAndroid Build Coastguard Worker RINOK(copyCoder->Code(inStream, outStream, NULL, NULL, progress))
1148*f6dc9357SAndroid Build Coastguard Worker opRes = NExtract::NOperationResult::kDataError;
1149*f6dc9357SAndroid Build Coastguard Worker if (copyCoderSpec->TotalSize == size)
1150*f6dc9357SAndroid Build Coastguard Worker opRes = NExtract::NOperationResult::kOK;
1151*f6dc9357SAndroid Build Coastguard Worker else if (copyCoderSpec->TotalSize < size)
1152*f6dc9357SAndroid Build Coastguard Worker opRes = NExtract::NOperationResult::kUnexpectedEnd;
1153*f6dc9357SAndroid Build Coastguard Worker }
1154*f6dc9357SAndroid Build Coastguard Worker outStream.Release();
1155*f6dc9357SAndroid Build Coastguard Worker RINOK(extractCallback->SetOperationResult(opRes))
1156*f6dc9357SAndroid Build Coastguard Worker }
1157*f6dc9357SAndroid Build Coastguard Worker
1158*f6dc9357SAndroid Build Coastguard Worker return S_OK;
1159*f6dc9357SAndroid Build Coastguard Worker COM_TRY_END
1160*f6dc9357SAndroid Build Coastguard Worker }
1161*f6dc9357SAndroid Build Coastguard Worker
1162*f6dc9357SAndroid Build Coastguard Worker
1163*f6dc9357SAndroid Build Coastguard Worker REGISTER_ARC_I(
1164*f6dc9357SAndroid Build Coastguard Worker "LP", "lpimg img", NULL, 0xc1,
1165*f6dc9357SAndroid Build Coastguard Worker k_Signature,
1166*f6dc9357SAndroid Build Coastguard Worker LP_PARTITION_RESERVED_BYTES,
1167*f6dc9357SAndroid Build Coastguard Worker 0,
1168*f6dc9357SAndroid Build Coastguard Worker NULL)
1169*f6dc9357SAndroid Build Coastguard Worker
1170*f6dc9357SAndroid Build Coastguard Worker }}
1171