1*f6dc9357SAndroid Build Coastguard Worker // SquashfsHandler.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/Alloc.h"
6*f6dc9357SAndroid Build Coastguard Worker #include "../../../C/LzmaDec.h"
7*f6dc9357SAndroid Build Coastguard Worker #include "../../../C/Xz.h"
8*f6dc9357SAndroid Build Coastguard Worker #include "../../../C/ZstdDec.h"
9*f6dc9357SAndroid Build Coastguard Worker #include "../../../C/CpuArch.h"
10*f6dc9357SAndroid Build Coastguard Worker
11*f6dc9357SAndroid Build Coastguard Worker #include "../../Common/ComTry.h"
12*f6dc9357SAndroid Build Coastguard Worker #include "../../Common/MyLinux.h"
13*f6dc9357SAndroid Build Coastguard Worker #include "../../Common/IntToString.h"
14*f6dc9357SAndroid Build Coastguard Worker #include "../../Common/StringConvert.h"
15*f6dc9357SAndroid Build Coastguard Worker #include "../../Common/UTFConvert.h"
16*f6dc9357SAndroid Build Coastguard Worker
17*f6dc9357SAndroid Build Coastguard Worker #include "../../Windows/PropVariantUtils.h"
18*f6dc9357SAndroid Build Coastguard Worker #include "../../Windows/TimeUtils.h"
19*f6dc9357SAndroid Build Coastguard Worker
20*f6dc9357SAndroid Build Coastguard Worker #include "../Common/CWrappers.h"
21*f6dc9357SAndroid Build Coastguard Worker #include "../Common/LimitedStreams.h"
22*f6dc9357SAndroid Build Coastguard Worker #include "../Common/ProgressUtils.h"
23*f6dc9357SAndroid Build Coastguard Worker #include "../Common/RegisterArc.h"
24*f6dc9357SAndroid Build Coastguard Worker #include "../Common/StreamObjects.h"
25*f6dc9357SAndroid Build Coastguard Worker #include "../Common/StreamUtils.h"
26*f6dc9357SAndroid Build Coastguard Worker
27*f6dc9357SAndroid Build Coastguard Worker #include "../Compress/CopyCoder.h"
28*f6dc9357SAndroid Build Coastguard Worker #include "../Compress/ZlibDecoder.h"
29*f6dc9357SAndroid Build Coastguard Worker // #include "../Compress/LzmaDecoder.h"
30*f6dc9357SAndroid Build Coastguard Worker
31*f6dc9357SAndroid Build Coastguard Worker namespace NArchive {
32*f6dc9357SAndroid Build Coastguard Worker namespace NSquashfs {
33*f6dc9357SAndroid Build Coastguard Worker
34*f6dc9357SAndroid Build Coastguard Worker static const UInt32 kNumFilesMax = 1 << 28;
35*f6dc9357SAndroid Build Coastguard Worker static const unsigned kNumDirLevelsMax = 1 << 10;
36*f6dc9357SAndroid Build Coastguard Worker
37*f6dc9357SAndroid Build Coastguard Worker // Layout: Header, Data, inodes, Directories, Fragments, UIDs, GIDs
38*f6dc9357SAndroid Build Coastguard Worker
39*f6dc9357SAndroid Build Coastguard Worker /*
40*f6dc9357SAndroid Build Coastguard Worker #define Get16(p) (be ? GetBe16(p) : GetUi16(p))
41*f6dc9357SAndroid Build Coastguard Worker #define Get32(p) (be ? GetBe32(p) : GetUi32(p))
42*f6dc9357SAndroid Build Coastguard Worker #define Get64(p) (be ? GetBe64(p) : GetUi64(p))
43*f6dc9357SAndroid Build Coastguard Worker */
44*f6dc9357SAndroid Build Coastguard Worker
Get16b(const Byte * p,bool be)45*f6dc9357SAndroid Build Coastguard Worker static UInt16 Get16b(const Byte *p, bool be) { return be ? GetBe16(p) : GetUi16(p); }
Get32b(const Byte * p,bool be)46*f6dc9357SAndroid Build Coastguard Worker static UInt32 Get32b(const Byte *p, bool be) { return be ? GetBe32(p) : GetUi32(p); }
Get64b(const Byte * p,bool be)47*f6dc9357SAndroid Build Coastguard Worker static UInt64 Get64b(const Byte *p, bool be) { return be ? GetBe64(p) : GetUi64(p); }
48*f6dc9357SAndroid Build Coastguard Worker
49*f6dc9357SAndroid Build Coastguard Worker #define Get16(p) Get16b(p, be)
50*f6dc9357SAndroid Build Coastguard Worker #define Get32(p) Get32b(p, be)
51*f6dc9357SAndroid Build Coastguard Worker #define Get64(p) Get64b(p, be)
52*f6dc9357SAndroid Build Coastguard Worker
53*f6dc9357SAndroid Build Coastguard Worker #define LE_16(offs, dest) dest = GetUi16(p + (offs))
54*f6dc9357SAndroid Build Coastguard Worker #define LE_32(offs, dest) dest = GetUi32(p + (offs))
55*f6dc9357SAndroid Build Coastguard Worker #define LE_64(offs, dest) dest = GetUi64(p + (offs))
56*f6dc9357SAndroid Build Coastguard Worker
57*f6dc9357SAndroid Build Coastguard Worker #define GET_16(offs, dest) dest = Get16(p + (offs))
58*f6dc9357SAndroid Build Coastguard Worker #define GET_32(offs, dest) dest = Get32(p + (offs))
59*f6dc9357SAndroid Build Coastguard Worker #define GET_64(offs, dest) dest = Get64(p + (offs))
60*f6dc9357SAndroid Build Coastguard Worker
61*f6dc9357SAndroid Build Coastguard Worker static const UInt32 kSignature32_LE = 0x73717368;
62*f6dc9357SAndroid Build Coastguard Worker static const UInt32 kSignature32_BE = 0x68737173;
63*f6dc9357SAndroid Build Coastguard Worker static const UInt32 kSignature32_LZ = 0x71736873;
64*f6dc9357SAndroid Build Coastguard Worker static const UInt32 kSignature32_B2 = 0x73687371;
65*f6dc9357SAndroid Build Coastguard Worker
66*f6dc9357SAndroid Build Coastguard Worker #define kMethod_ZLIB 1
67*f6dc9357SAndroid Build Coastguard Worker #define kMethod_LZMA 2
68*f6dc9357SAndroid Build Coastguard Worker #define kMethod_LZO 3
69*f6dc9357SAndroid Build Coastguard Worker #define kMethod_XZ 4
70*f6dc9357SAndroid Build Coastguard Worker // #define kMethod_LZ4 5
71*f6dc9357SAndroid Build Coastguard Worker #define kMethod_ZSTD 6
72*f6dc9357SAndroid Build Coastguard Worker
73*f6dc9357SAndroid Build Coastguard Worker static const char * const k_Methods[] =
74*f6dc9357SAndroid Build Coastguard Worker {
75*f6dc9357SAndroid Build Coastguard Worker "0"
76*f6dc9357SAndroid Build Coastguard Worker , "ZLIB"
77*f6dc9357SAndroid Build Coastguard Worker , "LZMA"
78*f6dc9357SAndroid Build Coastguard Worker , "LZO"
79*f6dc9357SAndroid Build Coastguard Worker , "XZ"
80*f6dc9357SAndroid Build Coastguard Worker , "LZ4"
81*f6dc9357SAndroid Build Coastguard Worker , "ZSTD"
82*f6dc9357SAndroid Build Coastguard Worker };
83*f6dc9357SAndroid Build Coastguard Worker
84*f6dc9357SAndroid Build Coastguard Worker static const unsigned kMetadataBlockSizeLog = 13;
85*f6dc9357SAndroid Build Coastguard Worker static const UInt32 kMetadataBlockSize = (1 << kMetadataBlockSizeLog);
86*f6dc9357SAndroid Build Coastguard Worker
87*f6dc9357SAndroid Build Coastguard Worker enum
88*f6dc9357SAndroid Build Coastguard Worker {
89*f6dc9357SAndroid Build Coastguard Worker kType_IPC,
90*f6dc9357SAndroid Build Coastguard Worker kType_DIR,
91*f6dc9357SAndroid Build Coastguard Worker kType_FILE,
92*f6dc9357SAndroid Build Coastguard Worker kType_LNK,
93*f6dc9357SAndroid Build Coastguard Worker kType_BLK,
94*f6dc9357SAndroid Build Coastguard Worker kType_CHR,
95*f6dc9357SAndroid Build Coastguard Worker kType_FIFO,
96*f6dc9357SAndroid Build Coastguard Worker kType_SOCK
97*f6dc9357SAndroid Build Coastguard Worker };
98*f6dc9357SAndroid Build Coastguard Worker
99*f6dc9357SAndroid Build Coastguard Worker static const UInt32 k_TypeToMode[] =
100*f6dc9357SAndroid Build Coastguard Worker {
101*f6dc9357SAndroid Build Coastguard Worker 0,
102*f6dc9357SAndroid Build Coastguard Worker MY_LIN_S_IFDIR, MY_LIN_S_IFREG, MY_LIN_S_IFLNK, MY_LIN_S_IFBLK, MY_LIN_S_IFCHR, MY_LIN_S_IFIFO, MY_LIN_S_IFSOCK,
103*f6dc9357SAndroid Build Coastguard Worker MY_LIN_S_IFDIR, MY_LIN_S_IFREG, MY_LIN_S_IFLNK, MY_LIN_S_IFBLK, MY_LIN_S_IFCHR, MY_LIN_S_IFIFO, MY_LIN_S_IFSOCK
104*f6dc9357SAndroid Build Coastguard Worker };
105*f6dc9357SAndroid Build Coastguard Worker
106*f6dc9357SAndroid Build Coastguard Worker
107*f6dc9357SAndroid Build Coastguard Worker enum
108*f6dc9357SAndroid Build Coastguard Worker {
109*f6dc9357SAndroid Build Coastguard Worker kFlag_UNC_INODES,
110*f6dc9357SAndroid Build Coastguard Worker kFlag_UNC_DATA,
111*f6dc9357SAndroid Build Coastguard Worker kFlag_CHECK,
112*f6dc9357SAndroid Build Coastguard Worker kFlag_UNC_FRAGS,
113*f6dc9357SAndroid Build Coastguard Worker kFlag_NO_FRAGS,
114*f6dc9357SAndroid Build Coastguard Worker kFlag_ALWAYS_FRAG,
115*f6dc9357SAndroid Build Coastguard Worker kFlag_DUPLICATE,
116*f6dc9357SAndroid Build Coastguard Worker kFlag_EXPORT
117*f6dc9357SAndroid Build Coastguard Worker };
118*f6dc9357SAndroid Build Coastguard Worker
119*f6dc9357SAndroid Build Coastguard Worker static const char * const k_Flags[] =
120*f6dc9357SAndroid Build Coastguard Worker {
121*f6dc9357SAndroid Build Coastguard Worker "UNCOMPRESSED_INODES"
122*f6dc9357SAndroid Build Coastguard Worker , "UNCOMPRESSED_DATA"
123*f6dc9357SAndroid Build Coastguard Worker , "CHECK"
124*f6dc9357SAndroid Build Coastguard Worker , "UNCOMPRESSED_FRAGMENTS"
125*f6dc9357SAndroid Build Coastguard Worker , "NO_FRAGMENTS"
126*f6dc9357SAndroid Build Coastguard Worker , "ALWAYS_FRAGMENTS"
127*f6dc9357SAndroid Build Coastguard Worker , "DUPLICATES_REMOVED"
128*f6dc9357SAndroid Build Coastguard Worker , "EXPORTABLE"
129*f6dc9357SAndroid Build Coastguard Worker , "UNCOMPRESSED_XATTRS"
130*f6dc9357SAndroid Build Coastguard Worker , "NO_XATTRS"
131*f6dc9357SAndroid Build Coastguard Worker , "COMPRESSOR_OPTIONS"
132*f6dc9357SAndroid Build Coastguard Worker , "UNCOMPRESSED_IDS"
133*f6dc9357SAndroid Build Coastguard Worker };
134*f6dc9357SAndroid Build Coastguard Worker
135*f6dc9357SAndroid Build Coastguard Worker static const UInt32 kNotCompressedBit16 = 1 << 15;
136*f6dc9357SAndroid Build Coastguard Worker static const UInt32 kNotCompressedBit32 = 1 << 24;
137*f6dc9357SAndroid Build Coastguard Worker
138*f6dc9357SAndroid Build Coastguard Worker #define GET_COMPRESSED_BLOCK_SIZE(size) ((size) & ~kNotCompressedBit32)
139*f6dc9357SAndroid Build Coastguard Worker #define IS_COMPRESSED_BLOCK(size) (((size) & kNotCompressedBit32) == 0)
140*f6dc9357SAndroid Build Coastguard Worker
141*f6dc9357SAndroid Build Coastguard Worker // static const UInt32 kHeaderSize1 = 0x33;
142*f6dc9357SAndroid Build Coastguard Worker // static const UInt32 kHeaderSize2 = 0x3F;
143*f6dc9357SAndroid Build Coastguard Worker static const UInt32 kHeaderSize3 = 0x77;
144*f6dc9357SAndroid Build Coastguard Worker // static const UInt32 kHeaderSize4 = 0x60;
145*f6dc9357SAndroid Build Coastguard Worker
146*f6dc9357SAndroid Build Coastguard Worker struct CHeader
147*f6dc9357SAndroid Build Coastguard Worker {
148*f6dc9357SAndroid Build Coastguard Worker bool be;
149*f6dc9357SAndroid Build Coastguard Worker bool SeveralMethods;
150*f6dc9357SAndroid Build Coastguard Worker Byte NumUids;
151*f6dc9357SAndroid Build Coastguard Worker Byte NumGids;
152*f6dc9357SAndroid Build Coastguard Worker
153*f6dc9357SAndroid Build Coastguard Worker UInt32 NumInodes;
154*f6dc9357SAndroid Build Coastguard Worker UInt32 CTime;
155*f6dc9357SAndroid Build Coastguard Worker UInt32 BlockSize;
156*f6dc9357SAndroid Build Coastguard Worker UInt32 NumFrags;
157*f6dc9357SAndroid Build Coastguard Worker UInt16 Method;
158*f6dc9357SAndroid Build Coastguard Worker UInt16 BlockSizeLog;
159*f6dc9357SAndroid Build Coastguard Worker UInt16 Flags;
160*f6dc9357SAndroid Build Coastguard Worker UInt16 NumIDs;
161*f6dc9357SAndroid Build Coastguard Worker UInt16 Major;
162*f6dc9357SAndroid Build Coastguard Worker UInt16 Minor;
163*f6dc9357SAndroid Build Coastguard Worker UInt64 RootInode;
164*f6dc9357SAndroid Build Coastguard Worker UInt64 Size;
165*f6dc9357SAndroid Build Coastguard Worker UInt64 UidTable;
166*f6dc9357SAndroid Build Coastguard Worker UInt64 GidTable;
167*f6dc9357SAndroid Build Coastguard Worker UInt64 XattrIdTable;
168*f6dc9357SAndroid Build Coastguard Worker UInt64 InodeTable;
169*f6dc9357SAndroid Build Coastguard Worker UInt64 DirTable;
170*f6dc9357SAndroid Build Coastguard Worker UInt64 FragTable;
171*f6dc9357SAndroid Build Coastguard Worker UInt64 LookupTable;
172*f6dc9357SAndroid Build Coastguard Worker
Parse3NArchive::NSquashfs::CHeader173*f6dc9357SAndroid Build Coastguard Worker void Parse3(const Byte *p)
174*f6dc9357SAndroid Build Coastguard Worker {
175*f6dc9357SAndroid Build Coastguard Worker Method = kMethod_ZLIB;
176*f6dc9357SAndroid Build Coastguard Worker GET_32 (0x08, Size);
177*f6dc9357SAndroid Build Coastguard Worker GET_32 (0x0C, UidTable);
178*f6dc9357SAndroid Build Coastguard Worker GET_32 (0x10, GidTable);
179*f6dc9357SAndroid Build Coastguard Worker GET_32 (0x14, InodeTable);
180*f6dc9357SAndroid Build Coastguard Worker GET_32 (0x18, DirTable);
181*f6dc9357SAndroid Build Coastguard Worker GET_16 (0x20, BlockSize);
182*f6dc9357SAndroid Build Coastguard Worker GET_16 (0x22, BlockSizeLog);
183*f6dc9357SAndroid Build Coastguard Worker Flags = p[0x24];
184*f6dc9357SAndroid Build Coastguard Worker NumUids = p[0x25];
185*f6dc9357SAndroid Build Coastguard Worker NumGids = p[0x26];
186*f6dc9357SAndroid Build Coastguard Worker GET_32 (0x27, CTime);
187*f6dc9357SAndroid Build Coastguard Worker GET_64 (0x2B, RootInode);
188*f6dc9357SAndroid Build Coastguard Worker NumFrags = 0;
189*f6dc9357SAndroid Build Coastguard Worker FragTable = UidTable;
190*f6dc9357SAndroid Build Coastguard Worker
191*f6dc9357SAndroid Build Coastguard Worker if (Major >= 2)
192*f6dc9357SAndroid Build Coastguard Worker {
193*f6dc9357SAndroid Build Coastguard Worker GET_32 (0x33, BlockSize);
194*f6dc9357SAndroid Build Coastguard Worker GET_32 (0x37, NumFrags);
195*f6dc9357SAndroid Build Coastguard Worker GET_32 (0x3B, FragTable);
196*f6dc9357SAndroid Build Coastguard Worker if (Major == 3)
197*f6dc9357SAndroid Build Coastguard Worker {
198*f6dc9357SAndroid Build Coastguard Worker GET_64 (0x3F, Size);
199*f6dc9357SAndroid Build Coastguard Worker GET_64 (0x47, UidTable);
200*f6dc9357SAndroid Build Coastguard Worker GET_64 (0x4F, GidTable);
201*f6dc9357SAndroid Build Coastguard Worker GET_64 (0x57, InodeTable);
202*f6dc9357SAndroid Build Coastguard Worker GET_64 (0x5F, DirTable);
203*f6dc9357SAndroid Build Coastguard Worker GET_64 (0x67, FragTable);
204*f6dc9357SAndroid Build Coastguard Worker GET_64 (0x6F, LookupTable);
205*f6dc9357SAndroid Build Coastguard Worker }
206*f6dc9357SAndroid Build Coastguard Worker }
207*f6dc9357SAndroid Build Coastguard Worker }
208*f6dc9357SAndroid Build Coastguard Worker
Parse4NArchive::NSquashfs::CHeader209*f6dc9357SAndroid Build Coastguard Worker void Parse4(const Byte *p)
210*f6dc9357SAndroid Build Coastguard Worker {
211*f6dc9357SAndroid Build Coastguard Worker LE_32 (0x08, CTime);
212*f6dc9357SAndroid Build Coastguard Worker LE_32 (0x0C, BlockSize);
213*f6dc9357SAndroid Build Coastguard Worker LE_32 (0x10, NumFrags);
214*f6dc9357SAndroid Build Coastguard Worker LE_16 (0x14, Method);
215*f6dc9357SAndroid Build Coastguard Worker LE_16 (0x16, BlockSizeLog);
216*f6dc9357SAndroid Build Coastguard Worker LE_16 (0x18, Flags);
217*f6dc9357SAndroid Build Coastguard Worker LE_16 (0x1A, NumIDs);
218*f6dc9357SAndroid Build Coastguard Worker LE_64 (0x20, RootInode);
219*f6dc9357SAndroid Build Coastguard Worker LE_64 (0x28, Size);
220*f6dc9357SAndroid Build Coastguard Worker LE_64 (0x30, UidTable);
221*f6dc9357SAndroid Build Coastguard Worker LE_64 (0x38, XattrIdTable);
222*f6dc9357SAndroid Build Coastguard Worker LE_64 (0x40, InodeTable);
223*f6dc9357SAndroid Build Coastguard Worker LE_64 (0x48, DirTable);
224*f6dc9357SAndroid Build Coastguard Worker LE_64 (0x50, FragTable);
225*f6dc9357SAndroid Build Coastguard Worker LE_64 (0x58, LookupTable);
226*f6dc9357SAndroid Build Coastguard Worker GidTable = 0;
227*f6dc9357SAndroid Build Coastguard Worker }
228*f6dc9357SAndroid Build Coastguard Worker
ParseNArchive::NSquashfs::CHeader229*f6dc9357SAndroid Build Coastguard Worker bool Parse(const Byte *p)
230*f6dc9357SAndroid Build Coastguard Worker {
231*f6dc9357SAndroid Build Coastguard Worker be = false;
232*f6dc9357SAndroid Build Coastguard Worker SeveralMethods = false;
233*f6dc9357SAndroid Build Coastguard Worker switch (GetUi32(p))
234*f6dc9357SAndroid Build Coastguard Worker {
235*f6dc9357SAndroid Build Coastguard Worker case kSignature32_LE: break;
236*f6dc9357SAndroid Build Coastguard Worker case kSignature32_BE: be = true; break;
237*f6dc9357SAndroid Build Coastguard Worker case kSignature32_LZ: SeveralMethods = true; break;
238*f6dc9357SAndroid Build Coastguard Worker case kSignature32_B2: SeveralMethods = true; be = true; break;
239*f6dc9357SAndroid Build Coastguard Worker default: return false;
240*f6dc9357SAndroid Build Coastguard Worker }
241*f6dc9357SAndroid Build Coastguard Worker GET_32 (4, NumInodes);
242*f6dc9357SAndroid Build Coastguard Worker GET_16 (0x1C, Major);
243*f6dc9357SAndroid Build Coastguard Worker GET_16 (0x1E, Minor);
244*f6dc9357SAndroid Build Coastguard Worker if (Major <= 3)
245*f6dc9357SAndroid Build Coastguard Worker Parse3(p);
246*f6dc9357SAndroid Build Coastguard Worker else
247*f6dc9357SAndroid Build Coastguard Worker {
248*f6dc9357SAndroid Build Coastguard Worker if (be)
249*f6dc9357SAndroid Build Coastguard Worker return false;
250*f6dc9357SAndroid Build Coastguard Worker Parse4(p);
251*f6dc9357SAndroid Build Coastguard Worker }
252*f6dc9357SAndroid Build Coastguard Worker return
253*f6dc9357SAndroid Build Coastguard Worker InodeTable < DirTable &&
254*f6dc9357SAndroid Build Coastguard Worker DirTable <= FragTable &&
255*f6dc9357SAndroid Build Coastguard Worker FragTable <= Size &&
256*f6dc9357SAndroid Build Coastguard Worker UidTable <= Size &&
257*f6dc9357SAndroid Build Coastguard Worker BlockSizeLog >= 12 &&
258*f6dc9357SAndroid Build Coastguard Worker BlockSizeLog < 31 &&
259*f6dc9357SAndroid Build Coastguard Worker BlockSize == ((UInt32)1 << BlockSizeLog);
260*f6dc9357SAndroid Build Coastguard Worker }
261*f6dc9357SAndroid Build Coastguard Worker
IsSupportedNArchive::NSquashfs::CHeader262*f6dc9357SAndroid Build Coastguard Worker bool IsSupported() const { return Major > 0 && Major <= 4 && BlockSizeLog <= 23; }
IsOldVersionNArchive::NSquashfs::CHeader263*f6dc9357SAndroid Build Coastguard Worker bool IsOldVersion() const { return Major < 4; }
NeedCheckDataNArchive::NSquashfs::CHeader264*f6dc9357SAndroid Build Coastguard Worker bool NeedCheckData() const { return (Flags & (1 << kFlag_CHECK)) != 0; }
GetFileNameOffsetNArchive::NSquashfs::CHeader265*f6dc9357SAndroid Build Coastguard Worker unsigned GetFileNameOffset() const { return Major <= 2 ? 3 : (Major == 3 ? 5 : 8); }
GetSymLinkOffsetNArchive::NSquashfs::CHeader266*f6dc9357SAndroid Build Coastguard Worker unsigned GetSymLinkOffset() const { return Major <= 1 ? 5: (Major <= 2 ? 6: (Major == 3 ? 18 : 24)); }
GetSpecGuidIndexNArchive::NSquashfs::CHeader267*f6dc9357SAndroid Build Coastguard Worker unsigned GetSpecGuidIndex() const { return Major <= 1 ? 0xF: 0xFF; }
268*f6dc9357SAndroid Build Coastguard Worker };
269*f6dc9357SAndroid Build Coastguard Worker
270*f6dc9357SAndroid Build Coastguard Worker static const UInt32 kFrag_Empty = (UInt32)(Int32)-1;
271*f6dc9357SAndroid Build Coastguard Worker // static const UInt32 kXattr_Empty = (UInt32)(Int32)-1;
272*f6dc9357SAndroid Build Coastguard Worker
273*f6dc9357SAndroid Build Coastguard Worker struct CNode
274*f6dc9357SAndroid Build Coastguard Worker {
275*f6dc9357SAndroid Build Coastguard Worker UInt16 Type;
276*f6dc9357SAndroid Build Coastguard Worker UInt16 Mode;
277*f6dc9357SAndroid Build Coastguard Worker UInt16 Uid;
278*f6dc9357SAndroid Build Coastguard Worker UInt16 Gid;
279*f6dc9357SAndroid Build Coastguard Worker UInt32 Frag;
280*f6dc9357SAndroid Build Coastguard Worker UInt32 Offset;
281*f6dc9357SAndroid Build Coastguard Worker // UInt32 MTime;
282*f6dc9357SAndroid Build Coastguard Worker // UInt32 Number;
283*f6dc9357SAndroid Build Coastguard Worker // UInt32 NumLinks;
284*f6dc9357SAndroid Build Coastguard Worker // UInt32 RDev;
285*f6dc9357SAndroid Build Coastguard Worker // UInt32 Xattr;
286*f6dc9357SAndroid Build Coastguard Worker // UInt32 Parent;
287*f6dc9357SAndroid Build Coastguard Worker
288*f6dc9357SAndroid Build Coastguard Worker UInt64 FileSize;
289*f6dc9357SAndroid Build Coastguard Worker UInt64 StartBlock;
290*f6dc9357SAndroid Build Coastguard Worker // UInt64 Sparse;
291*f6dc9357SAndroid Build Coastguard Worker
292*f6dc9357SAndroid Build Coastguard Worker UInt32 Parse1(const Byte *p, UInt32 size, const CHeader &_h);
293*f6dc9357SAndroid Build Coastguard Worker UInt32 Parse2(const Byte *p, UInt32 size, const CHeader &_h);
294*f6dc9357SAndroid Build Coastguard Worker UInt32 Parse3(const Byte *p, UInt32 size, const CHeader &_h);
295*f6dc9357SAndroid Build Coastguard Worker UInt32 Parse4(const Byte *p, UInt32 size, const CHeader &_h);
296*f6dc9357SAndroid Build Coastguard Worker
IsDirNArchive::NSquashfs::CNode297*f6dc9357SAndroid Build Coastguard Worker bool IsDir() const { return (Type == kType_DIR || Type == kType_DIR + 7); }
IsLinkNArchive::NSquashfs::CNode298*f6dc9357SAndroid Build Coastguard Worker bool IsLink() const { return (Type == kType_LNK || Type == kType_LNK + 7); }
GetSizeNArchive::NSquashfs::CNode299*f6dc9357SAndroid Build Coastguard Worker UInt64 GetSize() const { return IsDir() ? 0 : FileSize; }
300*f6dc9357SAndroid Build Coastguard Worker
ThereAreFragsNArchive::NSquashfs::CNode301*f6dc9357SAndroid Build Coastguard Worker bool ThereAreFrags() const { return Frag != kFrag_Empty; }
GetNumBlocksNArchive::NSquashfs::CNode302*f6dc9357SAndroid Build Coastguard Worker UInt64 GetNumBlocks(const CHeader &_h) const
303*f6dc9357SAndroid Build Coastguard Worker {
304*f6dc9357SAndroid Build Coastguard Worker return (FileSize >> _h.BlockSizeLog) +
305*f6dc9357SAndroid Build Coastguard Worker (!ThereAreFrags() && (FileSize & (_h.BlockSize - 1)) != 0);
306*f6dc9357SAndroid Build Coastguard Worker }
307*f6dc9357SAndroid Build Coastguard Worker };
308*f6dc9357SAndroid Build Coastguard Worker
Parse1(const Byte * p,UInt32 size,const CHeader & _h)309*f6dc9357SAndroid Build Coastguard Worker UInt32 CNode::Parse1(const Byte *p, UInt32 size, const CHeader &_h)
310*f6dc9357SAndroid Build Coastguard Worker {
311*f6dc9357SAndroid Build Coastguard Worker const bool be = _h.be;
312*f6dc9357SAndroid Build Coastguard Worker if (size < 4)
313*f6dc9357SAndroid Build Coastguard Worker return 0;
314*f6dc9357SAndroid Build Coastguard Worker {
315*f6dc9357SAndroid Build Coastguard Worker const UInt32 t = Get16(p);
316*f6dc9357SAndroid Build Coastguard Worker if (be)
317*f6dc9357SAndroid Build Coastguard Worker {
318*f6dc9357SAndroid Build Coastguard Worker Type = (UInt16)(t >> 12);
319*f6dc9357SAndroid Build Coastguard Worker Mode = (UInt16)(t & 0xFFF);
320*f6dc9357SAndroid Build Coastguard Worker Uid = (UInt16)(p[2] >> 4);
321*f6dc9357SAndroid Build Coastguard Worker Gid = (UInt16)(p[2] & 0xF);
322*f6dc9357SAndroid Build Coastguard Worker }
323*f6dc9357SAndroid Build Coastguard Worker else
324*f6dc9357SAndroid Build Coastguard Worker {
325*f6dc9357SAndroid Build Coastguard Worker Type = (UInt16)(t & 0xF);
326*f6dc9357SAndroid Build Coastguard Worker Mode = (UInt16)(t >> 4);
327*f6dc9357SAndroid Build Coastguard Worker Uid = (UInt16)(p[2] & 0xF);
328*f6dc9357SAndroid Build Coastguard Worker Gid = (UInt16)(p[2] >> 4);
329*f6dc9357SAndroid Build Coastguard Worker }
330*f6dc9357SAndroid Build Coastguard Worker }
331*f6dc9357SAndroid Build Coastguard Worker
332*f6dc9357SAndroid Build Coastguard Worker // Xattr = kXattr_Empty;
333*f6dc9357SAndroid Build Coastguard Worker // MTime = 0;
334*f6dc9357SAndroid Build Coastguard Worker FileSize = 0;
335*f6dc9357SAndroid Build Coastguard Worker StartBlock = 0;
336*f6dc9357SAndroid Build Coastguard Worker Frag = kFrag_Empty;
337*f6dc9357SAndroid Build Coastguard Worker
338*f6dc9357SAndroid Build Coastguard Worker if (Type == 0)
339*f6dc9357SAndroid Build Coastguard Worker {
340*f6dc9357SAndroid Build Coastguard Worker Byte t = p[3];
341*f6dc9357SAndroid Build Coastguard Worker if (be)
342*f6dc9357SAndroid Build Coastguard Worker {
343*f6dc9357SAndroid Build Coastguard Worker Type = (UInt16)(t >> 4);
344*f6dc9357SAndroid Build Coastguard Worker Offset = (UInt16)(t & 0xF);
345*f6dc9357SAndroid Build Coastguard Worker }
346*f6dc9357SAndroid Build Coastguard Worker else
347*f6dc9357SAndroid Build Coastguard Worker {
348*f6dc9357SAndroid Build Coastguard Worker Type = (UInt16)(t & 0xF);
349*f6dc9357SAndroid Build Coastguard Worker Offset = (UInt16)(t >> 4);
350*f6dc9357SAndroid Build Coastguard Worker }
351*f6dc9357SAndroid Build Coastguard Worker return (Type == kType_FIFO || Type == kType_SOCK) ? 4 : 0;
352*f6dc9357SAndroid Build Coastguard Worker }
353*f6dc9357SAndroid Build Coastguard Worker
354*f6dc9357SAndroid Build Coastguard Worker Type--;
355*f6dc9357SAndroid Build Coastguard Worker Uid = (UInt16)(Uid + (Type / 5) * 16);
356*f6dc9357SAndroid Build Coastguard Worker Type = (UInt16)((Type % 5) + 1);
357*f6dc9357SAndroid Build Coastguard Worker
358*f6dc9357SAndroid Build Coastguard Worker if (Type == kType_FILE)
359*f6dc9357SAndroid Build Coastguard Worker {
360*f6dc9357SAndroid Build Coastguard Worker if (size < 15)
361*f6dc9357SAndroid Build Coastguard Worker return 0;
362*f6dc9357SAndroid Build Coastguard Worker // GET_32 (3, MTime);
363*f6dc9357SAndroid Build Coastguard Worker GET_32 (7, StartBlock);
364*f6dc9357SAndroid Build Coastguard Worker UInt32 t;
365*f6dc9357SAndroid Build Coastguard Worker GET_32 (11, t);
366*f6dc9357SAndroid Build Coastguard Worker FileSize = t;
367*f6dc9357SAndroid Build Coastguard Worker UInt32 numBlocks = t >> _h.BlockSizeLog;
368*f6dc9357SAndroid Build Coastguard Worker if ((t & (_h.BlockSize - 1)) != 0)
369*f6dc9357SAndroid Build Coastguard Worker numBlocks++;
370*f6dc9357SAndroid Build Coastguard Worker UInt32 pos = numBlocks * 2 + 15;
371*f6dc9357SAndroid Build Coastguard Worker return (pos <= size) ? pos : 0;
372*f6dc9357SAndroid Build Coastguard Worker }
373*f6dc9357SAndroid Build Coastguard Worker
374*f6dc9357SAndroid Build Coastguard Worker if (Type == kType_DIR)
375*f6dc9357SAndroid Build Coastguard Worker {
376*f6dc9357SAndroid Build Coastguard Worker if (size < 14)
377*f6dc9357SAndroid Build Coastguard Worker return 0;
378*f6dc9357SAndroid Build Coastguard Worker UInt32 t = Get32(p + 3);
379*f6dc9357SAndroid Build Coastguard Worker if (be)
380*f6dc9357SAndroid Build Coastguard Worker {
381*f6dc9357SAndroid Build Coastguard Worker FileSize = t >> 13;
382*f6dc9357SAndroid Build Coastguard Worker Offset = t & 0x1FFF;
383*f6dc9357SAndroid Build Coastguard Worker }
384*f6dc9357SAndroid Build Coastguard Worker else
385*f6dc9357SAndroid Build Coastguard Worker {
386*f6dc9357SAndroid Build Coastguard Worker FileSize = t & 0x7FFFF;
387*f6dc9357SAndroid Build Coastguard Worker Offset = t >> 19;
388*f6dc9357SAndroid Build Coastguard Worker }
389*f6dc9357SAndroid Build Coastguard Worker // GET_32 (7, MTime);
390*f6dc9357SAndroid Build Coastguard Worker GET_32 (10, StartBlock);
391*f6dc9357SAndroid Build Coastguard Worker if (be)
392*f6dc9357SAndroid Build Coastguard Worker StartBlock &= 0xFFFFFF;
393*f6dc9357SAndroid Build Coastguard Worker else
394*f6dc9357SAndroid Build Coastguard Worker StartBlock >>= 8;
395*f6dc9357SAndroid Build Coastguard Worker return 14;
396*f6dc9357SAndroid Build Coastguard Worker }
397*f6dc9357SAndroid Build Coastguard Worker
398*f6dc9357SAndroid Build Coastguard Worker if (size < 5)
399*f6dc9357SAndroid Build Coastguard Worker return 0;
400*f6dc9357SAndroid Build Coastguard Worker
401*f6dc9357SAndroid Build Coastguard Worker if (Type == kType_LNK)
402*f6dc9357SAndroid Build Coastguard Worker {
403*f6dc9357SAndroid Build Coastguard Worker UInt32 len;
404*f6dc9357SAndroid Build Coastguard Worker GET_16 (3, len);
405*f6dc9357SAndroid Build Coastguard Worker FileSize = len;
406*f6dc9357SAndroid Build Coastguard Worker len += 5;
407*f6dc9357SAndroid Build Coastguard Worker return (len <= size) ? len : 0;
408*f6dc9357SAndroid Build Coastguard Worker }
409*f6dc9357SAndroid Build Coastguard Worker
410*f6dc9357SAndroid Build Coastguard Worker // GET_32 (3, RDev);
411*f6dc9357SAndroid Build Coastguard Worker return 5;
412*f6dc9357SAndroid Build Coastguard Worker }
413*f6dc9357SAndroid Build Coastguard Worker
Parse2(const Byte * p,UInt32 size,const CHeader & _h)414*f6dc9357SAndroid Build Coastguard Worker UInt32 CNode::Parse2(const Byte *p, UInt32 size, const CHeader &_h)
415*f6dc9357SAndroid Build Coastguard Worker {
416*f6dc9357SAndroid Build Coastguard Worker const bool be = _h.be;
417*f6dc9357SAndroid Build Coastguard Worker if (size < 4)
418*f6dc9357SAndroid Build Coastguard Worker return 0;
419*f6dc9357SAndroid Build Coastguard Worker {
420*f6dc9357SAndroid Build Coastguard Worker const UInt32 t = Get16(p);
421*f6dc9357SAndroid Build Coastguard Worker if (be)
422*f6dc9357SAndroid Build Coastguard Worker {
423*f6dc9357SAndroid Build Coastguard Worker Type = (UInt16)(t >> 12);
424*f6dc9357SAndroid Build Coastguard Worker Mode = (UInt16)(t & 0xFFF);
425*f6dc9357SAndroid Build Coastguard Worker }
426*f6dc9357SAndroid Build Coastguard Worker else
427*f6dc9357SAndroid Build Coastguard Worker {
428*f6dc9357SAndroid Build Coastguard Worker Type = (UInt16)(t & 0xF);
429*f6dc9357SAndroid Build Coastguard Worker Mode = (UInt16)(t >> 4);
430*f6dc9357SAndroid Build Coastguard Worker }
431*f6dc9357SAndroid Build Coastguard Worker }
432*f6dc9357SAndroid Build Coastguard Worker
433*f6dc9357SAndroid Build Coastguard Worker Uid = p[2];
434*f6dc9357SAndroid Build Coastguard Worker Gid = p[3];
435*f6dc9357SAndroid Build Coastguard Worker
436*f6dc9357SAndroid Build Coastguard Worker // Xattr = kXattr_Empty;
437*f6dc9357SAndroid Build Coastguard Worker
438*f6dc9357SAndroid Build Coastguard Worker if (Type == kType_FILE)
439*f6dc9357SAndroid Build Coastguard Worker {
440*f6dc9357SAndroid Build Coastguard Worker if (size < 24)
441*f6dc9357SAndroid Build Coastguard Worker return 0;
442*f6dc9357SAndroid Build Coastguard Worker // GET_32 (4, MTime);
443*f6dc9357SAndroid Build Coastguard Worker GET_32 (8, StartBlock);
444*f6dc9357SAndroid Build Coastguard Worker GET_32 (12, Frag);
445*f6dc9357SAndroid Build Coastguard Worker GET_32 (16, Offset);
446*f6dc9357SAndroid Build Coastguard Worker UInt32 t;
447*f6dc9357SAndroid Build Coastguard Worker GET_32 (20, t);
448*f6dc9357SAndroid Build Coastguard Worker FileSize = t;
449*f6dc9357SAndroid Build Coastguard Worker UInt32 numBlocks = t >> _h.BlockSizeLog;
450*f6dc9357SAndroid Build Coastguard Worker if (!ThereAreFrags() && (t & (_h.BlockSize - 1)) != 0)
451*f6dc9357SAndroid Build Coastguard Worker numBlocks++;
452*f6dc9357SAndroid Build Coastguard Worker UInt32 pos = numBlocks * 4 + 24;
453*f6dc9357SAndroid Build Coastguard Worker return (pos <= size) ? (UInt32)pos : 0;
454*f6dc9357SAndroid Build Coastguard Worker }
455*f6dc9357SAndroid Build Coastguard Worker
456*f6dc9357SAndroid Build Coastguard Worker FileSize = 0;
457*f6dc9357SAndroid Build Coastguard Worker // MTime = 0;
458*f6dc9357SAndroid Build Coastguard Worker StartBlock = 0;
459*f6dc9357SAndroid Build Coastguard Worker Frag = kFrag_Empty;
460*f6dc9357SAndroid Build Coastguard Worker
461*f6dc9357SAndroid Build Coastguard Worker if (Type == kType_DIR)
462*f6dc9357SAndroid Build Coastguard Worker {
463*f6dc9357SAndroid Build Coastguard Worker if (size < 15)
464*f6dc9357SAndroid Build Coastguard Worker return 0;
465*f6dc9357SAndroid Build Coastguard Worker UInt32 t = Get32(p + 4);
466*f6dc9357SAndroid Build Coastguard Worker if (be)
467*f6dc9357SAndroid Build Coastguard Worker {
468*f6dc9357SAndroid Build Coastguard Worker FileSize = t >> 13;
469*f6dc9357SAndroid Build Coastguard Worker Offset = t & 0x1FFF;
470*f6dc9357SAndroid Build Coastguard Worker }
471*f6dc9357SAndroid Build Coastguard Worker else
472*f6dc9357SAndroid Build Coastguard Worker {
473*f6dc9357SAndroid Build Coastguard Worker FileSize = t & 0x7FFFF;
474*f6dc9357SAndroid Build Coastguard Worker Offset = t >> 19;
475*f6dc9357SAndroid Build Coastguard Worker }
476*f6dc9357SAndroid Build Coastguard Worker // GET_32 (8, MTime);
477*f6dc9357SAndroid Build Coastguard Worker GET_32 (11, StartBlock);
478*f6dc9357SAndroid Build Coastguard Worker if (be)
479*f6dc9357SAndroid Build Coastguard Worker StartBlock &= 0xFFFFFF;
480*f6dc9357SAndroid Build Coastguard Worker else
481*f6dc9357SAndroid Build Coastguard Worker StartBlock >>= 8;
482*f6dc9357SAndroid Build Coastguard Worker return 15;
483*f6dc9357SAndroid Build Coastguard Worker }
484*f6dc9357SAndroid Build Coastguard Worker
485*f6dc9357SAndroid Build Coastguard Worker if (Type == kType_DIR + 7)
486*f6dc9357SAndroid Build Coastguard Worker {
487*f6dc9357SAndroid Build Coastguard Worker if (size < 18)
488*f6dc9357SAndroid Build Coastguard Worker return 0;
489*f6dc9357SAndroid Build Coastguard Worker UInt32 t = Get32(p + 4);
490*f6dc9357SAndroid Build Coastguard Worker UInt32 t2 = Get16(p + 7);
491*f6dc9357SAndroid Build Coastguard Worker if (be)
492*f6dc9357SAndroid Build Coastguard Worker {
493*f6dc9357SAndroid Build Coastguard Worker FileSize = t >> 5;
494*f6dc9357SAndroid Build Coastguard Worker Offset = t2 & 0x1FFF;
495*f6dc9357SAndroid Build Coastguard Worker }
496*f6dc9357SAndroid Build Coastguard Worker else
497*f6dc9357SAndroid Build Coastguard Worker {
498*f6dc9357SAndroid Build Coastguard Worker FileSize = t & 0x7FFFFFF;
499*f6dc9357SAndroid Build Coastguard Worker Offset = t2 >> 3;
500*f6dc9357SAndroid Build Coastguard Worker }
501*f6dc9357SAndroid Build Coastguard Worker // GET_32 (9, MTime);
502*f6dc9357SAndroid Build Coastguard Worker GET_32 (12, StartBlock);
503*f6dc9357SAndroid Build Coastguard Worker if (be)
504*f6dc9357SAndroid Build Coastguard Worker StartBlock &= 0xFFFFFF;
505*f6dc9357SAndroid Build Coastguard Worker else
506*f6dc9357SAndroid Build Coastguard Worker StartBlock >>= 8;
507*f6dc9357SAndroid Build Coastguard Worker UInt32 iCount;
508*f6dc9357SAndroid Build Coastguard Worker GET_16 (16, iCount);
509*f6dc9357SAndroid Build Coastguard Worker UInt32 pos = 18;
510*f6dc9357SAndroid Build Coastguard Worker for (UInt32 i = 0; i < iCount; i++)
511*f6dc9357SAndroid Build Coastguard Worker {
512*f6dc9357SAndroid Build Coastguard Worker // 27 bits: index
513*f6dc9357SAndroid Build Coastguard Worker // 29 bits: startBlock
514*f6dc9357SAndroid Build Coastguard Worker if (pos + 8 > size)
515*f6dc9357SAndroid Build Coastguard Worker return 0;
516*f6dc9357SAndroid Build Coastguard Worker pos += 8 + (UInt32)p[pos + 7] + 1; // nameSize
517*f6dc9357SAndroid Build Coastguard Worker if (pos > size)
518*f6dc9357SAndroid Build Coastguard Worker return 0;
519*f6dc9357SAndroid Build Coastguard Worker }
520*f6dc9357SAndroid Build Coastguard Worker return pos;
521*f6dc9357SAndroid Build Coastguard Worker }
522*f6dc9357SAndroid Build Coastguard Worker
523*f6dc9357SAndroid Build Coastguard Worker if (Type == kType_FIFO || Type == kType_SOCK)
524*f6dc9357SAndroid Build Coastguard Worker return 4;
525*f6dc9357SAndroid Build Coastguard Worker
526*f6dc9357SAndroid Build Coastguard Worker if (size < 6)
527*f6dc9357SAndroid Build Coastguard Worker return 0;
528*f6dc9357SAndroid Build Coastguard Worker
529*f6dc9357SAndroid Build Coastguard Worker if (Type == kType_LNK)
530*f6dc9357SAndroid Build Coastguard Worker {
531*f6dc9357SAndroid Build Coastguard Worker UInt32 len;
532*f6dc9357SAndroid Build Coastguard Worker GET_16 (4, len);
533*f6dc9357SAndroid Build Coastguard Worker FileSize = len;
534*f6dc9357SAndroid Build Coastguard Worker len += 6;
535*f6dc9357SAndroid Build Coastguard Worker return (len <= size) ? len : 0;
536*f6dc9357SAndroid Build Coastguard Worker }
537*f6dc9357SAndroid Build Coastguard Worker
538*f6dc9357SAndroid Build Coastguard Worker if (Type == kType_BLK || Type == kType_CHR)
539*f6dc9357SAndroid Build Coastguard Worker {
540*f6dc9357SAndroid Build Coastguard Worker // GET_16 (4, RDev);
541*f6dc9357SAndroid Build Coastguard Worker return 6;
542*f6dc9357SAndroid Build Coastguard Worker }
543*f6dc9357SAndroid Build Coastguard Worker
544*f6dc9357SAndroid Build Coastguard Worker return 0;
545*f6dc9357SAndroid Build Coastguard Worker }
546*f6dc9357SAndroid Build Coastguard Worker
Parse3(const Byte * p,UInt32 size,const CHeader & _h)547*f6dc9357SAndroid Build Coastguard Worker UInt32 CNode::Parse3(const Byte *p, UInt32 size, const CHeader &_h)
548*f6dc9357SAndroid Build Coastguard Worker {
549*f6dc9357SAndroid Build Coastguard Worker const bool be = _h.be;
550*f6dc9357SAndroid Build Coastguard Worker if (size < 12)
551*f6dc9357SAndroid Build Coastguard Worker return 0;
552*f6dc9357SAndroid Build Coastguard Worker
553*f6dc9357SAndroid Build Coastguard Worker {
554*f6dc9357SAndroid Build Coastguard Worker const UInt32 t = Get16(p);
555*f6dc9357SAndroid Build Coastguard Worker if (be)
556*f6dc9357SAndroid Build Coastguard Worker {
557*f6dc9357SAndroid Build Coastguard Worker Type = (UInt16)(t >> 12);
558*f6dc9357SAndroid Build Coastguard Worker Mode = (UInt16)(t & 0xFFF);
559*f6dc9357SAndroid Build Coastguard Worker }
560*f6dc9357SAndroid Build Coastguard Worker else
561*f6dc9357SAndroid Build Coastguard Worker {
562*f6dc9357SAndroid Build Coastguard Worker Type = (UInt16)(t & 0xF);
563*f6dc9357SAndroid Build Coastguard Worker Mode = (UInt16)(t >> 4);
564*f6dc9357SAndroid Build Coastguard Worker }
565*f6dc9357SAndroid Build Coastguard Worker }
566*f6dc9357SAndroid Build Coastguard Worker
567*f6dc9357SAndroid Build Coastguard Worker Uid = p[2];
568*f6dc9357SAndroid Build Coastguard Worker Gid = p[3];
569*f6dc9357SAndroid Build Coastguard Worker // GET_32 (4, MTime);
570*f6dc9357SAndroid Build Coastguard Worker // GET_32 (8, Number);
571*f6dc9357SAndroid Build Coastguard Worker // Xattr = kXattr_Empty;
572*f6dc9357SAndroid Build Coastguard Worker FileSize = 0;
573*f6dc9357SAndroid Build Coastguard Worker StartBlock = 0;
574*f6dc9357SAndroid Build Coastguard Worker
575*f6dc9357SAndroid Build Coastguard Worker if (Type == kType_FILE || Type == kType_FILE + 7)
576*f6dc9357SAndroid Build Coastguard Worker {
577*f6dc9357SAndroid Build Coastguard Worker UInt32 offset;
578*f6dc9357SAndroid Build Coastguard Worker if (Type == kType_FILE)
579*f6dc9357SAndroid Build Coastguard Worker {
580*f6dc9357SAndroid Build Coastguard Worker if (size < 32)
581*f6dc9357SAndroid Build Coastguard Worker return 0;
582*f6dc9357SAndroid Build Coastguard Worker GET_64 (12, StartBlock);
583*f6dc9357SAndroid Build Coastguard Worker GET_32 (20, Frag);
584*f6dc9357SAndroid Build Coastguard Worker GET_32 (24, Offset);
585*f6dc9357SAndroid Build Coastguard Worker GET_32 (28, FileSize);
586*f6dc9357SAndroid Build Coastguard Worker offset = 32;
587*f6dc9357SAndroid Build Coastguard Worker }
588*f6dc9357SAndroid Build Coastguard Worker else
589*f6dc9357SAndroid Build Coastguard Worker {
590*f6dc9357SAndroid Build Coastguard Worker if (size < 40)
591*f6dc9357SAndroid Build Coastguard Worker return 0;
592*f6dc9357SAndroid Build Coastguard Worker // GET_32 (12, NumLinks);
593*f6dc9357SAndroid Build Coastguard Worker GET_64 (16, StartBlock);
594*f6dc9357SAndroid Build Coastguard Worker GET_32 (24, Frag);
595*f6dc9357SAndroid Build Coastguard Worker GET_32 (28, Offset);
596*f6dc9357SAndroid Build Coastguard Worker GET_64 (32, FileSize);
597*f6dc9357SAndroid Build Coastguard Worker offset = 40;
598*f6dc9357SAndroid Build Coastguard Worker }
599*f6dc9357SAndroid Build Coastguard Worker UInt64 pos = GetNumBlocks(_h) * 4 + offset;
600*f6dc9357SAndroid Build Coastguard Worker return (pos <= size) ? (UInt32)pos : 0;
601*f6dc9357SAndroid Build Coastguard Worker }
602*f6dc9357SAndroid Build Coastguard Worker
603*f6dc9357SAndroid Build Coastguard Worker if (size < 16)
604*f6dc9357SAndroid Build Coastguard Worker return 0;
605*f6dc9357SAndroid Build Coastguard Worker // GET_32 (12, NumLinks);
606*f6dc9357SAndroid Build Coastguard Worker
607*f6dc9357SAndroid Build Coastguard Worker if (Type == kType_DIR)
608*f6dc9357SAndroid Build Coastguard Worker {
609*f6dc9357SAndroid Build Coastguard Worker if (size < 28)
610*f6dc9357SAndroid Build Coastguard Worker return 0;
611*f6dc9357SAndroid Build Coastguard Worker UInt32 t = Get32(p + 16);
612*f6dc9357SAndroid Build Coastguard Worker if (be)
613*f6dc9357SAndroid Build Coastguard Worker {
614*f6dc9357SAndroid Build Coastguard Worker FileSize = t >> 13;
615*f6dc9357SAndroid Build Coastguard Worker Offset = t & 0x1FFF;
616*f6dc9357SAndroid Build Coastguard Worker }
617*f6dc9357SAndroid Build Coastguard Worker else
618*f6dc9357SAndroid Build Coastguard Worker {
619*f6dc9357SAndroid Build Coastguard Worker FileSize = t & 0x7FFFF;
620*f6dc9357SAndroid Build Coastguard Worker Offset = t >> 19;
621*f6dc9357SAndroid Build Coastguard Worker }
622*f6dc9357SAndroid Build Coastguard Worker GET_32 (20, StartBlock);
623*f6dc9357SAndroid Build Coastguard Worker // GET_32 (24, Parent);
624*f6dc9357SAndroid Build Coastguard Worker return 28;
625*f6dc9357SAndroid Build Coastguard Worker }
626*f6dc9357SAndroid Build Coastguard Worker
627*f6dc9357SAndroid Build Coastguard Worker if (Type == kType_DIR + 7)
628*f6dc9357SAndroid Build Coastguard Worker {
629*f6dc9357SAndroid Build Coastguard Worker if (size < 31)
630*f6dc9357SAndroid Build Coastguard Worker return 0;
631*f6dc9357SAndroid Build Coastguard Worker UInt32 t = Get32(p + 16);
632*f6dc9357SAndroid Build Coastguard Worker UInt32 t2 = Get16(p + 19);
633*f6dc9357SAndroid Build Coastguard Worker if (be)
634*f6dc9357SAndroid Build Coastguard Worker {
635*f6dc9357SAndroid Build Coastguard Worker FileSize = t >> 5;
636*f6dc9357SAndroid Build Coastguard Worker Offset = t2 & 0x1FFF;
637*f6dc9357SAndroid Build Coastguard Worker }
638*f6dc9357SAndroid Build Coastguard Worker else
639*f6dc9357SAndroid Build Coastguard Worker {
640*f6dc9357SAndroid Build Coastguard Worker FileSize = t & 0x7FFFFFF;
641*f6dc9357SAndroid Build Coastguard Worker Offset = t2 >> 3;
642*f6dc9357SAndroid Build Coastguard Worker }
643*f6dc9357SAndroid Build Coastguard Worker GET_32 (21, StartBlock);
644*f6dc9357SAndroid Build Coastguard Worker UInt32 iCount;
645*f6dc9357SAndroid Build Coastguard Worker GET_16 (25, iCount);
646*f6dc9357SAndroid Build Coastguard Worker // GET_32 (27, Parent);
647*f6dc9357SAndroid Build Coastguard Worker UInt32 pos = 31;
648*f6dc9357SAndroid Build Coastguard Worker for (UInt32 i = 0; i < iCount; i++)
649*f6dc9357SAndroid Build Coastguard Worker {
650*f6dc9357SAndroid Build Coastguard Worker // UInt32 index
651*f6dc9357SAndroid Build Coastguard Worker // UInt32 startBlock
652*f6dc9357SAndroid Build Coastguard Worker if (pos + 9 > size)
653*f6dc9357SAndroid Build Coastguard Worker return 0;
654*f6dc9357SAndroid Build Coastguard Worker pos += 9 + (unsigned)p[pos + 8] + 1; // nameSize
655*f6dc9357SAndroid Build Coastguard Worker if (pos > size)
656*f6dc9357SAndroid Build Coastguard Worker return 0;
657*f6dc9357SAndroid Build Coastguard Worker }
658*f6dc9357SAndroid Build Coastguard Worker return pos;
659*f6dc9357SAndroid Build Coastguard Worker }
660*f6dc9357SAndroid Build Coastguard Worker
661*f6dc9357SAndroid Build Coastguard Worker if (Type == kType_FIFO || Type == kType_SOCK)
662*f6dc9357SAndroid Build Coastguard Worker return 16;
663*f6dc9357SAndroid Build Coastguard Worker
664*f6dc9357SAndroid Build Coastguard Worker if (size < 18)
665*f6dc9357SAndroid Build Coastguard Worker return 0;
666*f6dc9357SAndroid Build Coastguard Worker if (Type == kType_LNK)
667*f6dc9357SAndroid Build Coastguard Worker {
668*f6dc9357SAndroid Build Coastguard Worker UInt32 len;
669*f6dc9357SAndroid Build Coastguard Worker GET_16 (16, len);
670*f6dc9357SAndroid Build Coastguard Worker FileSize = len;
671*f6dc9357SAndroid Build Coastguard Worker len += 18;
672*f6dc9357SAndroid Build Coastguard Worker return (len <= size) ? len : 0;
673*f6dc9357SAndroid Build Coastguard Worker }
674*f6dc9357SAndroid Build Coastguard Worker
675*f6dc9357SAndroid Build Coastguard Worker if (Type == kType_BLK || Type == kType_CHR)
676*f6dc9357SAndroid Build Coastguard Worker {
677*f6dc9357SAndroid Build Coastguard Worker // GET_16 (16, RDev);
678*f6dc9357SAndroid Build Coastguard Worker return 18;
679*f6dc9357SAndroid Build Coastguard Worker }
680*f6dc9357SAndroid Build Coastguard Worker
681*f6dc9357SAndroid Build Coastguard Worker return 0;
682*f6dc9357SAndroid Build Coastguard Worker }
683*f6dc9357SAndroid Build Coastguard Worker
Parse4(const Byte * p,UInt32 size,const CHeader & _h)684*f6dc9357SAndroid Build Coastguard Worker UInt32 CNode::Parse4(const Byte *p, UInt32 size, const CHeader &_h)
685*f6dc9357SAndroid Build Coastguard Worker {
686*f6dc9357SAndroid Build Coastguard Worker if (size < 20)
687*f6dc9357SAndroid Build Coastguard Worker return 0;
688*f6dc9357SAndroid Build Coastguard Worker LE_16 (0, Type);
689*f6dc9357SAndroid Build Coastguard Worker LE_16 (2, Mode);
690*f6dc9357SAndroid Build Coastguard Worker LE_16 (4, Uid);
691*f6dc9357SAndroid Build Coastguard Worker LE_16 (6, Gid);
692*f6dc9357SAndroid Build Coastguard Worker // LE_32 (8, MTime);
693*f6dc9357SAndroid Build Coastguard Worker // LE_32 (12, Number);
694*f6dc9357SAndroid Build Coastguard Worker
695*f6dc9357SAndroid Build Coastguard Worker // Xattr = kXattr_Empty;
696*f6dc9357SAndroid Build Coastguard Worker FileSize = 0;
697*f6dc9357SAndroid Build Coastguard Worker StartBlock = 0;
698*f6dc9357SAndroid Build Coastguard Worker
699*f6dc9357SAndroid Build Coastguard Worker if (Type == kType_FILE || Type == kType_FILE + 7)
700*f6dc9357SAndroid Build Coastguard Worker {
701*f6dc9357SAndroid Build Coastguard Worker UInt32 offset;
702*f6dc9357SAndroid Build Coastguard Worker if (Type == kType_FILE)
703*f6dc9357SAndroid Build Coastguard Worker {
704*f6dc9357SAndroid Build Coastguard Worker if (size < 32)
705*f6dc9357SAndroid Build Coastguard Worker return 0;
706*f6dc9357SAndroid Build Coastguard Worker LE_32 (16, StartBlock);
707*f6dc9357SAndroid Build Coastguard Worker LE_32 (20, Frag);
708*f6dc9357SAndroid Build Coastguard Worker LE_32 (24, Offset);
709*f6dc9357SAndroid Build Coastguard Worker LE_32 (28, FileSize);
710*f6dc9357SAndroid Build Coastguard Worker offset = 32;
711*f6dc9357SAndroid Build Coastguard Worker }
712*f6dc9357SAndroid Build Coastguard Worker else
713*f6dc9357SAndroid Build Coastguard Worker {
714*f6dc9357SAndroid Build Coastguard Worker if (size < 56)
715*f6dc9357SAndroid Build Coastguard Worker return 0;
716*f6dc9357SAndroid Build Coastguard Worker LE_64 (16, StartBlock);
717*f6dc9357SAndroid Build Coastguard Worker LE_64 (24, FileSize);
718*f6dc9357SAndroid Build Coastguard Worker // LE_64 (32, Sparse);
719*f6dc9357SAndroid Build Coastguard Worker // LE_32 (40, NumLinks);
720*f6dc9357SAndroid Build Coastguard Worker LE_32 (44, Frag);
721*f6dc9357SAndroid Build Coastguard Worker LE_32 (48, Offset);
722*f6dc9357SAndroid Build Coastguard Worker // LE_32 (52, Xattr);
723*f6dc9357SAndroid Build Coastguard Worker offset = 56;
724*f6dc9357SAndroid Build Coastguard Worker }
725*f6dc9357SAndroid Build Coastguard Worker UInt64 pos = GetNumBlocks(_h) * 4 + offset;
726*f6dc9357SAndroid Build Coastguard Worker return (pos <= size) ? (UInt32)pos : 0;
727*f6dc9357SAndroid Build Coastguard Worker }
728*f6dc9357SAndroid Build Coastguard Worker
729*f6dc9357SAndroid Build Coastguard Worker if (Type == kType_DIR)
730*f6dc9357SAndroid Build Coastguard Worker {
731*f6dc9357SAndroid Build Coastguard Worker if (size < 32)
732*f6dc9357SAndroid Build Coastguard Worker return 0;
733*f6dc9357SAndroid Build Coastguard Worker LE_32 (16, StartBlock);
734*f6dc9357SAndroid Build Coastguard Worker // LE_32 (20, NumLinks);
735*f6dc9357SAndroid Build Coastguard Worker LE_16 (24, FileSize);
736*f6dc9357SAndroid Build Coastguard Worker LE_16 (26, Offset);
737*f6dc9357SAndroid Build Coastguard Worker // LE_32 (28, Parent);
738*f6dc9357SAndroid Build Coastguard Worker return 32;
739*f6dc9357SAndroid Build Coastguard Worker }
740*f6dc9357SAndroid Build Coastguard Worker
741*f6dc9357SAndroid Build Coastguard Worker // LE_32 (16, NumLinks);
742*f6dc9357SAndroid Build Coastguard Worker
743*f6dc9357SAndroid Build Coastguard Worker if (Type == kType_DIR + 7)
744*f6dc9357SAndroid Build Coastguard Worker {
745*f6dc9357SAndroid Build Coastguard Worker if (size < 40)
746*f6dc9357SAndroid Build Coastguard Worker return 0;
747*f6dc9357SAndroid Build Coastguard Worker LE_32 (20, FileSize);
748*f6dc9357SAndroid Build Coastguard Worker LE_32 (24, StartBlock);
749*f6dc9357SAndroid Build Coastguard Worker // LE_32 (28, Parent);
750*f6dc9357SAndroid Build Coastguard Worker UInt32 iCount;
751*f6dc9357SAndroid Build Coastguard Worker LE_16 (32, iCount);
752*f6dc9357SAndroid Build Coastguard Worker LE_16 (34, Offset);
753*f6dc9357SAndroid Build Coastguard Worker // LE_32 (36, Xattr);
754*f6dc9357SAndroid Build Coastguard Worker
755*f6dc9357SAndroid Build Coastguard Worker UInt32 pos = 40;
756*f6dc9357SAndroid Build Coastguard Worker for (UInt32 i = 0; i < iCount; i++)
757*f6dc9357SAndroid Build Coastguard Worker {
758*f6dc9357SAndroid Build Coastguard Worker // UInt32 index
759*f6dc9357SAndroid Build Coastguard Worker // UInt32 startBlock
760*f6dc9357SAndroid Build Coastguard Worker if (pos + 12 > size)
761*f6dc9357SAndroid Build Coastguard Worker return 0;
762*f6dc9357SAndroid Build Coastguard Worker UInt32 nameLen = GetUi32(p + pos + 8);
763*f6dc9357SAndroid Build Coastguard Worker pos += 12 + nameLen + 1;
764*f6dc9357SAndroid Build Coastguard Worker if (pos > size || nameLen > (1 << 10))
765*f6dc9357SAndroid Build Coastguard Worker return 0;
766*f6dc9357SAndroid Build Coastguard Worker }
767*f6dc9357SAndroid Build Coastguard Worker return pos;
768*f6dc9357SAndroid Build Coastguard Worker }
769*f6dc9357SAndroid Build Coastguard Worker
770*f6dc9357SAndroid Build Coastguard Worker unsigned offset = 20;
771*f6dc9357SAndroid Build Coastguard Worker switch (Type)
772*f6dc9357SAndroid Build Coastguard Worker {
773*f6dc9357SAndroid Build Coastguard Worker case kType_FIFO: case kType_FIFO + 7:
774*f6dc9357SAndroid Build Coastguard Worker case kType_SOCK: case kType_SOCK + 7:
775*f6dc9357SAndroid Build Coastguard Worker break;
776*f6dc9357SAndroid Build Coastguard Worker case kType_LNK: case kType_LNK + 7:
777*f6dc9357SAndroid Build Coastguard Worker {
778*f6dc9357SAndroid Build Coastguard Worker if (size < 24)
779*f6dc9357SAndroid Build Coastguard Worker return 0;
780*f6dc9357SAndroid Build Coastguard Worker UInt32 len;
781*f6dc9357SAndroid Build Coastguard Worker LE_32 (20, len);
782*f6dc9357SAndroid Build Coastguard Worker FileSize = len;
783*f6dc9357SAndroid Build Coastguard Worker offset = len + 24;
784*f6dc9357SAndroid Build Coastguard Worker if (size < offset || len > (1 << 30))
785*f6dc9357SAndroid Build Coastguard Worker return 0;
786*f6dc9357SAndroid Build Coastguard Worker break;
787*f6dc9357SAndroid Build Coastguard Worker }
788*f6dc9357SAndroid Build Coastguard Worker case kType_BLK: case kType_BLK + 7:
789*f6dc9357SAndroid Build Coastguard Worker case kType_CHR: case kType_CHR + 7:
790*f6dc9357SAndroid Build Coastguard Worker if (size < 24)
791*f6dc9357SAndroid Build Coastguard Worker return 0;
792*f6dc9357SAndroid Build Coastguard Worker // LE_32 (20, RDev);
793*f6dc9357SAndroid Build Coastguard Worker offset = 24;
794*f6dc9357SAndroid Build Coastguard Worker break;
795*f6dc9357SAndroid Build Coastguard Worker default:
796*f6dc9357SAndroid Build Coastguard Worker return 0;
797*f6dc9357SAndroid Build Coastguard Worker }
798*f6dc9357SAndroid Build Coastguard Worker
799*f6dc9357SAndroid Build Coastguard Worker if (Type >= 8)
800*f6dc9357SAndroid Build Coastguard Worker {
801*f6dc9357SAndroid Build Coastguard Worker if (size < offset + 4)
802*f6dc9357SAndroid Build Coastguard Worker return 0;
803*f6dc9357SAndroid Build Coastguard Worker // LE_32 (offset, Xattr);
804*f6dc9357SAndroid Build Coastguard Worker offset += 4;
805*f6dc9357SAndroid Build Coastguard Worker }
806*f6dc9357SAndroid Build Coastguard Worker return offset;
807*f6dc9357SAndroid Build Coastguard Worker }
808*f6dc9357SAndroid Build Coastguard Worker
809*f6dc9357SAndroid Build Coastguard Worker struct CItem
810*f6dc9357SAndroid Build Coastguard Worker {
811*f6dc9357SAndroid Build Coastguard Worker int Node;
812*f6dc9357SAndroid Build Coastguard Worker int Parent;
813*f6dc9357SAndroid Build Coastguard Worker UInt32 Ptr;
814*f6dc9357SAndroid Build Coastguard Worker
CItemNArchive::NSquashfs::CItem815*f6dc9357SAndroid Build Coastguard Worker CItem(): Node(-1), Parent(-1), Ptr(0) {}
816*f6dc9357SAndroid Build Coastguard Worker };
817*f6dc9357SAndroid Build Coastguard Worker
818*f6dc9357SAndroid Build Coastguard Worker struct CData
819*f6dc9357SAndroid Build Coastguard Worker {
820*f6dc9357SAndroid Build Coastguard Worker CByteBuffer Data;
821*f6dc9357SAndroid Build Coastguard Worker CRecordVector<UInt32> PackPos;
822*f6dc9357SAndroid Build Coastguard Worker CRecordVector<UInt32> UnpackPos; // additional item at the end contains TotalUnpackSize
823*f6dc9357SAndroid Build Coastguard Worker
GetNumBlocksNArchive::NSquashfs::CData824*f6dc9357SAndroid Build Coastguard Worker UInt32 GetNumBlocks() const { return PackPos.Size(); }
ClearNArchive::NSquashfs::CData825*f6dc9357SAndroid Build Coastguard Worker void Clear()
826*f6dc9357SAndroid Build Coastguard Worker {
827*f6dc9357SAndroid Build Coastguard Worker Data.Free();
828*f6dc9357SAndroid Build Coastguard Worker PackPos.Clear();
829*f6dc9357SAndroid Build Coastguard Worker UnpackPos.Clear();
830*f6dc9357SAndroid Build Coastguard Worker }
831*f6dc9357SAndroid Build Coastguard Worker };
832*f6dc9357SAndroid Build Coastguard Worker
833*f6dc9357SAndroid Build Coastguard Worker struct CFrag
834*f6dc9357SAndroid Build Coastguard Worker {
835*f6dc9357SAndroid Build Coastguard Worker UInt64 StartBlock;
836*f6dc9357SAndroid Build Coastguard Worker UInt32 Size;
837*f6dc9357SAndroid Build Coastguard Worker };
838*f6dc9357SAndroid Build Coastguard Worker
839*f6dc9357SAndroid Build Coastguard Worker
840*f6dc9357SAndroid Build Coastguard Worker Z7_CLASS_IMP_CHandler_IInArchive_1(
841*f6dc9357SAndroid Build Coastguard Worker IInArchiveGetStream
842*f6dc9357SAndroid Build Coastguard Worker )
843*f6dc9357SAndroid Build Coastguard Worker bool _noPropsLZMA;
844*f6dc9357SAndroid Build Coastguard Worker bool _needCheckLzma;
845*f6dc9357SAndroid Build Coastguard Worker
846*f6dc9357SAndroid Build Coastguard Worker CRecordVector<CItem> _items;
847*f6dc9357SAndroid Build Coastguard Worker CRecordVector<CNode> _nodes;
848*f6dc9357SAndroid Build Coastguard Worker CRecordVector<UInt32> _nodesPos;
849*f6dc9357SAndroid Build Coastguard Worker CRecordVector<UInt32> _blockToNode;
850*f6dc9357SAndroid Build Coastguard Worker CData _inodesData;
851*f6dc9357SAndroid Build Coastguard Worker CData _dirs;
852*f6dc9357SAndroid Build Coastguard Worker CRecordVector<CFrag> _frags;
853*f6dc9357SAndroid Build Coastguard Worker CByteBuffer _uids;
854*f6dc9357SAndroid Build Coastguard Worker CByteBuffer _gids;
855*f6dc9357SAndroid Build Coastguard Worker CHeader _h;
856*f6dc9357SAndroid Build Coastguard Worker
857*f6dc9357SAndroid Build Coastguard Worker UInt64 _sizeCalculated;
858*f6dc9357SAndroid Build Coastguard Worker CMyComPtr<IInStream> _stream;
859*f6dc9357SAndroid Build Coastguard Worker
860*f6dc9357SAndroid Build Coastguard Worker IArchiveOpenCallback *_openCallback;
861*f6dc9357SAndroid Build Coastguard Worker
862*f6dc9357SAndroid Build Coastguard Worker UInt32 _openCodePage;
863*f6dc9357SAndroid Build Coastguard Worker int _nodeIndex;
864*f6dc9357SAndroid Build Coastguard Worker CRecordVector<bool> _blockCompressed;
865*f6dc9357SAndroid Build Coastguard Worker CRecordVector<UInt64> _blockOffsets;
866*f6dc9357SAndroid Build Coastguard Worker
867*f6dc9357SAndroid Build Coastguard Worker CByteBuffer _cachedBlock;
868*f6dc9357SAndroid Build Coastguard Worker UInt64 _cachedBlockStartPos;
869*f6dc9357SAndroid Build Coastguard Worker UInt32 _cachedPackBlockSize;
870*f6dc9357SAndroid Build Coastguard Worker UInt32 _cachedUnpackBlockSize;
871*f6dc9357SAndroid Build Coastguard Worker
872*f6dc9357SAndroid Build Coastguard Worker CMyComPtr2_Create<ISequentialInStream, CLimitedSequentialInStream> _limitedInStream;
873*f6dc9357SAndroid Build Coastguard Worker CMyComPtr2_Create<ISequentialOutStream, CBufPtrSeqOutStream> _outStream;
874*f6dc9357SAndroid Build Coastguard Worker CMyComPtr2_Create<ISequentialOutStream, CDynBufSeqOutStream> _dynOutStream;
875*f6dc9357SAndroid Build Coastguard Worker
876*f6dc9357SAndroid Build Coastguard Worker // CMyComPtr2<ICompressCoder, NCompress::NLzma::CDecoder> _lzmaDecoder;
877*f6dc9357SAndroid Build Coastguard Worker CMyComPtr2<ICompressCoder, NCompress::NZlib::CDecoder> _zlibDecoder;
878*f6dc9357SAndroid Build Coastguard Worker
879*f6dc9357SAndroid Build Coastguard Worker CXzUnpacker _xz;
880*f6dc9357SAndroid Build Coastguard Worker CZstdDecHandle _zstd;
881*f6dc9357SAndroid Build Coastguard Worker
882*f6dc9357SAndroid Build Coastguard Worker CByteBuffer _inputBuffer;
883*f6dc9357SAndroid Build Coastguard Worker
ClearCache()884*f6dc9357SAndroid Build Coastguard Worker void ClearCache()
885*f6dc9357SAndroid Build Coastguard Worker {
886*f6dc9357SAndroid Build Coastguard Worker _cachedBlockStartPos = 0;
887*f6dc9357SAndroid Build Coastguard Worker _cachedPackBlockSize = 0;
888*f6dc9357SAndroid Build Coastguard Worker _cachedUnpackBlockSize = 0;
889*f6dc9357SAndroid Build Coastguard Worker }
890*f6dc9357SAndroid Build Coastguard Worker
Seek2(UInt64 offset)891*f6dc9357SAndroid Build Coastguard Worker HRESULT Seek2(UInt64 offset)
892*f6dc9357SAndroid Build Coastguard Worker {
893*f6dc9357SAndroid Build Coastguard Worker return InStream_SeekSet(_stream, offset);
894*f6dc9357SAndroid Build Coastguard Worker }
895*f6dc9357SAndroid Build Coastguard Worker
896*f6dc9357SAndroid Build Coastguard Worker HRESULT Decompress(ISequentialOutStream *outStream, Byte *outBuf, bool *outBufWasWritten, UInt32 *outBufWasWrittenSize,
897*f6dc9357SAndroid Build Coastguard Worker UInt32 inSize, UInt32 outSizeMax);
898*f6dc9357SAndroid Build Coastguard Worker HRESULT ReadMetadataBlock(UInt32 &packSize);
899*f6dc9357SAndroid Build Coastguard Worker HRESULT ReadMetadataBlock2();
900*f6dc9357SAndroid Build Coastguard Worker HRESULT ReadData(CData &data, UInt64 start, UInt64 end);
901*f6dc9357SAndroid Build Coastguard Worker
902*f6dc9357SAndroid Build Coastguard Worker HRESULT OpenDir(int parent, UInt32 startBlock, UInt32 offset, unsigned level, int &nodeIndex);
903*f6dc9357SAndroid Build Coastguard Worker HRESULT ScanInodes(UInt64 ptr);
904*f6dc9357SAndroid Build Coastguard Worker HRESULT ReadUids(UInt64 start, UInt32 num, CByteBuffer &ids);
905*f6dc9357SAndroid Build Coastguard Worker HRESULT Open2(IInStream *inStream);
906*f6dc9357SAndroid Build Coastguard Worker AString GetPath(unsigned index) const;
907*f6dc9357SAndroid Build Coastguard Worker bool GetPackSize(unsigned index, UInt64 &res, bool fillOffsets);
908*f6dc9357SAndroid Build Coastguard Worker
909*f6dc9357SAndroid Build Coastguard Worker public:
910*f6dc9357SAndroid Build Coastguard Worker CHandler();
911*f6dc9357SAndroid Build Coastguard Worker ~CHandler()
912*f6dc9357SAndroid Build Coastguard Worker {
913*f6dc9357SAndroid Build Coastguard Worker XzUnpacker_Free(&_xz);
914*f6dc9357SAndroid Build Coastguard Worker if (_zstd)
915*f6dc9357SAndroid Build Coastguard Worker ZstdDec_Destroy(_zstd);
916*f6dc9357SAndroid Build Coastguard Worker }
917*f6dc9357SAndroid Build Coastguard Worker
918*f6dc9357SAndroid Build Coastguard Worker HRESULT ReadBlock(UInt64 blockIndex, Byte *dest, size_t blockSize);
919*f6dc9357SAndroid Build Coastguard Worker };
920*f6dc9357SAndroid Build Coastguard Worker
921*f6dc9357SAndroid Build Coastguard Worker
922*f6dc9357SAndroid Build Coastguard Worker CHandler::CHandler():
923*f6dc9357SAndroid Build Coastguard Worker _zstd(NULL)
924*f6dc9357SAndroid Build Coastguard Worker {
925*f6dc9357SAndroid Build Coastguard Worker XzUnpacker_Construct(&_xz, &g_Alloc);
926*f6dc9357SAndroid Build Coastguard Worker }
927*f6dc9357SAndroid Build Coastguard Worker
928*f6dc9357SAndroid Build Coastguard Worker static const Byte kProps[] =
929*f6dc9357SAndroid Build Coastguard Worker {
930*f6dc9357SAndroid Build Coastguard Worker kpidPath,
931*f6dc9357SAndroid Build Coastguard Worker kpidIsDir,
932*f6dc9357SAndroid Build Coastguard Worker kpidSize,
933*f6dc9357SAndroid Build Coastguard Worker kpidPackSize,
934*f6dc9357SAndroid Build Coastguard Worker kpidMTime,
935*f6dc9357SAndroid Build Coastguard Worker kpidPosixAttrib,
936*f6dc9357SAndroid Build Coastguard Worker kpidUserId,
937*f6dc9357SAndroid Build Coastguard Worker kpidGroupId
938*f6dc9357SAndroid Build Coastguard Worker // kpidLinks,
939*f6dc9357SAndroid Build Coastguard Worker // kpidOffset
940*f6dc9357SAndroid Build Coastguard Worker };
941*f6dc9357SAndroid Build Coastguard Worker
942*f6dc9357SAndroid Build Coastguard Worker static const Byte kArcProps[] =
943*f6dc9357SAndroid Build Coastguard Worker {
944*f6dc9357SAndroid Build Coastguard Worker kpidHeadersSize,
945*f6dc9357SAndroid Build Coastguard Worker kpidFileSystem,
946*f6dc9357SAndroid Build Coastguard Worker kpidMethod,
947*f6dc9357SAndroid Build Coastguard Worker kpidClusterSize,
948*f6dc9357SAndroid Build Coastguard Worker kpidBigEndian,
949*f6dc9357SAndroid Build Coastguard Worker kpidCTime,
950*f6dc9357SAndroid Build Coastguard Worker kpidCharacts,
951*f6dc9357SAndroid Build Coastguard Worker kpidCodePage
952*f6dc9357SAndroid Build Coastguard Worker // kpidNumBlocks
953*f6dc9357SAndroid Build Coastguard Worker };
954*f6dc9357SAndroid Build Coastguard Worker
955*f6dc9357SAndroid Build Coastguard Worker IMP_IInArchive_Props
956*f6dc9357SAndroid Build Coastguard Worker IMP_IInArchive_ArcProps
957*f6dc9357SAndroid Build Coastguard Worker
958*f6dc9357SAndroid Build Coastguard Worker static HRESULT LzoDecode(Byte *dest, SizeT *destLen, const Byte *src, SizeT *srcLen)
959*f6dc9357SAndroid Build Coastguard Worker {
960*f6dc9357SAndroid Build Coastguard Worker SizeT destRem = *destLen;
961*f6dc9357SAndroid Build Coastguard Worker SizeT srcRem = *srcLen;
962*f6dc9357SAndroid Build Coastguard Worker *destLen = 0;
963*f6dc9357SAndroid Build Coastguard Worker *srcLen = 0;
964*f6dc9357SAndroid Build Coastguard Worker const Byte *destStart = dest;
965*f6dc9357SAndroid Build Coastguard Worker const Byte *srcStart = src;
966*f6dc9357SAndroid Build Coastguard Worker unsigned mode = 0;
967*f6dc9357SAndroid Build Coastguard Worker
968*f6dc9357SAndroid Build Coastguard Worker {
969*f6dc9357SAndroid Build Coastguard Worker if (srcRem == 0)
970*f6dc9357SAndroid Build Coastguard Worker return S_FALSE;
971*f6dc9357SAndroid Build Coastguard Worker UInt32 b = *src;
972*f6dc9357SAndroid Build Coastguard Worker if (b > 17)
973*f6dc9357SAndroid Build Coastguard Worker {
974*f6dc9357SAndroid Build Coastguard Worker src++;
975*f6dc9357SAndroid Build Coastguard Worker srcRem--;
976*f6dc9357SAndroid Build Coastguard Worker b -= 17;
977*f6dc9357SAndroid Build Coastguard Worker mode = (b < 4 ? 1 : 4);
978*f6dc9357SAndroid Build Coastguard Worker if (b > srcRem || b > destRem)
979*f6dc9357SAndroid Build Coastguard Worker return S_FALSE;
980*f6dc9357SAndroid Build Coastguard Worker srcRem -= b;
981*f6dc9357SAndroid Build Coastguard Worker destRem -= b;
982*f6dc9357SAndroid Build Coastguard Worker do
983*f6dc9357SAndroid Build Coastguard Worker *dest++ = *src++;
984*f6dc9357SAndroid Build Coastguard Worker while (--b);
985*f6dc9357SAndroid Build Coastguard Worker }
986*f6dc9357SAndroid Build Coastguard Worker }
987*f6dc9357SAndroid Build Coastguard Worker
988*f6dc9357SAndroid Build Coastguard Worker for (;;)
989*f6dc9357SAndroid Build Coastguard Worker {
990*f6dc9357SAndroid Build Coastguard Worker if (srcRem < 3)
991*f6dc9357SAndroid Build Coastguard Worker return S_FALSE;
992*f6dc9357SAndroid Build Coastguard Worker UInt32 b = *src++;
993*f6dc9357SAndroid Build Coastguard Worker srcRem--;
994*f6dc9357SAndroid Build Coastguard Worker UInt32 len, back;
995*f6dc9357SAndroid Build Coastguard Worker
996*f6dc9357SAndroid Build Coastguard Worker if (b >= 64)
997*f6dc9357SAndroid Build Coastguard Worker {
998*f6dc9357SAndroid Build Coastguard Worker srcRem--;
999*f6dc9357SAndroid Build Coastguard Worker back = ((b >> 2) & 7) + ((UInt32)*src++ << 3);
1000*f6dc9357SAndroid Build Coastguard Worker len = (b >> 5) + 1;
1001*f6dc9357SAndroid Build Coastguard Worker }
1002*f6dc9357SAndroid Build Coastguard Worker else if (b < 16)
1003*f6dc9357SAndroid Build Coastguard Worker {
1004*f6dc9357SAndroid Build Coastguard Worker if (mode == 0)
1005*f6dc9357SAndroid Build Coastguard Worker {
1006*f6dc9357SAndroid Build Coastguard Worker if (b == 0)
1007*f6dc9357SAndroid Build Coastguard Worker {
1008*f6dc9357SAndroid Build Coastguard Worker for (b = 15;; b += 255)
1009*f6dc9357SAndroid Build Coastguard Worker {
1010*f6dc9357SAndroid Build Coastguard Worker if (srcRem == 0)
1011*f6dc9357SAndroid Build Coastguard Worker return S_FALSE;
1012*f6dc9357SAndroid Build Coastguard Worker UInt32 b2 = *src++;
1013*f6dc9357SAndroid Build Coastguard Worker srcRem--;
1014*f6dc9357SAndroid Build Coastguard Worker if (b2 != 0)
1015*f6dc9357SAndroid Build Coastguard Worker {
1016*f6dc9357SAndroid Build Coastguard Worker b += b2;
1017*f6dc9357SAndroid Build Coastguard Worker break;
1018*f6dc9357SAndroid Build Coastguard Worker }
1019*f6dc9357SAndroid Build Coastguard Worker }
1020*f6dc9357SAndroid Build Coastguard Worker }
1021*f6dc9357SAndroid Build Coastguard Worker
1022*f6dc9357SAndroid Build Coastguard Worker b += 3;
1023*f6dc9357SAndroid Build Coastguard Worker if (b > srcRem || b > destRem)
1024*f6dc9357SAndroid Build Coastguard Worker return S_FALSE;
1025*f6dc9357SAndroid Build Coastguard Worker srcRem -= b;
1026*f6dc9357SAndroid Build Coastguard Worker destRem -= b;
1027*f6dc9357SAndroid Build Coastguard Worker mode = 4;
1028*f6dc9357SAndroid Build Coastguard Worker do
1029*f6dc9357SAndroid Build Coastguard Worker *dest++ = *src++;
1030*f6dc9357SAndroid Build Coastguard Worker while (--b);
1031*f6dc9357SAndroid Build Coastguard Worker continue;
1032*f6dc9357SAndroid Build Coastguard Worker }
1033*f6dc9357SAndroid Build Coastguard Worker
1034*f6dc9357SAndroid Build Coastguard Worker srcRem--;
1035*f6dc9357SAndroid Build Coastguard Worker back = (b >> 2) + ((UInt32)*src++ << 2);
1036*f6dc9357SAndroid Build Coastguard Worker len = 2;
1037*f6dc9357SAndroid Build Coastguard Worker if (mode == 4)
1038*f6dc9357SAndroid Build Coastguard Worker {
1039*f6dc9357SAndroid Build Coastguard Worker back += (1 << 11);
1040*f6dc9357SAndroid Build Coastguard Worker len = 3;
1041*f6dc9357SAndroid Build Coastguard Worker }
1042*f6dc9357SAndroid Build Coastguard Worker }
1043*f6dc9357SAndroid Build Coastguard Worker else
1044*f6dc9357SAndroid Build Coastguard Worker {
1045*f6dc9357SAndroid Build Coastguard Worker UInt32 bOld = b;
1046*f6dc9357SAndroid Build Coastguard Worker b = (b < 32 ? 7 : 31);
1047*f6dc9357SAndroid Build Coastguard Worker len = bOld & b;
1048*f6dc9357SAndroid Build Coastguard Worker
1049*f6dc9357SAndroid Build Coastguard Worker if (len == 0)
1050*f6dc9357SAndroid Build Coastguard Worker {
1051*f6dc9357SAndroid Build Coastguard Worker for (len = b;; len += 255)
1052*f6dc9357SAndroid Build Coastguard Worker {
1053*f6dc9357SAndroid Build Coastguard Worker if (srcRem == 0)
1054*f6dc9357SAndroid Build Coastguard Worker return S_FALSE;
1055*f6dc9357SAndroid Build Coastguard Worker UInt32 b2 = *src++;
1056*f6dc9357SAndroid Build Coastguard Worker srcRem--;
1057*f6dc9357SAndroid Build Coastguard Worker if (b2 != 0)
1058*f6dc9357SAndroid Build Coastguard Worker {
1059*f6dc9357SAndroid Build Coastguard Worker len += b2;
1060*f6dc9357SAndroid Build Coastguard Worker break;
1061*f6dc9357SAndroid Build Coastguard Worker }
1062*f6dc9357SAndroid Build Coastguard Worker }
1063*f6dc9357SAndroid Build Coastguard Worker }
1064*f6dc9357SAndroid Build Coastguard Worker
1065*f6dc9357SAndroid Build Coastguard Worker len += 2;
1066*f6dc9357SAndroid Build Coastguard Worker if (srcRem < 2)
1067*f6dc9357SAndroid Build Coastguard Worker return S_FALSE;
1068*f6dc9357SAndroid Build Coastguard Worker b = *src;
1069*f6dc9357SAndroid Build Coastguard Worker back = (b >> 2) + ((UInt32)src[1] << 6);
1070*f6dc9357SAndroid Build Coastguard Worker src += 2;
1071*f6dc9357SAndroid Build Coastguard Worker srcRem -= 2;
1072*f6dc9357SAndroid Build Coastguard Worker if (bOld < 32)
1073*f6dc9357SAndroid Build Coastguard Worker {
1074*f6dc9357SAndroid Build Coastguard Worker back += ((bOld & 8) << 11);
1075*f6dc9357SAndroid Build Coastguard Worker if (back == 0)
1076*f6dc9357SAndroid Build Coastguard Worker {
1077*f6dc9357SAndroid Build Coastguard Worker *destLen = (size_t)(dest - destStart);
1078*f6dc9357SAndroid Build Coastguard Worker *srcLen = (size_t)(src - srcStart);
1079*f6dc9357SAndroid Build Coastguard Worker return S_OK;
1080*f6dc9357SAndroid Build Coastguard Worker }
1081*f6dc9357SAndroid Build Coastguard Worker back += (1 << 14) - 1;
1082*f6dc9357SAndroid Build Coastguard Worker }
1083*f6dc9357SAndroid Build Coastguard Worker }
1084*f6dc9357SAndroid Build Coastguard Worker
1085*f6dc9357SAndroid Build Coastguard Worker back++;
1086*f6dc9357SAndroid Build Coastguard Worker if (len > destRem || (size_t)(dest - destStart) < back)
1087*f6dc9357SAndroid Build Coastguard Worker return S_FALSE;
1088*f6dc9357SAndroid Build Coastguard Worker destRem -= len;
1089*f6dc9357SAndroid Build Coastguard Worker Byte *destTemp = dest - back;
1090*f6dc9357SAndroid Build Coastguard Worker dest += len;
1091*f6dc9357SAndroid Build Coastguard Worker
1092*f6dc9357SAndroid Build Coastguard Worker do
1093*f6dc9357SAndroid Build Coastguard Worker {
1094*f6dc9357SAndroid Build Coastguard Worker *(destTemp + back) = *destTemp;
1095*f6dc9357SAndroid Build Coastguard Worker destTemp++;
1096*f6dc9357SAndroid Build Coastguard Worker }
1097*f6dc9357SAndroid Build Coastguard Worker while (--len);
1098*f6dc9357SAndroid Build Coastguard Worker
1099*f6dc9357SAndroid Build Coastguard Worker b &= 3;
1100*f6dc9357SAndroid Build Coastguard Worker mode = b;
1101*f6dc9357SAndroid Build Coastguard Worker if (b == 0)
1102*f6dc9357SAndroid Build Coastguard Worker continue;
1103*f6dc9357SAndroid Build Coastguard Worker if (b > srcRem || b > destRem)
1104*f6dc9357SAndroid Build Coastguard Worker return S_FALSE;
1105*f6dc9357SAndroid Build Coastguard Worker srcRem -= b;
1106*f6dc9357SAndroid Build Coastguard Worker destRem -= b;
1107*f6dc9357SAndroid Build Coastguard Worker *dest++ = *src++;
1108*f6dc9357SAndroid Build Coastguard Worker if (b > 1)
1109*f6dc9357SAndroid Build Coastguard Worker {
1110*f6dc9357SAndroid Build Coastguard Worker *dest++ = *src++;
1111*f6dc9357SAndroid Build Coastguard Worker if (b > 2)
1112*f6dc9357SAndroid Build Coastguard Worker *dest++ = *src++;
1113*f6dc9357SAndroid Build Coastguard Worker }
1114*f6dc9357SAndroid Build Coastguard Worker }
1115*f6dc9357SAndroid Build Coastguard Worker }
1116*f6dc9357SAndroid Build Coastguard Worker
1117*f6dc9357SAndroid Build Coastguard Worker HRESULT CHandler::Decompress(ISequentialOutStream *outStream, Byte *outBuf, bool *outBufWasWritten, UInt32 *outBufWasWrittenSize, UInt32 inSize, UInt32 outSizeMax)
1118*f6dc9357SAndroid Build Coastguard Worker {
1119*f6dc9357SAndroid Build Coastguard Worker if (outBuf)
1120*f6dc9357SAndroid Build Coastguard Worker {
1121*f6dc9357SAndroid Build Coastguard Worker *outBufWasWritten = false;
1122*f6dc9357SAndroid Build Coastguard Worker *outBufWasWrittenSize = 0;
1123*f6dc9357SAndroid Build Coastguard Worker }
1124*f6dc9357SAndroid Build Coastguard Worker UInt32 method = _h.Method;
1125*f6dc9357SAndroid Build Coastguard Worker if (_h.SeveralMethods)
1126*f6dc9357SAndroid Build Coastguard Worker {
1127*f6dc9357SAndroid Build Coastguard Worker Byte b;
1128*f6dc9357SAndroid Build Coastguard Worker RINOK(ReadStream_FALSE(_stream, &b, 1))
1129*f6dc9357SAndroid Build Coastguard Worker RINOK(_stream->Seek(-1, STREAM_SEEK_CUR, NULL))
1130*f6dc9357SAndroid Build Coastguard Worker method = (b == 0x5D ? kMethod_LZMA : kMethod_ZLIB);
1131*f6dc9357SAndroid Build Coastguard Worker }
1132*f6dc9357SAndroid Build Coastguard Worker
1133*f6dc9357SAndroid Build Coastguard Worker if (method == kMethod_ZLIB && _needCheckLzma)
1134*f6dc9357SAndroid Build Coastguard Worker {
1135*f6dc9357SAndroid Build Coastguard Worker Byte b;
1136*f6dc9357SAndroid Build Coastguard Worker RINOK(ReadStream_FALSE(_stream, &b, 1))
1137*f6dc9357SAndroid Build Coastguard Worker RINOK(_stream->Seek(-1, STREAM_SEEK_CUR, NULL))
1138*f6dc9357SAndroid Build Coastguard Worker if (b == 0)
1139*f6dc9357SAndroid Build Coastguard Worker {
1140*f6dc9357SAndroid Build Coastguard Worker _noPropsLZMA = true;
1141*f6dc9357SAndroid Build Coastguard Worker method = _h.Method = kMethod_LZMA;
1142*f6dc9357SAndroid Build Coastguard Worker }
1143*f6dc9357SAndroid Build Coastguard Worker _needCheckLzma = false;
1144*f6dc9357SAndroid Build Coastguard Worker }
1145*f6dc9357SAndroid Build Coastguard Worker
1146*f6dc9357SAndroid Build Coastguard Worker if (method == kMethod_ZLIB)
1147*f6dc9357SAndroid Build Coastguard Worker {
1148*f6dc9357SAndroid Build Coastguard Worker _zlibDecoder.Create_if_Empty();
1149*f6dc9357SAndroid Build Coastguard Worker RINOK(_zlibDecoder.Interface()->Code(_limitedInStream, outStream, NULL, NULL, NULL))
1150*f6dc9357SAndroid Build Coastguard Worker if (inSize != _zlibDecoder->GetInputProcessedSize())
1151*f6dc9357SAndroid Build Coastguard Worker return S_FALSE;
1152*f6dc9357SAndroid Build Coastguard Worker }
1153*f6dc9357SAndroid Build Coastguard Worker /*
1154*f6dc9357SAndroid Build Coastguard Worker else if (method == kMethod_LZMA)
1155*f6dc9357SAndroid Build Coastguard Worker {
1156*f6dc9357SAndroid Build Coastguard Worker _lzmaDecoder.Create_if_Empty();
1157*f6dc9357SAndroid Build Coastguard Worker // _lzmaDecoder->FinishStream = true;
1158*f6dc9357SAndroid Build Coastguard Worker const UInt32 kPropsSize = LZMA_PROPS_SIZE + 8;
1159*f6dc9357SAndroid Build Coastguard Worker Byte props[kPropsSize];
1160*f6dc9357SAndroid Build Coastguard Worker UInt32 propsSize;
1161*f6dc9357SAndroid Build Coastguard Worker UInt64 outSize;
1162*f6dc9357SAndroid Build Coastguard Worker if (_noPropsLZMA)
1163*f6dc9357SAndroid Build Coastguard Worker {
1164*f6dc9357SAndroid Build Coastguard Worker props[0] = 0x5D;
1165*f6dc9357SAndroid Build Coastguard Worker SetUi32(&props[1], _h.BlockSize);
1166*f6dc9357SAndroid Build Coastguard Worker propsSize = 0;
1167*f6dc9357SAndroid Build Coastguard Worker outSize = outSizeMax;
1168*f6dc9357SAndroid Build Coastguard Worker }
1169*f6dc9357SAndroid Build Coastguard Worker else
1170*f6dc9357SAndroid Build Coastguard Worker {
1171*f6dc9357SAndroid Build Coastguard Worker RINOK(ReadStream_FALSE(_limitedInStream, props, kPropsSize));
1172*f6dc9357SAndroid Build Coastguard Worker propsSize = kPropsSize;
1173*f6dc9357SAndroid Build Coastguard Worker outSize = GetUi64(&props[LZMA_PROPS_SIZE]);
1174*f6dc9357SAndroid Build Coastguard Worker if (outSize > outSizeMax)
1175*f6dc9357SAndroid Build Coastguard Worker return S_FALSE;
1176*f6dc9357SAndroid Build Coastguard Worker }
1177*f6dc9357SAndroid Build Coastguard Worker RINOK(_lzmaDecoderSpec->SetDecoderProperties2(props, LZMA_PROPS_SIZE));
1178*f6dc9357SAndroid Build Coastguard Worker RINOK(_lzmaDecoder->Code(_limitedInStream, outStream, NULL, &outSize, NULL));
1179*f6dc9357SAndroid Build Coastguard Worker if (inSize != propsSize + _lzmaDecoderSpec->GetInputProcessedSize())
1180*f6dc9357SAndroid Build Coastguard Worker return S_FALSE;
1181*f6dc9357SAndroid Build Coastguard Worker }
1182*f6dc9357SAndroid Build Coastguard Worker */
1183*f6dc9357SAndroid Build Coastguard Worker else
1184*f6dc9357SAndroid Build Coastguard Worker {
1185*f6dc9357SAndroid Build Coastguard Worker if (_inputBuffer.Size() < inSize)
1186*f6dc9357SAndroid Build Coastguard Worker _inputBuffer.Alloc(inSize);
1187*f6dc9357SAndroid Build Coastguard Worker RINOK(ReadStream_FALSE(_stream, _inputBuffer, inSize))
1188*f6dc9357SAndroid Build Coastguard Worker
1189*f6dc9357SAndroid Build Coastguard Worker Byte *dest = outBuf;
1190*f6dc9357SAndroid Build Coastguard Worker if (!outBuf)
1191*f6dc9357SAndroid Build Coastguard Worker {
1192*f6dc9357SAndroid Build Coastguard Worker dest = _dynOutStream->GetBufPtrForWriting(outSizeMax);
1193*f6dc9357SAndroid Build Coastguard Worker if (!dest)
1194*f6dc9357SAndroid Build Coastguard Worker return E_OUTOFMEMORY;
1195*f6dc9357SAndroid Build Coastguard Worker }
1196*f6dc9357SAndroid Build Coastguard Worker
1197*f6dc9357SAndroid Build Coastguard Worker SizeT destLen = outSizeMax, srcLen = inSize;
1198*f6dc9357SAndroid Build Coastguard Worker
1199*f6dc9357SAndroid Build Coastguard Worker if (method == kMethod_LZO)
1200*f6dc9357SAndroid Build Coastguard Worker {
1201*f6dc9357SAndroid Build Coastguard Worker RINOK(LzoDecode(dest, &destLen, _inputBuffer, &srcLen))
1202*f6dc9357SAndroid Build Coastguard Worker }
1203*f6dc9357SAndroid Build Coastguard Worker else if (method == kMethod_LZMA)
1204*f6dc9357SAndroid Build Coastguard Worker {
1205*f6dc9357SAndroid Build Coastguard Worker Byte props[5];
1206*f6dc9357SAndroid Build Coastguard Worker const Byte *src = _inputBuffer;
1207*f6dc9357SAndroid Build Coastguard Worker
1208*f6dc9357SAndroid Build Coastguard Worker if (_noPropsLZMA)
1209*f6dc9357SAndroid Build Coastguard Worker {
1210*f6dc9357SAndroid Build Coastguard Worker props[0] = 0x5D;
1211*f6dc9357SAndroid Build Coastguard Worker SetUi32(&props[1], _h.BlockSize)
1212*f6dc9357SAndroid Build Coastguard Worker }
1213*f6dc9357SAndroid Build Coastguard Worker else
1214*f6dc9357SAndroid Build Coastguard Worker {
1215*f6dc9357SAndroid Build Coastguard Worker const UInt32 kPropsSize = LZMA_PROPS_SIZE + 8;
1216*f6dc9357SAndroid Build Coastguard Worker if (inSize < kPropsSize)
1217*f6dc9357SAndroid Build Coastguard Worker return S_FALSE;
1218*f6dc9357SAndroid Build Coastguard Worker memcpy(props, src, LZMA_PROPS_SIZE);
1219*f6dc9357SAndroid Build Coastguard Worker UInt64 outSize = GetUi64(src + LZMA_PROPS_SIZE);
1220*f6dc9357SAndroid Build Coastguard Worker if (outSize > outSizeMax)
1221*f6dc9357SAndroid Build Coastguard Worker return S_FALSE;
1222*f6dc9357SAndroid Build Coastguard Worker destLen = (SizeT)outSize;
1223*f6dc9357SAndroid Build Coastguard Worker src += kPropsSize;
1224*f6dc9357SAndroid Build Coastguard Worker inSize -= kPropsSize;
1225*f6dc9357SAndroid Build Coastguard Worker srcLen = inSize;
1226*f6dc9357SAndroid Build Coastguard Worker }
1227*f6dc9357SAndroid Build Coastguard Worker
1228*f6dc9357SAndroid Build Coastguard Worker ELzmaStatus status;
1229*f6dc9357SAndroid Build Coastguard Worker SRes res = LzmaDecode(dest, &destLen,
1230*f6dc9357SAndroid Build Coastguard Worker src, &srcLen,
1231*f6dc9357SAndroid Build Coastguard Worker props, LZMA_PROPS_SIZE,
1232*f6dc9357SAndroid Build Coastguard Worker LZMA_FINISH_END,
1233*f6dc9357SAndroid Build Coastguard Worker &status, &g_Alloc);
1234*f6dc9357SAndroid Build Coastguard Worker if (res != 0)
1235*f6dc9357SAndroid Build Coastguard Worker return SResToHRESULT(res);
1236*f6dc9357SAndroid Build Coastguard Worker if (status != LZMA_STATUS_FINISHED_WITH_MARK
1237*f6dc9357SAndroid Build Coastguard Worker && status != LZMA_STATUS_MAYBE_FINISHED_WITHOUT_MARK)
1238*f6dc9357SAndroid Build Coastguard Worker return S_FALSE;
1239*f6dc9357SAndroid Build Coastguard Worker }
1240*f6dc9357SAndroid Build Coastguard Worker else if (method == kMethod_ZSTD)
1241*f6dc9357SAndroid Build Coastguard Worker {
1242*f6dc9357SAndroid Build Coastguard Worker const Byte *src = _inputBuffer;
1243*f6dc9357SAndroid Build Coastguard Worker
1244*f6dc9357SAndroid Build Coastguard Worker if (!_zstd)
1245*f6dc9357SAndroid Build Coastguard Worker {
1246*f6dc9357SAndroid Build Coastguard Worker _zstd = ZstdDec_Create(&g_AlignedAlloc, &g_AlignedAlloc);
1247*f6dc9357SAndroid Build Coastguard Worker if (!_zstd)
1248*f6dc9357SAndroid Build Coastguard Worker return E_OUTOFMEMORY;
1249*f6dc9357SAndroid Build Coastguard Worker }
1250*f6dc9357SAndroid Build Coastguard Worker
1251*f6dc9357SAndroid Build Coastguard Worker CZstdDecState state;
1252*f6dc9357SAndroid Build Coastguard Worker ZstdDecState_Clear(&state);
1253*f6dc9357SAndroid Build Coastguard Worker
1254*f6dc9357SAndroid Build Coastguard Worker state.inBuf = src;
1255*f6dc9357SAndroid Build Coastguard Worker state.inLim = srcLen; // + 1; for debug
1256*f6dc9357SAndroid Build Coastguard Worker // state.outStep = outSizeMax;
1257*f6dc9357SAndroid Build Coastguard Worker
1258*f6dc9357SAndroid Build Coastguard Worker state.outBuf_fromCaller = dest;
1259*f6dc9357SAndroid Build Coastguard Worker state.outBufSize_fromCaller = outSizeMax;
1260*f6dc9357SAndroid Build Coastguard Worker // state.mustBeFinished = True;
1261*f6dc9357SAndroid Build Coastguard Worker
1262*f6dc9357SAndroid Build Coastguard Worker ZstdDec_Init(_zstd);
1263*f6dc9357SAndroid Build Coastguard Worker SRes sres;
1264*f6dc9357SAndroid Build Coastguard Worker for (;;)
1265*f6dc9357SAndroid Build Coastguard Worker {
1266*f6dc9357SAndroid Build Coastguard Worker sres = ZstdDec_Decode(_zstd, &state);
1267*f6dc9357SAndroid Build Coastguard Worker if (sres != SZ_OK)
1268*f6dc9357SAndroid Build Coastguard Worker break;
1269*f6dc9357SAndroid Build Coastguard Worker if (state.inLim == state.inPos
1270*f6dc9357SAndroid Build Coastguard Worker && (state.status == ZSTD_STATUS_NEEDS_MORE_INPUT ||
1271*f6dc9357SAndroid Build Coastguard Worker state.status == ZSTD_STATUS_FINISHED_FRAME))
1272*f6dc9357SAndroid Build Coastguard Worker break;
1273*f6dc9357SAndroid Build Coastguard Worker // sres = sres;
1274*f6dc9357SAndroid Build Coastguard Worker // break; // for debug
1275*f6dc9357SAndroid Build Coastguard Worker }
1276*f6dc9357SAndroid Build Coastguard Worker
1277*f6dc9357SAndroid Build Coastguard Worker CZstdDecResInfo info;
1278*f6dc9357SAndroid Build Coastguard Worker // ZstdDecInfo_Clear(&stat);
1279*f6dc9357SAndroid Build Coastguard Worker // stat->InSize = state.inPos;
1280*f6dc9357SAndroid Build Coastguard Worker ZstdDec_GetResInfo(_zstd, &state, sres, &info);
1281*f6dc9357SAndroid Build Coastguard Worker sres = info.decode_SRes;
1282*f6dc9357SAndroid Build Coastguard Worker if (sres == SZ_OK)
1283*f6dc9357SAndroid Build Coastguard Worker {
1284*f6dc9357SAndroid Build Coastguard Worker if (state.status != ZSTD_STATUS_FINISHED_FRAME
1285*f6dc9357SAndroid Build Coastguard Worker // ||stat.UnexpededEnd
1286*f6dc9357SAndroid Build Coastguard Worker || info.extraSize != 0
1287*f6dc9357SAndroid Build Coastguard Worker || state.inLim != state.inPos)
1288*f6dc9357SAndroid Build Coastguard Worker sres = SZ_ERROR_DATA;
1289*f6dc9357SAndroid Build Coastguard Worker }
1290*f6dc9357SAndroid Build Coastguard Worker if (sres != SZ_OK)
1291*f6dc9357SAndroid Build Coastguard Worker return SResToHRESULT(sres);
1292*f6dc9357SAndroid Build Coastguard Worker if (state.winPos > outSizeMax)
1293*f6dc9357SAndroid Build Coastguard Worker return E_FAIL;
1294*f6dc9357SAndroid Build Coastguard Worker // memcpy(dest, state.dic, state.dicPos);
1295*f6dc9357SAndroid Build Coastguard Worker destLen = state.winPos;
1296*f6dc9357SAndroid Build Coastguard Worker }
1297*f6dc9357SAndroid Build Coastguard Worker else
1298*f6dc9357SAndroid Build Coastguard Worker {
1299*f6dc9357SAndroid Build Coastguard Worker ECoderStatus status;
1300*f6dc9357SAndroid Build Coastguard Worker const SRes res = XzUnpacker_CodeFull(&_xz,
1301*f6dc9357SAndroid Build Coastguard Worker dest, &destLen,
1302*f6dc9357SAndroid Build Coastguard Worker _inputBuffer, &srcLen,
1303*f6dc9357SAndroid Build Coastguard Worker CODER_FINISH_END, &status);
1304*f6dc9357SAndroid Build Coastguard Worker if (res != 0)
1305*f6dc9357SAndroid Build Coastguard Worker return SResToHRESULT(res);
1306*f6dc9357SAndroid Build Coastguard Worker if (status != CODER_STATUS_NEEDS_MORE_INPUT || !XzUnpacker_IsStreamWasFinished(&_xz))
1307*f6dc9357SAndroid Build Coastguard Worker return S_FALSE;
1308*f6dc9357SAndroid Build Coastguard Worker }
1309*f6dc9357SAndroid Build Coastguard Worker
1310*f6dc9357SAndroid Build Coastguard Worker if (inSize != srcLen)
1311*f6dc9357SAndroid Build Coastguard Worker return S_FALSE;
1312*f6dc9357SAndroid Build Coastguard Worker if (outBuf)
1313*f6dc9357SAndroid Build Coastguard Worker {
1314*f6dc9357SAndroid Build Coastguard Worker *outBufWasWritten = true;
1315*f6dc9357SAndroid Build Coastguard Worker *outBufWasWrittenSize = (UInt32)destLen;
1316*f6dc9357SAndroid Build Coastguard Worker }
1317*f6dc9357SAndroid Build Coastguard Worker else
1318*f6dc9357SAndroid Build Coastguard Worker _dynOutStream->UpdateSize(destLen);
1319*f6dc9357SAndroid Build Coastguard Worker }
1320*f6dc9357SAndroid Build Coastguard Worker return S_OK;
1321*f6dc9357SAndroid Build Coastguard Worker }
1322*f6dc9357SAndroid Build Coastguard Worker
1323*f6dc9357SAndroid Build Coastguard Worker HRESULT CHandler::ReadMetadataBlock(UInt32 &packSize)
1324*f6dc9357SAndroid Build Coastguard Worker {
1325*f6dc9357SAndroid Build Coastguard Worker Byte temp[3];
1326*f6dc9357SAndroid Build Coastguard Worker const unsigned offset = _h.NeedCheckData() ? 3 : 2;
1327*f6dc9357SAndroid Build Coastguard Worker if (offset > packSize)
1328*f6dc9357SAndroid Build Coastguard Worker return S_FALSE;
1329*f6dc9357SAndroid Build Coastguard Worker RINOK(ReadStream_FALSE(_stream, temp, offset))
1330*f6dc9357SAndroid Build Coastguard Worker // if (NeedCheckData && Major < 4) checkByte must be = 0xFF
1331*f6dc9357SAndroid Build Coastguard Worker const bool be = _h.be;
1332*f6dc9357SAndroid Build Coastguard Worker UInt32 size = Get16(temp);
1333*f6dc9357SAndroid Build Coastguard Worker const bool isCompressed = ((size & kNotCompressedBit16) == 0);
1334*f6dc9357SAndroid Build Coastguard Worker if (size != kNotCompressedBit16)
1335*f6dc9357SAndroid Build Coastguard Worker size &= ~kNotCompressedBit16;
1336*f6dc9357SAndroid Build Coastguard Worker
1337*f6dc9357SAndroid Build Coastguard Worker if (size > kMetadataBlockSize || offset + size > packSize)
1338*f6dc9357SAndroid Build Coastguard Worker return S_FALSE;
1339*f6dc9357SAndroid Build Coastguard Worker packSize = offset + size;
1340*f6dc9357SAndroid Build Coastguard Worker if (isCompressed)
1341*f6dc9357SAndroid Build Coastguard Worker {
1342*f6dc9357SAndroid Build Coastguard Worker _limitedInStream->Init(size);
1343*f6dc9357SAndroid Build Coastguard Worker RINOK(Decompress(_dynOutStream, NULL, NULL, NULL, size, kMetadataBlockSize))
1344*f6dc9357SAndroid Build Coastguard Worker }
1345*f6dc9357SAndroid Build Coastguard Worker else
1346*f6dc9357SAndroid Build Coastguard Worker {
1347*f6dc9357SAndroid Build Coastguard Worker // size != 0 here
1348*f6dc9357SAndroid Build Coastguard Worker Byte *buf = _dynOutStream->GetBufPtrForWriting(size);
1349*f6dc9357SAndroid Build Coastguard Worker if (!buf)
1350*f6dc9357SAndroid Build Coastguard Worker return E_OUTOFMEMORY;
1351*f6dc9357SAndroid Build Coastguard Worker RINOK(ReadStream_FALSE(_stream, buf, size))
1352*f6dc9357SAndroid Build Coastguard Worker _dynOutStream->UpdateSize(size);
1353*f6dc9357SAndroid Build Coastguard Worker }
1354*f6dc9357SAndroid Build Coastguard Worker return S_OK;
1355*f6dc9357SAndroid Build Coastguard Worker }
1356*f6dc9357SAndroid Build Coastguard Worker
1357*f6dc9357SAndroid Build Coastguard Worker
1358*f6dc9357SAndroid Build Coastguard Worker HRESULT CHandler::ReadMetadataBlock2()
1359*f6dc9357SAndroid Build Coastguard Worker {
1360*f6dc9357SAndroid Build Coastguard Worker _dynOutStream->Init();
1361*f6dc9357SAndroid Build Coastguard Worker UInt32 packSize = kMetadataBlockSize + 3; // check it
1362*f6dc9357SAndroid Build Coastguard Worker return ReadMetadataBlock(packSize);
1363*f6dc9357SAndroid Build Coastguard Worker }
1364*f6dc9357SAndroid Build Coastguard Worker
1365*f6dc9357SAndroid Build Coastguard Worker HRESULT CHandler::ReadData(CData &data, UInt64 start, UInt64 end)
1366*f6dc9357SAndroid Build Coastguard Worker {
1367*f6dc9357SAndroid Build Coastguard Worker if (end < start || end - start >= ((UInt64)1 << 32))
1368*f6dc9357SAndroid Build Coastguard Worker return S_FALSE;
1369*f6dc9357SAndroid Build Coastguard Worker const UInt32 size = (UInt32)(end - start);
1370*f6dc9357SAndroid Build Coastguard Worker RINOK(Seek2(start))
1371*f6dc9357SAndroid Build Coastguard Worker _dynOutStream->Init();
1372*f6dc9357SAndroid Build Coastguard Worker UInt32 packPos = 0;
1373*f6dc9357SAndroid Build Coastguard Worker while (packPos != size)
1374*f6dc9357SAndroid Build Coastguard Worker {
1375*f6dc9357SAndroid Build Coastguard Worker data.PackPos.Add(packPos);
1376*f6dc9357SAndroid Build Coastguard Worker data.UnpackPos.Add((UInt32)_dynOutStream->GetSize());
1377*f6dc9357SAndroid Build Coastguard Worker if (packPos > size)
1378*f6dc9357SAndroid Build Coastguard Worker return S_FALSE;
1379*f6dc9357SAndroid Build Coastguard Worker UInt32 packSize = size - packPos;
1380*f6dc9357SAndroid Build Coastguard Worker RINOK(ReadMetadataBlock(packSize))
1381*f6dc9357SAndroid Build Coastguard Worker {
1382*f6dc9357SAndroid Build Coastguard Worker const size_t tSize = _dynOutStream->GetSize();
1383*f6dc9357SAndroid Build Coastguard Worker if (tSize != (UInt32)tSize)
1384*f6dc9357SAndroid Build Coastguard Worker return S_FALSE;
1385*f6dc9357SAndroid Build Coastguard Worker }
1386*f6dc9357SAndroid Build Coastguard Worker packPos += packSize;
1387*f6dc9357SAndroid Build Coastguard Worker }
1388*f6dc9357SAndroid Build Coastguard Worker data.UnpackPos.Add((UInt32)_dynOutStream->GetSize());
1389*f6dc9357SAndroid Build Coastguard Worker _dynOutStream->CopyToBuffer(data.Data);
1390*f6dc9357SAndroid Build Coastguard Worker return S_OK;
1391*f6dc9357SAndroid Build Coastguard Worker }
1392*f6dc9357SAndroid Build Coastguard Worker
1393*f6dc9357SAndroid Build Coastguard Worker struct CTempItem
1394*f6dc9357SAndroid Build Coastguard Worker {
1395*f6dc9357SAndroid Build Coastguard Worker UInt32 StartBlock;
1396*f6dc9357SAndroid Build Coastguard Worker // UInt32 iNodeNumber1;
1397*f6dc9357SAndroid Build Coastguard Worker UInt32 Offset;
1398*f6dc9357SAndroid Build Coastguard Worker // UInt16 iNodeNumber2;
1399*f6dc9357SAndroid Build Coastguard Worker UInt16 Type;
1400*f6dc9357SAndroid Build Coastguard Worker };
1401*f6dc9357SAndroid Build Coastguard Worker
1402*f6dc9357SAndroid Build Coastguard Worker HRESULT CHandler::OpenDir(int parent, UInt32 startBlock, UInt32 offset, unsigned level, int &nodeIndex)
1403*f6dc9357SAndroid Build Coastguard Worker {
1404*f6dc9357SAndroid Build Coastguard Worker if (level > kNumDirLevelsMax)
1405*f6dc9357SAndroid Build Coastguard Worker return S_FALSE;
1406*f6dc9357SAndroid Build Coastguard Worker
1407*f6dc9357SAndroid Build Coastguard Worker int blockIndex = _inodesData.PackPos.FindInSorted(startBlock);
1408*f6dc9357SAndroid Build Coastguard Worker if (blockIndex < 0)
1409*f6dc9357SAndroid Build Coastguard Worker return S_FALSE;
1410*f6dc9357SAndroid Build Coastguard Worker UInt32 unpackPos = _inodesData.UnpackPos[blockIndex] + offset;
1411*f6dc9357SAndroid Build Coastguard Worker if (unpackPos < offset)
1412*f6dc9357SAndroid Build Coastguard Worker return S_FALSE;
1413*f6dc9357SAndroid Build Coastguard Worker
1414*f6dc9357SAndroid Build Coastguard Worker nodeIndex = _nodesPos.FindInSorted(unpackPos, _blockToNode[blockIndex], _blockToNode[blockIndex + 1]);
1415*f6dc9357SAndroid Build Coastguard Worker // nodeIndex = _nodesPos.FindInSorted(unpackPos);
1416*f6dc9357SAndroid Build Coastguard Worker if (nodeIndex < 0)
1417*f6dc9357SAndroid Build Coastguard Worker return S_FALSE;
1418*f6dc9357SAndroid Build Coastguard Worker
1419*f6dc9357SAndroid Build Coastguard Worker const CNode &n = _nodes[nodeIndex];
1420*f6dc9357SAndroid Build Coastguard Worker if (!n.IsDir())
1421*f6dc9357SAndroid Build Coastguard Worker return S_OK;
1422*f6dc9357SAndroid Build Coastguard Worker blockIndex = _dirs.PackPos.FindInSorted((UInt32)n.StartBlock);
1423*f6dc9357SAndroid Build Coastguard Worker if (blockIndex < 0)
1424*f6dc9357SAndroid Build Coastguard Worker return S_FALSE;
1425*f6dc9357SAndroid Build Coastguard Worker unpackPos = _dirs.UnpackPos[blockIndex] + n.Offset;
1426*f6dc9357SAndroid Build Coastguard Worker if (unpackPos < n.Offset || unpackPos > _dirs.Data.Size())
1427*f6dc9357SAndroid Build Coastguard Worker return S_FALSE;
1428*f6dc9357SAndroid Build Coastguard Worker
1429*f6dc9357SAndroid Build Coastguard Worker UInt32 rem = (UInt32)_dirs.Data.Size() - unpackPos;
1430*f6dc9357SAndroid Build Coastguard Worker const Byte *p = _dirs.Data + unpackPos;
1431*f6dc9357SAndroid Build Coastguard Worker UInt32 fileSize = (UInt32)n.FileSize;
1432*f6dc9357SAndroid Build Coastguard Worker
1433*f6dc9357SAndroid Build Coastguard Worker // for some squashfs files: fileSize = rem + 3 !!!
1434*f6dc9357SAndroid Build Coastguard Worker if (_h.Major >= 3)
1435*f6dc9357SAndroid Build Coastguard Worker {
1436*f6dc9357SAndroid Build Coastguard Worker if (fileSize < 3)
1437*f6dc9357SAndroid Build Coastguard Worker return S_FALSE;
1438*f6dc9357SAndroid Build Coastguard Worker fileSize -= 3;
1439*f6dc9357SAndroid Build Coastguard Worker }
1440*f6dc9357SAndroid Build Coastguard Worker if (fileSize > rem)
1441*f6dc9357SAndroid Build Coastguard Worker return S_FALSE;
1442*f6dc9357SAndroid Build Coastguard Worker rem = fileSize;
1443*f6dc9357SAndroid Build Coastguard Worker
1444*f6dc9357SAndroid Build Coastguard Worker AString tempString;
1445*f6dc9357SAndroid Build Coastguard Worker
1446*f6dc9357SAndroid Build Coastguard Worker CRecordVector<CTempItem> tempItems;
1447*f6dc9357SAndroid Build Coastguard Worker while (rem != 0)
1448*f6dc9357SAndroid Build Coastguard Worker {
1449*f6dc9357SAndroid Build Coastguard Worker const bool be = _h.be;
1450*f6dc9357SAndroid Build Coastguard Worker UInt32 count;
1451*f6dc9357SAndroid Build Coastguard Worker CTempItem tempItem;
1452*f6dc9357SAndroid Build Coastguard Worker if (_h.Major <= 2)
1453*f6dc9357SAndroid Build Coastguard Worker {
1454*f6dc9357SAndroid Build Coastguard Worker if (rem < 4)
1455*f6dc9357SAndroid Build Coastguard Worker return S_FALSE;
1456*f6dc9357SAndroid Build Coastguard Worker count = p[0];
1457*f6dc9357SAndroid Build Coastguard Worker tempItem.StartBlock = Get32(p);
1458*f6dc9357SAndroid Build Coastguard Worker if (be)
1459*f6dc9357SAndroid Build Coastguard Worker tempItem.StartBlock &= 0xFFFFFF;
1460*f6dc9357SAndroid Build Coastguard Worker else
1461*f6dc9357SAndroid Build Coastguard Worker tempItem.StartBlock >>= 8;
1462*f6dc9357SAndroid Build Coastguard Worker p += 4;
1463*f6dc9357SAndroid Build Coastguard Worker rem -= 4;
1464*f6dc9357SAndroid Build Coastguard Worker }
1465*f6dc9357SAndroid Build Coastguard Worker else
1466*f6dc9357SAndroid Build Coastguard Worker {
1467*f6dc9357SAndroid Build Coastguard Worker if (_h.Major == 3)
1468*f6dc9357SAndroid Build Coastguard Worker {
1469*f6dc9357SAndroid Build Coastguard Worker if (rem < 9)
1470*f6dc9357SAndroid Build Coastguard Worker return S_FALSE;
1471*f6dc9357SAndroid Build Coastguard Worker count = p[0];
1472*f6dc9357SAndroid Build Coastguard Worker p += 1;
1473*f6dc9357SAndroid Build Coastguard Worker rem -= 1;
1474*f6dc9357SAndroid Build Coastguard Worker }
1475*f6dc9357SAndroid Build Coastguard Worker else
1476*f6dc9357SAndroid Build Coastguard Worker {
1477*f6dc9357SAndroid Build Coastguard Worker if (rem < 12)
1478*f6dc9357SAndroid Build Coastguard Worker return S_FALSE;
1479*f6dc9357SAndroid Build Coastguard Worker count = GetUi32(p);
1480*f6dc9357SAndroid Build Coastguard Worker p += 4;
1481*f6dc9357SAndroid Build Coastguard Worker rem -= 4;
1482*f6dc9357SAndroid Build Coastguard Worker }
1483*f6dc9357SAndroid Build Coastguard Worker GET_32 (0, tempItem.StartBlock);
1484*f6dc9357SAndroid Build Coastguard Worker // GET_32 (4, tempItem.iNodeNumber1);
1485*f6dc9357SAndroid Build Coastguard Worker p += 8;
1486*f6dc9357SAndroid Build Coastguard Worker rem -= 8;
1487*f6dc9357SAndroid Build Coastguard Worker }
1488*f6dc9357SAndroid Build Coastguard Worker count++;
1489*f6dc9357SAndroid Build Coastguard Worker
1490*f6dc9357SAndroid Build Coastguard Worker for (UInt32 i = 0; i < count; i++)
1491*f6dc9357SAndroid Build Coastguard Worker {
1492*f6dc9357SAndroid Build Coastguard Worker if (rem == 0)
1493*f6dc9357SAndroid Build Coastguard Worker return S_FALSE;
1494*f6dc9357SAndroid Build Coastguard Worker
1495*f6dc9357SAndroid Build Coastguard Worker UInt32 nameOffset = _h.GetFileNameOffset();
1496*f6dc9357SAndroid Build Coastguard Worker if (rem < nameOffset)
1497*f6dc9357SAndroid Build Coastguard Worker return S_FALSE;
1498*f6dc9357SAndroid Build Coastguard Worker
1499*f6dc9357SAndroid Build Coastguard Worker if (_items.Size() >= kNumFilesMax)
1500*f6dc9357SAndroid Build Coastguard Worker return S_FALSE;
1501*f6dc9357SAndroid Build Coastguard Worker if (_openCallback)
1502*f6dc9357SAndroid Build Coastguard Worker {
1503*f6dc9357SAndroid Build Coastguard Worker UInt64 numFiles = _items.Size();
1504*f6dc9357SAndroid Build Coastguard Worker if ((numFiles & 0xFFFF) == 0)
1505*f6dc9357SAndroid Build Coastguard Worker {
1506*f6dc9357SAndroid Build Coastguard Worker RINOK(_openCallback->SetCompleted(&numFiles, NULL))
1507*f6dc9357SAndroid Build Coastguard Worker }
1508*f6dc9357SAndroid Build Coastguard Worker }
1509*f6dc9357SAndroid Build Coastguard Worker
1510*f6dc9357SAndroid Build Coastguard Worker CItem item;
1511*f6dc9357SAndroid Build Coastguard Worker item.Ptr = (UInt32)(p - (const Byte *)_dirs.Data);
1512*f6dc9357SAndroid Build Coastguard Worker
1513*f6dc9357SAndroid Build Coastguard Worker UInt32 size;
1514*f6dc9357SAndroid Build Coastguard Worker if (_h.IsOldVersion())
1515*f6dc9357SAndroid Build Coastguard Worker {
1516*f6dc9357SAndroid Build Coastguard Worker UInt32 t = Get16(p);
1517*f6dc9357SAndroid Build Coastguard Worker if (be)
1518*f6dc9357SAndroid Build Coastguard Worker {
1519*f6dc9357SAndroid Build Coastguard Worker tempItem.Offset = t >> 3;
1520*f6dc9357SAndroid Build Coastguard Worker tempItem.Type = (UInt16)(t & 0x7);
1521*f6dc9357SAndroid Build Coastguard Worker }
1522*f6dc9357SAndroid Build Coastguard Worker else
1523*f6dc9357SAndroid Build Coastguard Worker {
1524*f6dc9357SAndroid Build Coastguard Worker tempItem.Offset = t & 0x1FFF;
1525*f6dc9357SAndroid Build Coastguard Worker tempItem.Type = (UInt16)(t >> 13);
1526*f6dc9357SAndroid Build Coastguard Worker }
1527*f6dc9357SAndroid Build Coastguard Worker size = (UInt32)p[2];
1528*f6dc9357SAndroid Build Coastguard Worker /*
1529*f6dc9357SAndroid Build Coastguard Worker if (_h.Major > 2)
1530*f6dc9357SAndroid Build Coastguard Worker tempItem.iNodeNumber2 = Get16(p + 3);
1531*f6dc9357SAndroid Build Coastguard Worker */
1532*f6dc9357SAndroid Build Coastguard Worker }
1533*f6dc9357SAndroid Build Coastguard Worker else
1534*f6dc9357SAndroid Build Coastguard Worker {
1535*f6dc9357SAndroid Build Coastguard Worker GET_16 (0, tempItem.Offset);
1536*f6dc9357SAndroid Build Coastguard Worker // GET_16 (2, tempItem.iNodeNumber2);
1537*f6dc9357SAndroid Build Coastguard Worker GET_16 (4, tempItem.Type);
1538*f6dc9357SAndroid Build Coastguard Worker GET_16 (6, size);
1539*f6dc9357SAndroid Build Coastguard Worker }
1540*f6dc9357SAndroid Build Coastguard Worker p += nameOffset;
1541*f6dc9357SAndroid Build Coastguard Worker rem -= nameOffset;
1542*f6dc9357SAndroid Build Coastguard Worker size++;
1543*f6dc9357SAndroid Build Coastguard Worker if (rem < size)
1544*f6dc9357SAndroid Build Coastguard Worker return S_FALSE;
1545*f6dc9357SAndroid Build Coastguard Worker
1546*f6dc9357SAndroid Build Coastguard Worker if (_openCodePage == CP_UTF8)
1547*f6dc9357SAndroid Build Coastguard Worker {
1548*f6dc9357SAndroid Build Coastguard Worker tempString.SetFrom_CalcLen((const char *)p, size);
1549*f6dc9357SAndroid Build Coastguard Worker if (!CheckUTF8_AString(tempString))
1550*f6dc9357SAndroid Build Coastguard Worker _openCodePage = CP_OEMCP;
1551*f6dc9357SAndroid Build Coastguard Worker }
1552*f6dc9357SAndroid Build Coastguard Worker
1553*f6dc9357SAndroid Build Coastguard Worker p += size;
1554*f6dc9357SAndroid Build Coastguard Worker rem -= size;
1555*f6dc9357SAndroid Build Coastguard Worker item.Parent = parent;
1556*f6dc9357SAndroid Build Coastguard Worker _items.Add(item);
1557*f6dc9357SAndroid Build Coastguard Worker tempItems.Add(tempItem);
1558*f6dc9357SAndroid Build Coastguard Worker }
1559*f6dc9357SAndroid Build Coastguard Worker }
1560*f6dc9357SAndroid Build Coastguard Worker
1561*f6dc9357SAndroid Build Coastguard Worker const unsigned startItemIndex = _items.Size() - tempItems.Size();
1562*f6dc9357SAndroid Build Coastguard Worker FOR_VECTOR (i, tempItems)
1563*f6dc9357SAndroid Build Coastguard Worker {
1564*f6dc9357SAndroid Build Coastguard Worker const CTempItem &tempItem = tempItems[i];
1565*f6dc9357SAndroid Build Coastguard Worker const unsigned index = startItemIndex + i;
1566*f6dc9357SAndroid Build Coastguard Worker CItem &item = _items[index];
1567*f6dc9357SAndroid Build Coastguard Worker RINOK(OpenDir((int)index, tempItem.StartBlock, tempItem.Offset, level + 1, item.Node))
1568*f6dc9357SAndroid Build Coastguard Worker }
1569*f6dc9357SAndroid Build Coastguard Worker
1570*f6dc9357SAndroid Build Coastguard Worker return S_OK;
1571*f6dc9357SAndroid Build Coastguard Worker }
1572*f6dc9357SAndroid Build Coastguard Worker
1573*f6dc9357SAndroid Build Coastguard Worker HRESULT CHandler::ReadUids(UInt64 start, UInt32 num, CByteBuffer &ids)
1574*f6dc9357SAndroid Build Coastguard Worker {
1575*f6dc9357SAndroid Build Coastguard Worker const size_t size = (size_t)num * 4;
1576*f6dc9357SAndroid Build Coastguard Worker ids.Alloc(size);
1577*f6dc9357SAndroid Build Coastguard Worker if (num == 0)
1578*f6dc9357SAndroid Build Coastguard Worker return S_OK;
1579*f6dc9357SAndroid Build Coastguard Worker RINOK(Seek2(start))
1580*f6dc9357SAndroid Build Coastguard Worker return ReadStream_FALSE(_stream, ids, size);
1581*f6dc9357SAndroid Build Coastguard Worker }
1582*f6dc9357SAndroid Build Coastguard Worker
1583*f6dc9357SAndroid Build Coastguard Worker HRESULT CHandler::Open2(IInStream *inStream)
1584*f6dc9357SAndroid Build Coastguard Worker {
1585*f6dc9357SAndroid Build Coastguard Worker {
1586*f6dc9357SAndroid Build Coastguard Worker Byte buf[kHeaderSize3];
1587*f6dc9357SAndroid Build Coastguard Worker RINOK(ReadStream_FALSE(inStream, buf, kHeaderSize3))
1588*f6dc9357SAndroid Build Coastguard Worker if (!_h.Parse(buf))
1589*f6dc9357SAndroid Build Coastguard Worker return S_FALSE;
1590*f6dc9357SAndroid Build Coastguard Worker if (!_h.IsSupported())
1591*f6dc9357SAndroid Build Coastguard Worker return E_NOTIMPL;
1592*f6dc9357SAndroid Build Coastguard Worker
1593*f6dc9357SAndroid Build Coastguard Worker _noPropsLZMA = false;
1594*f6dc9357SAndroid Build Coastguard Worker _needCheckLzma = false;
1595*f6dc9357SAndroid Build Coastguard Worker switch (_h.Method)
1596*f6dc9357SAndroid Build Coastguard Worker {
1597*f6dc9357SAndroid Build Coastguard Worker case kMethod_ZLIB: _needCheckLzma = true; break;
1598*f6dc9357SAndroid Build Coastguard Worker case kMethod_LZMA:
1599*f6dc9357SAndroid Build Coastguard Worker case kMethod_LZO:
1600*f6dc9357SAndroid Build Coastguard Worker case kMethod_XZ:
1601*f6dc9357SAndroid Build Coastguard Worker case kMethod_ZSTD:
1602*f6dc9357SAndroid Build Coastguard Worker break;
1603*f6dc9357SAndroid Build Coastguard Worker default:
1604*f6dc9357SAndroid Build Coastguard Worker return E_NOTIMPL;
1605*f6dc9357SAndroid Build Coastguard Worker }
1606*f6dc9357SAndroid Build Coastguard Worker }
1607*f6dc9357SAndroid Build Coastguard Worker
1608*f6dc9357SAndroid Build Coastguard Worker _stream = inStream;
1609*f6dc9357SAndroid Build Coastguard Worker
1610*f6dc9357SAndroid Build Coastguard Worker if (_h.NumFrags != 0)
1611*f6dc9357SAndroid Build Coastguard Worker {
1612*f6dc9357SAndroid Build Coastguard Worker if (_h.NumFrags > kNumFilesMax)
1613*f6dc9357SAndroid Build Coastguard Worker return S_FALSE;
1614*f6dc9357SAndroid Build Coastguard Worker _frags.ClearAndReserve(_h.NumFrags);
1615*f6dc9357SAndroid Build Coastguard Worker const unsigned bigFrag = (_h.Major > 2);
1616*f6dc9357SAndroid Build Coastguard Worker
1617*f6dc9357SAndroid Build Coastguard Worker const unsigned fragPtrsInBlockLog = kMetadataBlockSizeLog - (3 + bigFrag);
1618*f6dc9357SAndroid Build Coastguard Worker const UInt32 numBlocks = (_h.NumFrags + (1 << fragPtrsInBlockLog) - 1) >> fragPtrsInBlockLog;
1619*f6dc9357SAndroid Build Coastguard Worker const size_t numBlocksBytes = (size_t)numBlocks << (2 + bigFrag);
1620*f6dc9357SAndroid Build Coastguard Worker CByteBuffer data(numBlocksBytes);
1621*f6dc9357SAndroid Build Coastguard Worker RINOK(Seek2(_h.FragTable))
1622*f6dc9357SAndroid Build Coastguard Worker RINOK(ReadStream_FALSE(inStream, data, numBlocksBytes))
1623*f6dc9357SAndroid Build Coastguard Worker const bool be = _h.be;
1624*f6dc9357SAndroid Build Coastguard Worker
1625*f6dc9357SAndroid Build Coastguard Worker for (UInt32 i = 0; i < numBlocks; i++)
1626*f6dc9357SAndroid Build Coastguard Worker {
1627*f6dc9357SAndroid Build Coastguard Worker const UInt64 offset = bigFrag ? Get64(data + i * 8) : Get32(data + i * 4);
1628*f6dc9357SAndroid Build Coastguard Worker RINOK(Seek2(offset))
1629*f6dc9357SAndroid Build Coastguard Worker RINOK(ReadMetadataBlock2())
1630*f6dc9357SAndroid Build Coastguard Worker const UInt32 unpackSize = (UInt32)_dynOutStream->GetSize();
1631*f6dc9357SAndroid Build Coastguard Worker if (unpackSize != kMetadataBlockSize)
1632*f6dc9357SAndroid Build Coastguard Worker if (i != numBlocks - 1 || unpackSize != ((_h.NumFrags << (3 + bigFrag)) & (kMetadataBlockSize - 1)))
1633*f6dc9357SAndroid Build Coastguard Worker return S_FALSE;
1634*f6dc9357SAndroid Build Coastguard Worker const Byte *buf = _dynOutStream->GetBuffer();
1635*f6dc9357SAndroid Build Coastguard Worker for (UInt32 j = 0; j < kMetadataBlockSize && j < unpackSize;)
1636*f6dc9357SAndroid Build Coastguard Worker {
1637*f6dc9357SAndroid Build Coastguard Worker CFrag frag;
1638*f6dc9357SAndroid Build Coastguard Worker if (bigFrag)
1639*f6dc9357SAndroid Build Coastguard Worker {
1640*f6dc9357SAndroid Build Coastguard Worker frag.StartBlock = Get64(buf + j);
1641*f6dc9357SAndroid Build Coastguard Worker frag.Size = Get32(buf + j + 8);
1642*f6dc9357SAndroid Build Coastguard Worker // some archives contain nonzero in unused (buf + j + 12)
1643*f6dc9357SAndroid Build Coastguard Worker j += 16;
1644*f6dc9357SAndroid Build Coastguard Worker }
1645*f6dc9357SAndroid Build Coastguard Worker else
1646*f6dc9357SAndroid Build Coastguard Worker {
1647*f6dc9357SAndroid Build Coastguard Worker frag.StartBlock = Get32(buf + j);
1648*f6dc9357SAndroid Build Coastguard Worker frag.Size = Get32(buf + j + 4);
1649*f6dc9357SAndroid Build Coastguard Worker j += 8;
1650*f6dc9357SAndroid Build Coastguard Worker }
1651*f6dc9357SAndroid Build Coastguard Worker _frags.Add(frag);
1652*f6dc9357SAndroid Build Coastguard Worker }
1653*f6dc9357SAndroid Build Coastguard Worker }
1654*f6dc9357SAndroid Build Coastguard Worker if ((UInt32)_frags.Size() != _h.NumFrags)
1655*f6dc9357SAndroid Build Coastguard Worker return S_FALSE;
1656*f6dc9357SAndroid Build Coastguard Worker }
1657*f6dc9357SAndroid Build Coastguard Worker
1658*f6dc9357SAndroid Build Coastguard Worker RINOK(ReadData(_inodesData, _h.InodeTable, _h.DirTable))
1659*f6dc9357SAndroid Build Coastguard Worker RINOK(ReadData(_dirs, _h.DirTable, _h.FragTable))
1660*f6dc9357SAndroid Build Coastguard Worker
1661*f6dc9357SAndroid Build Coastguard Worker UInt64 absOffset = _h.RootInode >> 16;
1662*f6dc9357SAndroid Build Coastguard Worker if (absOffset >= ((UInt64)1 << 32))
1663*f6dc9357SAndroid Build Coastguard Worker return S_FALSE;
1664*f6dc9357SAndroid Build Coastguard Worker {
1665*f6dc9357SAndroid Build Coastguard Worker UInt32 pos = 0;
1666*f6dc9357SAndroid Build Coastguard Worker UInt32 totalSize = (UInt32)_inodesData.Data.Size();
1667*f6dc9357SAndroid Build Coastguard Worker const unsigned kMinNodeParseSize = 4;
1668*f6dc9357SAndroid Build Coastguard Worker if (_h.NumInodes > totalSize / kMinNodeParseSize)
1669*f6dc9357SAndroid Build Coastguard Worker return S_FALSE;
1670*f6dc9357SAndroid Build Coastguard Worker _nodesPos.ClearAndReserve(_h.NumInodes);
1671*f6dc9357SAndroid Build Coastguard Worker _nodes.ClearAndReserve(_h.NumInodes);
1672*f6dc9357SAndroid Build Coastguard Worker // we use _blockToNode for binary search seed optimizations
1673*f6dc9357SAndroid Build Coastguard Worker _blockToNode.ClearAndReserve(_inodesData.GetNumBlocks() + 1);
1674*f6dc9357SAndroid Build Coastguard Worker unsigned curBlock = 0;
1675*f6dc9357SAndroid Build Coastguard Worker for (UInt32 i = 0; i < _h.NumInodes; i++)
1676*f6dc9357SAndroid Build Coastguard Worker {
1677*f6dc9357SAndroid Build Coastguard Worker CNode n;
1678*f6dc9357SAndroid Build Coastguard Worker const Byte *p = _inodesData.Data + pos;
1679*f6dc9357SAndroid Build Coastguard Worker UInt32 size = totalSize - pos;
1680*f6dc9357SAndroid Build Coastguard Worker
1681*f6dc9357SAndroid Build Coastguard Worker switch (_h.Major)
1682*f6dc9357SAndroid Build Coastguard Worker {
1683*f6dc9357SAndroid Build Coastguard Worker case 1: size = n.Parse1(p, size, _h); break;
1684*f6dc9357SAndroid Build Coastguard Worker case 2: size = n.Parse2(p, size, _h); break;
1685*f6dc9357SAndroid Build Coastguard Worker case 3: size = n.Parse3(p, size, _h); break;
1686*f6dc9357SAndroid Build Coastguard Worker default: size = n.Parse4(p, size, _h); break;
1687*f6dc9357SAndroid Build Coastguard Worker }
1688*f6dc9357SAndroid Build Coastguard Worker if (size == 0)
1689*f6dc9357SAndroid Build Coastguard Worker return S_FALSE;
1690*f6dc9357SAndroid Build Coastguard Worker while (pos >= _inodesData.UnpackPos[curBlock])
1691*f6dc9357SAndroid Build Coastguard Worker {
1692*f6dc9357SAndroid Build Coastguard Worker _blockToNode.Add(_nodesPos.Size());
1693*f6dc9357SAndroid Build Coastguard Worker curBlock++;
1694*f6dc9357SAndroid Build Coastguard Worker }
1695*f6dc9357SAndroid Build Coastguard Worker _nodesPos.AddInReserved(pos);
1696*f6dc9357SAndroid Build Coastguard Worker _nodes.AddInReserved(n);
1697*f6dc9357SAndroid Build Coastguard Worker pos += size;
1698*f6dc9357SAndroid Build Coastguard Worker }
1699*f6dc9357SAndroid Build Coastguard Worker _blockToNode.Add(_nodesPos.Size());
1700*f6dc9357SAndroid Build Coastguard Worker if (pos != totalSize)
1701*f6dc9357SAndroid Build Coastguard Worker return S_FALSE;
1702*f6dc9357SAndroid Build Coastguard Worker }
1703*f6dc9357SAndroid Build Coastguard Worker int rootNodeIndex;
1704*f6dc9357SAndroid Build Coastguard Worker RINOK(OpenDir(-1, (UInt32)absOffset, (UInt32)_h.RootInode & 0xFFFF, 0, rootNodeIndex))
1705*f6dc9357SAndroid Build Coastguard Worker
1706*f6dc9357SAndroid Build Coastguard Worker if (_h.Major < 4)
1707*f6dc9357SAndroid Build Coastguard Worker {
1708*f6dc9357SAndroid Build Coastguard Worker RINOK(ReadUids(_h.UidTable, _h.NumUids, _uids))
1709*f6dc9357SAndroid Build Coastguard Worker RINOK(ReadUids(_h.GidTable, _h.NumGids, _gids))
1710*f6dc9357SAndroid Build Coastguard Worker }
1711*f6dc9357SAndroid Build Coastguard Worker else
1712*f6dc9357SAndroid Build Coastguard Worker {
1713*f6dc9357SAndroid Build Coastguard Worker const UInt32 size = (UInt32)_h.NumIDs * 4;
1714*f6dc9357SAndroid Build Coastguard Worker _uids.Alloc(size);
1715*f6dc9357SAndroid Build Coastguard Worker
1716*f6dc9357SAndroid Build Coastguard Worker const UInt32 numBlocks = (size + kMetadataBlockSize - 1) / kMetadataBlockSize;
1717*f6dc9357SAndroid Build Coastguard Worker const UInt32 numBlocksBytes = numBlocks << 3;
1718*f6dc9357SAndroid Build Coastguard Worker CByteBuffer data(numBlocksBytes);
1719*f6dc9357SAndroid Build Coastguard Worker RINOK(Seek2(_h.UidTable))
1720*f6dc9357SAndroid Build Coastguard Worker RINOK(ReadStream_FALSE(inStream, data, numBlocksBytes))
1721*f6dc9357SAndroid Build Coastguard Worker
1722*f6dc9357SAndroid Build Coastguard Worker for (UInt32 i = 0; i < numBlocks; i++)
1723*f6dc9357SAndroid Build Coastguard Worker {
1724*f6dc9357SAndroid Build Coastguard Worker const UInt64 offset = GetUi64(data + i * 8);
1725*f6dc9357SAndroid Build Coastguard Worker RINOK(Seek2(offset))
1726*f6dc9357SAndroid Build Coastguard Worker // RINOK(ReadMetadataBlock(NULL, _uids + kMetadataBlockSize * i, packSize, unpackSize));
1727*f6dc9357SAndroid Build Coastguard Worker RINOK(ReadMetadataBlock2())
1728*f6dc9357SAndroid Build Coastguard Worker const size_t unpackSize = _dynOutStream->GetSize();
1729*f6dc9357SAndroid Build Coastguard Worker const UInt32 remSize = (i == numBlocks - 1) ?
1730*f6dc9357SAndroid Build Coastguard Worker (size & (kMetadataBlockSize - 1)) : kMetadataBlockSize;
1731*f6dc9357SAndroid Build Coastguard Worker if (unpackSize != remSize)
1732*f6dc9357SAndroid Build Coastguard Worker return S_FALSE;
1733*f6dc9357SAndroid Build Coastguard Worker memcpy(_uids + kMetadataBlockSize * i, _dynOutStream->GetBuffer(), remSize);
1734*f6dc9357SAndroid Build Coastguard Worker }
1735*f6dc9357SAndroid Build Coastguard Worker }
1736*f6dc9357SAndroid Build Coastguard Worker
1737*f6dc9357SAndroid Build Coastguard Worker {
1738*f6dc9357SAndroid Build Coastguard Worker const UInt32 alignSize = 1 << 12;
1739*f6dc9357SAndroid Build Coastguard Worker Byte buf[alignSize];
1740*f6dc9357SAndroid Build Coastguard Worker RINOK(Seek2(_h.Size))
1741*f6dc9357SAndroid Build Coastguard Worker UInt32 rem = (UInt32)(0 - _h.Size) & (alignSize - 1);
1742*f6dc9357SAndroid Build Coastguard Worker _sizeCalculated = _h.Size;
1743*f6dc9357SAndroid Build Coastguard Worker if (rem != 0)
1744*f6dc9357SAndroid Build Coastguard Worker {
1745*f6dc9357SAndroid Build Coastguard Worker if (ReadStream_FALSE(_stream, buf, rem) == S_OK)
1746*f6dc9357SAndroid Build Coastguard Worker {
1747*f6dc9357SAndroid Build Coastguard Worker size_t i;
1748*f6dc9357SAndroid Build Coastguard Worker for (i = 0; i < rem && buf[i] == 0; i++);
1749*f6dc9357SAndroid Build Coastguard Worker if (i == rem)
1750*f6dc9357SAndroid Build Coastguard Worker _sizeCalculated = _h.Size + rem;
1751*f6dc9357SAndroid Build Coastguard Worker }
1752*f6dc9357SAndroid Build Coastguard Worker }
1753*f6dc9357SAndroid Build Coastguard Worker }
1754*f6dc9357SAndroid Build Coastguard Worker return S_OK;
1755*f6dc9357SAndroid Build Coastguard Worker }
1756*f6dc9357SAndroid Build Coastguard Worker
1757*f6dc9357SAndroid Build Coastguard Worker AString CHandler::GetPath(unsigned index) const
1758*f6dc9357SAndroid Build Coastguard Worker {
1759*f6dc9357SAndroid Build Coastguard Worker unsigned len = 0;
1760*f6dc9357SAndroid Build Coastguard Worker const unsigned indexMem = index;
1761*f6dc9357SAndroid Build Coastguard Worker const bool be = _h.be;
1762*f6dc9357SAndroid Build Coastguard Worker for (;;)
1763*f6dc9357SAndroid Build Coastguard Worker {
1764*f6dc9357SAndroid Build Coastguard Worker const CItem &item = _items[index];
1765*f6dc9357SAndroid Build Coastguard Worker const Byte *p = _dirs.Data + item.Ptr;
1766*f6dc9357SAndroid Build Coastguard Worker const unsigned size = (_h.IsOldVersion() ? (unsigned)p[2] : (unsigned)Get16(p + 6)) + 1;
1767*f6dc9357SAndroid Build Coastguard Worker p += _h.GetFileNameOffset();
1768*f6dc9357SAndroid Build Coastguard Worker unsigned i;
1769*f6dc9357SAndroid Build Coastguard Worker for (i = 0; i < size && p[i]; i++);
1770*f6dc9357SAndroid Build Coastguard Worker len += i + 1;
1771*f6dc9357SAndroid Build Coastguard Worker index = (unsigned)item.Parent;
1772*f6dc9357SAndroid Build Coastguard Worker if (item.Parent < 0)
1773*f6dc9357SAndroid Build Coastguard Worker break;
1774*f6dc9357SAndroid Build Coastguard Worker }
1775*f6dc9357SAndroid Build Coastguard Worker len--;
1776*f6dc9357SAndroid Build Coastguard Worker
1777*f6dc9357SAndroid Build Coastguard Worker AString path;
1778*f6dc9357SAndroid Build Coastguard Worker char *dest = path.GetBuf_SetEnd(len) + len;
1779*f6dc9357SAndroid Build Coastguard Worker index = indexMem;
1780*f6dc9357SAndroid Build Coastguard Worker for (;;)
1781*f6dc9357SAndroid Build Coastguard Worker {
1782*f6dc9357SAndroid Build Coastguard Worker const CItem &item = _items[index];
1783*f6dc9357SAndroid Build Coastguard Worker const Byte *p = _dirs.Data + item.Ptr;
1784*f6dc9357SAndroid Build Coastguard Worker const unsigned size = (_h.IsOldVersion() ? (unsigned)p[2] : (unsigned)Get16(p + 6)) + 1;
1785*f6dc9357SAndroid Build Coastguard Worker p += _h.GetFileNameOffset();
1786*f6dc9357SAndroid Build Coastguard Worker unsigned i;
1787*f6dc9357SAndroid Build Coastguard Worker for (i = 0; i < size && p[i]; i++);
1788*f6dc9357SAndroid Build Coastguard Worker dest -= i;
1789*f6dc9357SAndroid Build Coastguard Worker memcpy(dest, p, i);
1790*f6dc9357SAndroid Build Coastguard Worker index = (unsigned)item.Parent;
1791*f6dc9357SAndroid Build Coastguard Worker if (item.Parent < 0)
1792*f6dc9357SAndroid Build Coastguard Worker break;
1793*f6dc9357SAndroid Build Coastguard Worker *(--dest) = CHAR_PATH_SEPARATOR;
1794*f6dc9357SAndroid Build Coastguard Worker }
1795*f6dc9357SAndroid Build Coastguard Worker return path;
1796*f6dc9357SAndroid Build Coastguard Worker }
1797*f6dc9357SAndroid Build Coastguard Worker
1798*f6dc9357SAndroid Build Coastguard Worker Z7_COM7F_IMF(CHandler::Open(IInStream *stream, const UInt64 *, IArchiveOpenCallback *callback))
1799*f6dc9357SAndroid Build Coastguard Worker {
1800*f6dc9357SAndroid Build Coastguard Worker COM_TRY_BEGIN
1801*f6dc9357SAndroid Build Coastguard Worker {
1802*f6dc9357SAndroid Build Coastguard Worker Close();
1803*f6dc9357SAndroid Build Coastguard Worker _limitedInStream->SetStream(stream);
1804*f6dc9357SAndroid Build Coastguard Worker HRESULT res;
1805*f6dc9357SAndroid Build Coastguard Worker try
1806*f6dc9357SAndroid Build Coastguard Worker {
1807*f6dc9357SAndroid Build Coastguard Worker _openCallback = callback;
1808*f6dc9357SAndroid Build Coastguard Worker res = Open2(stream);
1809*f6dc9357SAndroid Build Coastguard Worker }
1810*f6dc9357SAndroid Build Coastguard Worker catch(...)
1811*f6dc9357SAndroid Build Coastguard Worker {
1812*f6dc9357SAndroid Build Coastguard Worker Close();
1813*f6dc9357SAndroid Build Coastguard Worker throw;
1814*f6dc9357SAndroid Build Coastguard Worker }
1815*f6dc9357SAndroid Build Coastguard Worker if (res != S_OK)
1816*f6dc9357SAndroid Build Coastguard Worker {
1817*f6dc9357SAndroid Build Coastguard Worker Close();
1818*f6dc9357SAndroid Build Coastguard Worker return res;
1819*f6dc9357SAndroid Build Coastguard Worker }
1820*f6dc9357SAndroid Build Coastguard Worker _stream = stream;
1821*f6dc9357SAndroid Build Coastguard Worker }
1822*f6dc9357SAndroid Build Coastguard Worker return S_OK;
1823*f6dc9357SAndroid Build Coastguard Worker COM_TRY_END
1824*f6dc9357SAndroid Build Coastguard Worker }
1825*f6dc9357SAndroid Build Coastguard Worker
1826*f6dc9357SAndroid Build Coastguard Worker Z7_COM7F_IMF(CHandler::Close())
1827*f6dc9357SAndroid Build Coastguard Worker {
1828*f6dc9357SAndroid Build Coastguard Worker _openCodePage = CP_UTF8;
1829*f6dc9357SAndroid Build Coastguard Worker _sizeCalculated = 0;
1830*f6dc9357SAndroid Build Coastguard Worker
1831*f6dc9357SAndroid Build Coastguard Worker _limitedInStream->ReleaseStream();
1832*f6dc9357SAndroid Build Coastguard Worker _stream.Release();
1833*f6dc9357SAndroid Build Coastguard Worker
1834*f6dc9357SAndroid Build Coastguard Worker _items.Clear();
1835*f6dc9357SAndroid Build Coastguard Worker _nodes.Clear();
1836*f6dc9357SAndroid Build Coastguard Worker _nodesPos.Clear();
1837*f6dc9357SAndroid Build Coastguard Worker _blockToNode.Clear();
1838*f6dc9357SAndroid Build Coastguard Worker _frags.Clear();
1839*f6dc9357SAndroid Build Coastguard Worker _inodesData.Clear();
1840*f6dc9357SAndroid Build Coastguard Worker _dirs.Clear();
1841*f6dc9357SAndroid Build Coastguard Worker
1842*f6dc9357SAndroid Build Coastguard Worker _uids.Free();
1843*f6dc9357SAndroid Build Coastguard Worker _gids.Free();
1844*f6dc9357SAndroid Build Coastguard Worker
1845*f6dc9357SAndroid Build Coastguard Worker _cachedBlock.Free();
1846*f6dc9357SAndroid Build Coastguard Worker ClearCache();
1847*f6dc9357SAndroid Build Coastguard Worker
1848*f6dc9357SAndroid Build Coastguard Worker return S_OK;
1849*f6dc9357SAndroid Build Coastguard Worker }
1850*f6dc9357SAndroid Build Coastguard Worker
1851*f6dc9357SAndroid Build Coastguard Worker bool CHandler::GetPackSize(unsigned index, UInt64 &totalPack, bool fillOffsets)
1852*f6dc9357SAndroid Build Coastguard Worker {
1853*f6dc9357SAndroid Build Coastguard Worker totalPack = 0;
1854*f6dc9357SAndroid Build Coastguard Worker const CItem &item = _items[index];
1855*f6dc9357SAndroid Build Coastguard Worker const CNode &node = _nodes[item.Node];
1856*f6dc9357SAndroid Build Coastguard Worker const UInt32 ptr = _nodesPos[item.Node];
1857*f6dc9357SAndroid Build Coastguard Worker const Byte *p = _inodesData.Data + ptr;
1858*f6dc9357SAndroid Build Coastguard Worker const bool be = _h.be;
1859*f6dc9357SAndroid Build Coastguard Worker
1860*f6dc9357SAndroid Build Coastguard Worker const UInt32 type = node.Type;
1861*f6dc9357SAndroid Build Coastguard Worker UInt32 offset;
1862*f6dc9357SAndroid Build Coastguard Worker if (node.IsLink() || node.FileSize == 0)
1863*f6dc9357SAndroid Build Coastguard Worker {
1864*f6dc9357SAndroid Build Coastguard Worker totalPack = node.FileSize;
1865*f6dc9357SAndroid Build Coastguard Worker return true;
1866*f6dc9357SAndroid Build Coastguard Worker }
1867*f6dc9357SAndroid Build Coastguard Worker
1868*f6dc9357SAndroid Build Coastguard Worker const UInt32 numBlocks = (UInt32)node.GetNumBlocks(_h);
1869*f6dc9357SAndroid Build Coastguard Worker
1870*f6dc9357SAndroid Build Coastguard Worker if (fillOffsets)
1871*f6dc9357SAndroid Build Coastguard Worker {
1872*f6dc9357SAndroid Build Coastguard Worker _blockOffsets.Clear();
1873*f6dc9357SAndroid Build Coastguard Worker _blockCompressed.Clear();
1874*f6dc9357SAndroid Build Coastguard Worker _blockOffsets.Add(totalPack);
1875*f6dc9357SAndroid Build Coastguard Worker }
1876*f6dc9357SAndroid Build Coastguard Worker
1877*f6dc9357SAndroid Build Coastguard Worker if (_h.Major <= 1)
1878*f6dc9357SAndroid Build Coastguard Worker {
1879*f6dc9357SAndroid Build Coastguard Worker offset = 15;
1880*f6dc9357SAndroid Build Coastguard Worker p += offset;
1881*f6dc9357SAndroid Build Coastguard Worker
1882*f6dc9357SAndroid Build Coastguard Worker for (UInt32 i = 0; i < numBlocks; i++)
1883*f6dc9357SAndroid Build Coastguard Worker {
1884*f6dc9357SAndroid Build Coastguard Worker UInt32 t = Get16(p + i * 2);
1885*f6dc9357SAndroid Build Coastguard Worker if (fillOffsets)
1886*f6dc9357SAndroid Build Coastguard Worker _blockCompressed.Add((t & kNotCompressedBit16) == 0);
1887*f6dc9357SAndroid Build Coastguard Worker if (t != kNotCompressedBit16)
1888*f6dc9357SAndroid Build Coastguard Worker t &= ~kNotCompressedBit16;
1889*f6dc9357SAndroid Build Coastguard Worker totalPack += t;
1890*f6dc9357SAndroid Build Coastguard Worker if (fillOffsets)
1891*f6dc9357SAndroid Build Coastguard Worker _blockOffsets.Add(totalPack);
1892*f6dc9357SAndroid Build Coastguard Worker }
1893*f6dc9357SAndroid Build Coastguard Worker }
1894*f6dc9357SAndroid Build Coastguard Worker else
1895*f6dc9357SAndroid Build Coastguard Worker {
1896*f6dc9357SAndroid Build Coastguard Worker if (_h.Major <= 2)
1897*f6dc9357SAndroid Build Coastguard Worker offset = 24;
1898*f6dc9357SAndroid Build Coastguard Worker else if (type == kType_FILE)
1899*f6dc9357SAndroid Build Coastguard Worker offset = 32;
1900*f6dc9357SAndroid Build Coastguard Worker else if (type == kType_FILE + 7)
1901*f6dc9357SAndroid Build Coastguard Worker offset = (_h.Major <= 3 ? 40 : 56);
1902*f6dc9357SAndroid Build Coastguard Worker else
1903*f6dc9357SAndroid Build Coastguard Worker return false;
1904*f6dc9357SAndroid Build Coastguard Worker
1905*f6dc9357SAndroid Build Coastguard Worker p += offset;
1906*f6dc9357SAndroid Build Coastguard Worker
1907*f6dc9357SAndroid Build Coastguard Worker for (UInt64 i = 0; i < numBlocks; i++)
1908*f6dc9357SAndroid Build Coastguard Worker {
1909*f6dc9357SAndroid Build Coastguard Worker UInt32 t = Get32(p + i * 4);
1910*f6dc9357SAndroid Build Coastguard Worker if (fillOffsets)
1911*f6dc9357SAndroid Build Coastguard Worker _blockCompressed.Add(IS_COMPRESSED_BLOCK(t));
1912*f6dc9357SAndroid Build Coastguard Worker UInt32 size = GET_COMPRESSED_BLOCK_SIZE(t);
1913*f6dc9357SAndroid Build Coastguard Worker if (size > _h.BlockSize)
1914*f6dc9357SAndroid Build Coastguard Worker return false;
1915*f6dc9357SAndroid Build Coastguard Worker totalPack += size;
1916*f6dc9357SAndroid Build Coastguard Worker if (fillOffsets)
1917*f6dc9357SAndroid Build Coastguard Worker _blockOffsets.Add(totalPack);
1918*f6dc9357SAndroid Build Coastguard Worker }
1919*f6dc9357SAndroid Build Coastguard Worker
1920*f6dc9357SAndroid Build Coastguard Worker if (node.ThereAreFrags())
1921*f6dc9357SAndroid Build Coastguard Worker {
1922*f6dc9357SAndroid Build Coastguard Worker if (node.Frag >= (UInt32)_frags.Size())
1923*f6dc9357SAndroid Build Coastguard Worker return false;
1924*f6dc9357SAndroid Build Coastguard Worker const CFrag &frag = _frags[node.Frag];
1925*f6dc9357SAndroid Build Coastguard Worker if (node.Offset == 0)
1926*f6dc9357SAndroid Build Coastguard Worker {
1927*f6dc9357SAndroid Build Coastguard Worker UInt32 size = GET_COMPRESSED_BLOCK_SIZE(frag.Size);
1928*f6dc9357SAndroid Build Coastguard Worker if (size > _h.BlockSize)
1929*f6dc9357SAndroid Build Coastguard Worker return false;
1930*f6dc9357SAndroid Build Coastguard Worker totalPack += size;
1931*f6dc9357SAndroid Build Coastguard Worker }
1932*f6dc9357SAndroid Build Coastguard Worker }
1933*f6dc9357SAndroid Build Coastguard Worker }
1934*f6dc9357SAndroid Build Coastguard Worker return true;
1935*f6dc9357SAndroid Build Coastguard Worker }
1936*f6dc9357SAndroid Build Coastguard Worker
1937*f6dc9357SAndroid Build Coastguard Worker
1938*f6dc9357SAndroid Build Coastguard Worker Z7_COM7F_IMF(CHandler::GetNumberOfItems(UInt32 *numItems))
1939*f6dc9357SAndroid Build Coastguard Worker {
1940*f6dc9357SAndroid Build Coastguard Worker *numItems = _items.Size();
1941*f6dc9357SAndroid Build Coastguard Worker return S_OK;
1942*f6dc9357SAndroid Build Coastguard Worker }
1943*f6dc9357SAndroid Build Coastguard Worker
1944*f6dc9357SAndroid Build Coastguard Worker Z7_COM7F_IMF(CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value))
1945*f6dc9357SAndroid Build Coastguard Worker {
1946*f6dc9357SAndroid Build Coastguard Worker COM_TRY_BEGIN
1947*f6dc9357SAndroid Build Coastguard Worker NWindows::NCOM::CPropVariant prop;
1948*f6dc9357SAndroid Build Coastguard Worker switch (propID)
1949*f6dc9357SAndroid Build Coastguard Worker {
1950*f6dc9357SAndroid Build Coastguard Worker case kpidMethod:
1951*f6dc9357SAndroid Build Coastguard Worker {
1952*f6dc9357SAndroid Build Coastguard Worker char sz[16];
1953*f6dc9357SAndroid Build Coastguard Worker const char *s;
1954*f6dc9357SAndroid Build Coastguard Worker if (_noPropsLZMA)
1955*f6dc9357SAndroid Build Coastguard Worker s = "LZMA Spec";
1956*f6dc9357SAndroid Build Coastguard Worker else if (_h.SeveralMethods)
1957*f6dc9357SAndroid Build Coastguard Worker s = "LZMA ZLIB";
1958*f6dc9357SAndroid Build Coastguard Worker else
1959*f6dc9357SAndroid Build Coastguard Worker {
1960*f6dc9357SAndroid Build Coastguard Worker s = NULL;
1961*f6dc9357SAndroid Build Coastguard Worker if (_h.Method < Z7_ARRAY_SIZE(k_Methods))
1962*f6dc9357SAndroid Build Coastguard Worker s = k_Methods[_h.Method];
1963*f6dc9357SAndroid Build Coastguard Worker if (!s)
1964*f6dc9357SAndroid Build Coastguard Worker {
1965*f6dc9357SAndroid Build Coastguard Worker ConvertUInt32ToString(_h.Method, sz);
1966*f6dc9357SAndroid Build Coastguard Worker s = sz;
1967*f6dc9357SAndroid Build Coastguard Worker }
1968*f6dc9357SAndroid Build Coastguard Worker }
1969*f6dc9357SAndroid Build Coastguard Worker prop = s;
1970*f6dc9357SAndroid Build Coastguard Worker break;
1971*f6dc9357SAndroid Build Coastguard Worker }
1972*f6dc9357SAndroid Build Coastguard Worker case kpidFileSystem:
1973*f6dc9357SAndroid Build Coastguard Worker {
1974*f6dc9357SAndroid Build Coastguard Worker AString res ("SquashFS");
1975*f6dc9357SAndroid Build Coastguard Worker if (_h.SeveralMethods)
1976*f6dc9357SAndroid Build Coastguard Worker res += "-LZMA";
1977*f6dc9357SAndroid Build Coastguard Worker res.Add_Space();
1978*f6dc9357SAndroid Build Coastguard Worker res.Add_UInt32(_h.Major);
1979*f6dc9357SAndroid Build Coastguard Worker res.Add_Dot();
1980*f6dc9357SAndroid Build Coastguard Worker res.Add_UInt32(_h.Minor);
1981*f6dc9357SAndroid Build Coastguard Worker prop = res;
1982*f6dc9357SAndroid Build Coastguard Worker break;
1983*f6dc9357SAndroid Build Coastguard Worker }
1984*f6dc9357SAndroid Build Coastguard Worker case kpidClusterSize: prop = _h.BlockSize; break;
1985*f6dc9357SAndroid Build Coastguard Worker case kpidBigEndian: prop = _h.be; break;
1986*f6dc9357SAndroid Build Coastguard Worker case kpidCTime:
1987*f6dc9357SAndroid Build Coastguard Worker if (_h.CTime != 0)
1988*f6dc9357SAndroid Build Coastguard Worker PropVariant_SetFrom_UnixTime(prop, _h.CTime);
1989*f6dc9357SAndroid Build Coastguard Worker break;
1990*f6dc9357SAndroid Build Coastguard Worker case kpidCharacts: FLAGS_TO_PROP(k_Flags, _h.Flags, prop); break;
1991*f6dc9357SAndroid Build Coastguard Worker // case kpidNumBlocks: prop = _h.NumFrags; break;
1992*f6dc9357SAndroid Build Coastguard Worker case kpidPhySize: prop = _sizeCalculated; break;
1993*f6dc9357SAndroid Build Coastguard Worker case kpidHeadersSize:
1994*f6dc9357SAndroid Build Coastguard Worker if (_sizeCalculated >= _h.InodeTable)
1995*f6dc9357SAndroid Build Coastguard Worker prop = _sizeCalculated - _h.InodeTable;
1996*f6dc9357SAndroid Build Coastguard Worker break;
1997*f6dc9357SAndroid Build Coastguard Worker
1998*f6dc9357SAndroid Build Coastguard Worker case kpidCodePage:
1999*f6dc9357SAndroid Build Coastguard Worker {
2000*f6dc9357SAndroid Build Coastguard Worker char sz[16];
2001*f6dc9357SAndroid Build Coastguard Worker const char *name = NULL;
2002*f6dc9357SAndroid Build Coastguard Worker switch (_openCodePage)
2003*f6dc9357SAndroid Build Coastguard Worker {
2004*f6dc9357SAndroid Build Coastguard Worker case CP_OEMCP: name = "OEM"; break;
2005*f6dc9357SAndroid Build Coastguard Worker case CP_UTF8: name = "UTF-8"; break;
2006*f6dc9357SAndroid Build Coastguard Worker }
2007*f6dc9357SAndroid Build Coastguard Worker if (!name)
2008*f6dc9357SAndroid Build Coastguard Worker {
2009*f6dc9357SAndroid Build Coastguard Worker ConvertUInt32ToString(_openCodePage, sz);
2010*f6dc9357SAndroid Build Coastguard Worker name = sz;
2011*f6dc9357SAndroid Build Coastguard Worker }
2012*f6dc9357SAndroid Build Coastguard Worker prop = name;
2013*f6dc9357SAndroid Build Coastguard Worker break;
2014*f6dc9357SAndroid Build Coastguard Worker }
2015*f6dc9357SAndroid Build Coastguard Worker }
2016*f6dc9357SAndroid Build Coastguard Worker prop.Detach(value);
2017*f6dc9357SAndroid Build Coastguard Worker return S_OK;
2018*f6dc9357SAndroid Build Coastguard Worker COM_TRY_END
2019*f6dc9357SAndroid Build Coastguard Worker }
2020*f6dc9357SAndroid Build Coastguard Worker
2021*f6dc9357SAndroid Build Coastguard Worker Z7_COM7F_IMF(CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *value))
2022*f6dc9357SAndroid Build Coastguard Worker {
2023*f6dc9357SAndroid Build Coastguard Worker COM_TRY_BEGIN
2024*f6dc9357SAndroid Build Coastguard Worker NWindows::NCOM::CPropVariant prop;
2025*f6dc9357SAndroid Build Coastguard Worker const CItem &item = _items[index];
2026*f6dc9357SAndroid Build Coastguard Worker const CNode &node = _nodes[item.Node];
2027*f6dc9357SAndroid Build Coastguard Worker const bool isDir = node.IsDir();
2028*f6dc9357SAndroid Build Coastguard Worker const bool be = _h.be;
2029*f6dc9357SAndroid Build Coastguard Worker
2030*f6dc9357SAndroid Build Coastguard Worker switch (propID)
2031*f6dc9357SAndroid Build Coastguard Worker {
2032*f6dc9357SAndroid Build Coastguard Worker case kpidPath:
2033*f6dc9357SAndroid Build Coastguard Worker {
2034*f6dc9357SAndroid Build Coastguard Worker AString path (GetPath(index));
2035*f6dc9357SAndroid Build Coastguard Worker UString s;
2036*f6dc9357SAndroid Build Coastguard Worker if (_openCodePage == CP_UTF8)
2037*f6dc9357SAndroid Build Coastguard Worker ConvertUTF8ToUnicode(path, s);
2038*f6dc9357SAndroid Build Coastguard Worker else
2039*f6dc9357SAndroid Build Coastguard Worker MultiByteToUnicodeString2(s, path, _openCodePage);
2040*f6dc9357SAndroid Build Coastguard Worker prop = s;
2041*f6dc9357SAndroid Build Coastguard Worker break;
2042*f6dc9357SAndroid Build Coastguard Worker }
2043*f6dc9357SAndroid Build Coastguard Worker case kpidIsDir: prop = isDir; break;
2044*f6dc9357SAndroid Build Coastguard Worker // case kpidOffset: if (!node.IsLink()) prop = (UInt64)node.StartBlock; break;
2045*f6dc9357SAndroid Build Coastguard Worker case kpidSize: if (!isDir) prop = node.GetSize(); break;
2046*f6dc9357SAndroid Build Coastguard Worker case kpidPackSize:
2047*f6dc9357SAndroid Build Coastguard Worker if (!isDir)
2048*f6dc9357SAndroid Build Coastguard Worker {
2049*f6dc9357SAndroid Build Coastguard Worker UInt64 size;
2050*f6dc9357SAndroid Build Coastguard Worker if (GetPackSize(index, size, false))
2051*f6dc9357SAndroid Build Coastguard Worker prop = size;
2052*f6dc9357SAndroid Build Coastguard Worker }
2053*f6dc9357SAndroid Build Coastguard Worker break;
2054*f6dc9357SAndroid Build Coastguard Worker case kpidMTime:
2055*f6dc9357SAndroid Build Coastguard Worker {
2056*f6dc9357SAndroid Build Coastguard Worker UInt32 offset = 0;
2057*f6dc9357SAndroid Build Coastguard Worker switch (_h.Major)
2058*f6dc9357SAndroid Build Coastguard Worker {
2059*f6dc9357SAndroid Build Coastguard Worker case 1:
2060*f6dc9357SAndroid Build Coastguard Worker if (node.Type == kType_FILE)
2061*f6dc9357SAndroid Build Coastguard Worker offset = 3;
2062*f6dc9357SAndroid Build Coastguard Worker else if (node.Type == kType_DIR)
2063*f6dc9357SAndroid Build Coastguard Worker offset = 7;
2064*f6dc9357SAndroid Build Coastguard Worker break;
2065*f6dc9357SAndroid Build Coastguard Worker case 2:
2066*f6dc9357SAndroid Build Coastguard Worker if (node.Type == kType_FILE)
2067*f6dc9357SAndroid Build Coastguard Worker offset = 4;
2068*f6dc9357SAndroid Build Coastguard Worker else if (node.Type == kType_DIR)
2069*f6dc9357SAndroid Build Coastguard Worker offset = 8;
2070*f6dc9357SAndroid Build Coastguard Worker else if (node.Type == kType_DIR + 7)
2071*f6dc9357SAndroid Build Coastguard Worker offset = 9;
2072*f6dc9357SAndroid Build Coastguard Worker break;
2073*f6dc9357SAndroid Build Coastguard Worker case 3: offset = 4; break;
2074*f6dc9357SAndroid Build Coastguard Worker case 4: offset = 8; break;
2075*f6dc9357SAndroid Build Coastguard Worker }
2076*f6dc9357SAndroid Build Coastguard Worker if (offset != 0)
2077*f6dc9357SAndroid Build Coastguard Worker {
2078*f6dc9357SAndroid Build Coastguard Worker const Byte *p = _inodesData.Data + _nodesPos[item.Node] + offset;
2079*f6dc9357SAndroid Build Coastguard Worker PropVariant_SetFrom_UnixTime(prop, Get32(p));
2080*f6dc9357SAndroid Build Coastguard Worker }
2081*f6dc9357SAndroid Build Coastguard Worker break;
2082*f6dc9357SAndroid Build Coastguard Worker }
2083*f6dc9357SAndroid Build Coastguard Worker case kpidPosixAttrib:
2084*f6dc9357SAndroid Build Coastguard Worker {
2085*f6dc9357SAndroid Build Coastguard Worker if (node.Type != 0 && node.Type < Z7_ARRAY_SIZE(k_TypeToMode))
2086*f6dc9357SAndroid Build Coastguard Worker prop = (UInt32)(node.Mode & 0xFFF) | k_TypeToMode[node.Type];
2087*f6dc9357SAndroid Build Coastguard Worker break;
2088*f6dc9357SAndroid Build Coastguard Worker }
2089*f6dc9357SAndroid Build Coastguard Worker case kpidUserId:
2090*f6dc9357SAndroid Build Coastguard Worker case kpidGroupId:
2091*f6dc9357SAndroid Build Coastguard Worker {
2092*f6dc9357SAndroid Build Coastguard Worker UInt32 id = node.Uid;
2093*f6dc9357SAndroid Build Coastguard Worker const CByteBuffer *ids = &_uids;
2094*f6dc9357SAndroid Build Coastguard Worker if (propID == kpidGroupId)
2095*f6dc9357SAndroid Build Coastguard Worker {
2096*f6dc9357SAndroid Build Coastguard Worker id = node.Gid;
2097*f6dc9357SAndroid Build Coastguard Worker if (_h.Major < 4)
2098*f6dc9357SAndroid Build Coastguard Worker {
2099*f6dc9357SAndroid Build Coastguard Worker if (id == _h.GetSpecGuidIndex())
2100*f6dc9357SAndroid Build Coastguard Worker id = node.Uid;
2101*f6dc9357SAndroid Build Coastguard Worker else
2102*f6dc9357SAndroid Build Coastguard Worker ids = &_gids;
2103*f6dc9357SAndroid Build Coastguard Worker }
2104*f6dc9357SAndroid Build Coastguard Worker }
2105*f6dc9357SAndroid Build Coastguard Worker const UInt32 offset = (UInt32)id * 4;
2106*f6dc9357SAndroid Build Coastguard Worker if (offset < ids->Size())
2107*f6dc9357SAndroid Build Coastguard Worker prop = (UInt32)Get32(*ids + offset);
2108*f6dc9357SAndroid Build Coastguard Worker break;
2109*f6dc9357SAndroid Build Coastguard Worker }
2110*f6dc9357SAndroid Build Coastguard Worker /*
2111*f6dc9357SAndroid Build Coastguard Worker case kpidLinks:
2112*f6dc9357SAndroid Build Coastguard Worker if (_h.Major >= 3 && node.Type != kType_FILE)
2113*f6dc9357SAndroid Build Coastguard Worker prop = node.NumLinks;
2114*f6dc9357SAndroid Build Coastguard Worker break;
2115*f6dc9357SAndroid Build Coastguard Worker */
2116*f6dc9357SAndroid Build Coastguard Worker }
2117*f6dc9357SAndroid Build Coastguard Worker prop.Detach(value);
2118*f6dc9357SAndroid Build Coastguard Worker return S_OK;
2119*f6dc9357SAndroid Build Coastguard Worker COM_TRY_END
2120*f6dc9357SAndroid Build Coastguard Worker }
2121*f6dc9357SAndroid Build Coastguard Worker
2122*f6dc9357SAndroid Build Coastguard Worker class CSquashfsInStream: public CCachedInStream
2123*f6dc9357SAndroid Build Coastguard Worker {
2124*f6dc9357SAndroid Build Coastguard Worker HRESULT ReadBlock(UInt64 blockIndex, Byte *dest, size_t blockSize) Z7_override;
2125*f6dc9357SAndroid Build Coastguard Worker public:
2126*f6dc9357SAndroid Build Coastguard Worker CHandler *Handler;
2127*f6dc9357SAndroid Build Coastguard Worker };
2128*f6dc9357SAndroid Build Coastguard Worker
2129*f6dc9357SAndroid Build Coastguard Worker HRESULT CSquashfsInStream::ReadBlock(UInt64 blockIndex, Byte *dest, size_t blockSize)
2130*f6dc9357SAndroid Build Coastguard Worker {
2131*f6dc9357SAndroid Build Coastguard Worker return Handler->ReadBlock(blockIndex, dest, blockSize);
2132*f6dc9357SAndroid Build Coastguard Worker }
2133*f6dc9357SAndroid Build Coastguard Worker
2134*f6dc9357SAndroid Build Coastguard Worker HRESULT CHandler::ReadBlock(UInt64 blockIndex, Byte *dest, size_t blockSize)
2135*f6dc9357SAndroid Build Coastguard Worker {
2136*f6dc9357SAndroid Build Coastguard Worker const CNode &node = _nodes[_nodeIndex];
2137*f6dc9357SAndroid Build Coastguard Worker UInt64 blockOffset;
2138*f6dc9357SAndroid Build Coastguard Worker UInt32 packBlockSize;
2139*f6dc9357SAndroid Build Coastguard Worker UInt32 offsetInBlock = 0;
2140*f6dc9357SAndroid Build Coastguard Worker bool compressed;
2141*f6dc9357SAndroid Build Coastguard Worker if (blockIndex < _blockCompressed.Size())
2142*f6dc9357SAndroid Build Coastguard Worker {
2143*f6dc9357SAndroid Build Coastguard Worker compressed = _blockCompressed[(unsigned)blockIndex];
2144*f6dc9357SAndroid Build Coastguard Worker blockOffset = _blockOffsets[(unsigned)blockIndex];
2145*f6dc9357SAndroid Build Coastguard Worker packBlockSize = (UInt32)(_blockOffsets[(unsigned)blockIndex + 1] - blockOffset);
2146*f6dc9357SAndroid Build Coastguard Worker blockOffset += node.StartBlock;
2147*f6dc9357SAndroid Build Coastguard Worker }
2148*f6dc9357SAndroid Build Coastguard Worker else
2149*f6dc9357SAndroid Build Coastguard Worker {
2150*f6dc9357SAndroid Build Coastguard Worker if (!node.ThereAreFrags())
2151*f6dc9357SAndroid Build Coastguard Worker return S_FALSE;
2152*f6dc9357SAndroid Build Coastguard Worker const CFrag &frag = _frags[node.Frag];
2153*f6dc9357SAndroid Build Coastguard Worker offsetInBlock = node.Offset;
2154*f6dc9357SAndroid Build Coastguard Worker blockOffset = frag.StartBlock;
2155*f6dc9357SAndroid Build Coastguard Worker packBlockSize = GET_COMPRESSED_BLOCK_SIZE(frag.Size);
2156*f6dc9357SAndroid Build Coastguard Worker compressed = IS_COMPRESSED_BLOCK(frag.Size);
2157*f6dc9357SAndroid Build Coastguard Worker }
2158*f6dc9357SAndroid Build Coastguard Worker
2159*f6dc9357SAndroid Build Coastguard Worker if (packBlockSize == 0)
2160*f6dc9357SAndroid Build Coastguard Worker {
2161*f6dc9357SAndroid Build Coastguard Worker // sparse file ???
2162*f6dc9357SAndroid Build Coastguard Worker memset(dest, 0, blockSize);
2163*f6dc9357SAndroid Build Coastguard Worker return S_OK;
2164*f6dc9357SAndroid Build Coastguard Worker }
2165*f6dc9357SAndroid Build Coastguard Worker
2166*f6dc9357SAndroid Build Coastguard Worker if (blockOffset != _cachedBlockStartPos ||
2167*f6dc9357SAndroid Build Coastguard Worker packBlockSize != _cachedPackBlockSize)
2168*f6dc9357SAndroid Build Coastguard Worker {
2169*f6dc9357SAndroid Build Coastguard Worker ClearCache();
2170*f6dc9357SAndroid Build Coastguard Worker RINOK(Seek2(blockOffset))
2171*f6dc9357SAndroid Build Coastguard Worker _limitedInStream->Init(packBlockSize);
2172*f6dc9357SAndroid Build Coastguard Worker
2173*f6dc9357SAndroid Build Coastguard Worker if (compressed)
2174*f6dc9357SAndroid Build Coastguard Worker {
2175*f6dc9357SAndroid Build Coastguard Worker _outStream->Init((Byte *)_cachedBlock, _h.BlockSize);
2176*f6dc9357SAndroid Build Coastguard Worker bool outBufWasWritten;
2177*f6dc9357SAndroid Build Coastguard Worker UInt32 outBufWasWrittenSize;
2178*f6dc9357SAndroid Build Coastguard Worker HRESULT res = Decompress(_outStream, _cachedBlock, &outBufWasWritten, &outBufWasWrittenSize, packBlockSize, _h.BlockSize);
2179*f6dc9357SAndroid Build Coastguard Worker RINOK(res)
2180*f6dc9357SAndroid Build Coastguard Worker if (outBufWasWritten)
2181*f6dc9357SAndroid Build Coastguard Worker _cachedUnpackBlockSize = outBufWasWrittenSize;
2182*f6dc9357SAndroid Build Coastguard Worker else
2183*f6dc9357SAndroid Build Coastguard Worker _cachedUnpackBlockSize = (UInt32)_outStream->GetPos();
2184*f6dc9357SAndroid Build Coastguard Worker }
2185*f6dc9357SAndroid Build Coastguard Worker else
2186*f6dc9357SAndroid Build Coastguard Worker {
2187*f6dc9357SAndroid Build Coastguard Worker if (packBlockSize > _h.BlockSize)
2188*f6dc9357SAndroid Build Coastguard Worker return S_FALSE;
2189*f6dc9357SAndroid Build Coastguard Worker RINOK(ReadStream_FALSE(_limitedInStream, _cachedBlock, packBlockSize))
2190*f6dc9357SAndroid Build Coastguard Worker _cachedUnpackBlockSize = packBlockSize;
2191*f6dc9357SAndroid Build Coastguard Worker }
2192*f6dc9357SAndroid Build Coastguard Worker _cachedBlockStartPos = blockOffset;
2193*f6dc9357SAndroid Build Coastguard Worker _cachedPackBlockSize = packBlockSize;
2194*f6dc9357SAndroid Build Coastguard Worker }
2195*f6dc9357SAndroid Build Coastguard Worker if (offsetInBlock + blockSize > _cachedUnpackBlockSize)
2196*f6dc9357SAndroid Build Coastguard Worker return S_FALSE;
2197*f6dc9357SAndroid Build Coastguard Worker if (blockSize != 0)
2198*f6dc9357SAndroid Build Coastguard Worker memcpy(dest, _cachedBlock + offsetInBlock, blockSize);
2199*f6dc9357SAndroid Build Coastguard Worker return S_OK;
2200*f6dc9357SAndroid Build Coastguard Worker }
2201*f6dc9357SAndroid Build Coastguard Worker
2202*f6dc9357SAndroid Build Coastguard Worker Z7_COM7F_IMF(CHandler::Extract(const UInt32 *indices, UInt32 numItems,
2203*f6dc9357SAndroid Build Coastguard Worker Int32 testMode, IArchiveExtractCallback *extractCallback))
2204*f6dc9357SAndroid Build Coastguard Worker {
2205*f6dc9357SAndroid Build Coastguard Worker COM_TRY_BEGIN
2206*f6dc9357SAndroid Build Coastguard Worker const bool allFilesMode = (numItems == (UInt32)(Int32)-1);
2207*f6dc9357SAndroid Build Coastguard Worker if (allFilesMode)
2208*f6dc9357SAndroid Build Coastguard Worker numItems = _items.Size();
2209*f6dc9357SAndroid Build Coastguard Worker if (numItems == 0)
2210*f6dc9357SAndroid Build Coastguard Worker return S_OK;
2211*f6dc9357SAndroid Build Coastguard Worker UInt64 totalSize = 0;
2212*f6dc9357SAndroid Build Coastguard Worker UInt32 i;
2213*f6dc9357SAndroid Build Coastguard Worker for (i = 0; i < numItems; i++)
2214*f6dc9357SAndroid Build Coastguard Worker {
2215*f6dc9357SAndroid Build Coastguard Worker const CItem &item = _items[allFilesMode ? i : indices[i]];
2216*f6dc9357SAndroid Build Coastguard Worker const CNode &node = _nodes[item.Node];
2217*f6dc9357SAndroid Build Coastguard Worker totalSize += node.GetSize();
2218*f6dc9357SAndroid Build Coastguard Worker }
2219*f6dc9357SAndroid Build Coastguard Worker RINOK(extractCallback->SetTotal(totalSize))
2220*f6dc9357SAndroid Build Coastguard Worker
2221*f6dc9357SAndroid Build Coastguard Worker UInt64 totalPackSize;
2222*f6dc9357SAndroid Build Coastguard Worker totalSize = totalPackSize = 0;
2223*f6dc9357SAndroid Build Coastguard Worker
2224*f6dc9357SAndroid Build Coastguard Worker CMyComPtr2_Create<ICompressProgressInfo, CLocalProgress> lps;
2225*f6dc9357SAndroid Build Coastguard Worker lps->Init(extractCallback, false);
2226*f6dc9357SAndroid Build Coastguard Worker CMyComPtr2_Create<ICompressCoder, NCompress::CCopyCoder> copyCoder;
2227*f6dc9357SAndroid Build Coastguard Worker
2228*f6dc9357SAndroid Build Coastguard Worker for (i = 0;; i++)
2229*f6dc9357SAndroid Build Coastguard Worker {
2230*f6dc9357SAndroid Build Coastguard Worker lps->InSize = totalPackSize;
2231*f6dc9357SAndroid Build Coastguard Worker lps->OutSize = totalSize;
2232*f6dc9357SAndroid Build Coastguard Worker RINOK(lps->SetCur())
2233*f6dc9357SAndroid Build Coastguard Worker if (i >= numItems)
2234*f6dc9357SAndroid Build Coastguard Worker break;
2235*f6dc9357SAndroid Build Coastguard Worker
2236*f6dc9357SAndroid Build Coastguard Worker int res;
2237*f6dc9357SAndroid Build Coastguard Worker {
2238*f6dc9357SAndroid Build Coastguard Worker CMyComPtr<ISequentialOutStream> outStream;
2239*f6dc9357SAndroid Build Coastguard Worker const Int32 askMode = testMode ?
2240*f6dc9357SAndroid Build Coastguard Worker NExtract::NAskMode::kTest :
2241*f6dc9357SAndroid Build Coastguard Worker NExtract::NAskMode::kExtract;
2242*f6dc9357SAndroid Build Coastguard Worker const UInt32 index = allFilesMode ? i : indices[i];
2243*f6dc9357SAndroid Build Coastguard Worker const CItem &item = _items[index];
2244*f6dc9357SAndroid Build Coastguard Worker const CNode &node = _nodes[item.Node];
2245*f6dc9357SAndroid Build Coastguard Worker RINOK(extractCallback->GetStream(index, &outStream, askMode))
2246*f6dc9357SAndroid Build Coastguard Worker // const Byte *p = _data + item.Offset;
2247*f6dc9357SAndroid Build Coastguard Worker
2248*f6dc9357SAndroid Build Coastguard Worker if (node.IsDir())
2249*f6dc9357SAndroid Build Coastguard Worker {
2250*f6dc9357SAndroid Build Coastguard Worker RINOK(extractCallback->PrepareOperation(askMode))
2251*f6dc9357SAndroid Build Coastguard Worker RINOK(extractCallback->SetOperationResult(NExtract::NOperationResult::kOK))
2252*f6dc9357SAndroid Build Coastguard Worker continue;
2253*f6dc9357SAndroid Build Coastguard Worker }
2254*f6dc9357SAndroid Build Coastguard Worker const UInt64 unpackSize = node.GetSize();
2255*f6dc9357SAndroid Build Coastguard Worker totalSize += unpackSize;
2256*f6dc9357SAndroid Build Coastguard Worker UInt64 packSize;
2257*f6dc9357SAndroid Build Coastguard Worker if (GetPackSize(index, packSize, false))
2258*f6dc9357SAndroid Build Coastguard Worker totalPackSize += packSize;
2259*f6dc9357SAndroid Build Coastguard Worker
2260*f6dc9357SAndroid Build Coastguard Worker if (!testMode && !outStream)
2261*f6dc9357SAndroid Build Coastguard Worker continue;
2262*f6dc9357SAndroid Build Coastguard Worker RINOK(extractCallback->PrepareOperation(askMode))
2263*f6dc9357SAndroid Build Coastguard Worker
2264*f6dc9357SAndroid Build Coastguard Worker res = NExtract::NOperationResult::kDataError;
2265*f6dc9357SAndroid Build Coastguard Worker {
2266*f6dc9357SAndroid Build Coastguard Worker CMyComPtr<ISequentialInStream> inSeqStream;
2267*f6dc9357SAndroid Build Coastguard Worker HRESULT hres = GetStream(index, &inSeqStream);
2268*f6dc9357SAndroid Build Coastguard Worker if (hres == S_FALSE || !inSeqStream)
2269*f6dc9357SAndroid Build Coastguard Worker {
2270*f6dc9357SAndroid Build Coastguard Worker if (hres == E_OUTOFMEMORY)
2271*f6dc9357SAndroid Build Coastguard Worker return hres;
2272*f6dc9357SAndroid Build Coastguard Worker res = NExtract::NOperationResult::kUnsupportedMethod;
2273*f6dc9357SAndroid Build Coastguard Worker }
2274*f6dc9357SAndroid Build Coastguard Worker else
2275*f6dc9357SAndroid Build Coastguard Worker {
2276*f6dc9357SAndroid Build Coastguard Worker RINOK(hres)
2277*f6dc9357SAndroid Build Coastguard Worker {
2278*f6dc9357SAndroid Build Coastguard Worker hres = copyCoder.Interface()->Code(inSeqStream, outStream, NULL, NULL, lps);
2279*f6dc9357SAndroid Build Coastguard Worker if (hres == S_OK)
2280*f6dc9357SAndroid Build Coastguard Worker {
2281*f6dc9357SAndroid Build Coastguard Worker if (copyCoder->TotalSize == unpackSize)
2282*f6dc9357SAndroid Build Coastguard Worker res = NExtract::NOperationResult::kOK;
2283*f6dc9357SAndroid Build Coastguard Worker }
2284*f6dc9357SAndroid Build Coastguard Worker else if (hres == E_NOTIMPL)
2285*f6dc9357SAndroid Build Coastguard Worker {
2286*f6dc9357SAndroid Build Coastguard Worker res = NExtract::NOperationResult::kUnsupportedMethod;
2287*f6dc9357SAndroid Build Coastguard Worker }
2288*f6dc9357SAndroid Build Coastguard Worker else if (hres != S_FALSE)
2289*f6dc9357SAndroid Build Coastguard Worker {
2290*f6dc9357SAndroid Build Coastguard Worker RINOK(hres)
2291*f6dc9357SAndroid Build Coastguard Worker }
2292*f6dc9357SAndroid Build Coastguard Worker }
2293*f6dc9357SAndroid Build Coastguard Worker }
2294*f6dc9357SAndroid Build Coastguard Worker }
2295*f6dc9357SAndroid Build Coastguard Worker }
2296*f6dc9357SAndroid Build Coastguard Worker RINOK(extractCallback->SetOperationResult(res))
2297*f6dc9357SAndroid Build Coastguard Worker }
2298*f6dc9357SAndroid Build Coastguard Worker
2299*f6dc9357SAndroid Build Coastguard Worker return S_OK;
2300*f6dc9357SAndroid Build Coastguard Worker COM_TRY_END
2301*f6dc9357SAndroid Build Coastguard Worker }
2302*f6dc9357SAndroid Build Coastguard Worker
2303*f6dc9357SAndroid Build Coastguard Worker
2304*f6dc9357SAndroid Build Coastguard Worker Z7_COM7F_IMF(CHandler::GetStream(UInt32 index, ISequentialInStream **stream))
2305*f6dc9357SAndroid Build Coastguard Worker {
2306*f6dc9357SAndroid Build Coastguard Worker COM_TRY_BEGIN
2307*f6dc9357SAndroid Build Coastguard Worker
2308*f6dc9357SAndroid Build Coastguard Worker const CItem &item = _items[index];
2309*f6dc9357SAndroid Build Coastguard Worker const CNode &node = _nodes[item.Node];
2310*f6dc9357SAndroid Build Coastguard Worker
2311*f6dc9357SAndroid Build Coastguard Worker if (node.IsDir())
2312*f6dc9357SAndroid Build Coastguard Worker return E_FAIL;
2313*f6dc9357SAndroid Build Coastguard Worker
2314*f6dc9357SAndroid Build Coastguard Worker const Byte *p = _inodesData.Data + _nodesPos[item.Node];
2315*f6dc9357SAndroid Build Coastguard Worker
2316*f6dc9357SAndroid Build Coastguard Worker if (node.FileSize == 0 || node.IsLink())
2317*f6dc9357SAndroid Build Coastguard Worker {
2318*f6dc9357SAndroid Build Coastguard Worker CBufInStream *streamSpec = new CBufInStream;
2319*f6dc9357SAndroid Build Coastguard Worker CMyComPtr<IInStream> streamTemp = streamSpec;
2320*f6dc9357SAndroid Build Coastguard Worker if (node.IsLink())
2321*f6dc9357SAndroid Build Coastguard Worker streamSpec->Init(p + _h.GetSymLinkOffset(), (size_t)node.FileSize);
2322*f6dc9357SAndroid Build Coastguard Worker else
2323*f6dc9357SAndroid Build Coastguard Worker streamSpec->Init(NULL, 0);
2324*f6dc9357SAndroid Build Coastguard Worker *stream = streamTemp.Detach();
2325*f6dc9357SAndroid Build Coastguard Worker return S_OK;
2326*f6dc9357SAndroid Build Coastguard Worker }
2327*f6dc9357SAndroid Build Coastguard Worker
2328*f6dc9357SAndroid Build Coastguard Worker UInt64 packSize;
2329*f6dc9357SAndroid Build Coastguard Worker if (!GetPackSize(index, packSize, true))
2330*f6dc9357SAndroid Build Coastguard Worker return S_FALSE;
2331*f6dc9357SAndroid Build Coastguard Worker
2332*f6dc9357SAndroid Build Coastguard Worker _nodeIndex = item.Node;
2333*f6dc9357SAndroid Build Coastguard Worker
2334*f6dc9357SAndroid Build Coastguard Worker size_t cacheSize = _h.BlockSize;
2335*f6dc9357SAndroid Build Coastguard Worker if (_cachedBlock.Size() != cacheSize)
2336*f6dc9357SAndroid Build Coastguard Worker {
2337*f6dc9357SAndroid Build Coastguard Worker ClearCache();
2338*f6dc9357SAndroid Build Coastguard Worker _cachedBlock.Alloc(cacheSize);
2339*f6dc9357SAndroid Build Coastguard Worker }
2340*f6dc9357SAndroid Build Coastguard Worker
2341*f6dc9357SAndroid Build Coastguard Worker CSquashfsInStream *streamSpec = new CSquashfsInStream;
2342*f6dc9357SAndroid Build Coastguard Worker CMyComPtr<IInStream> streamTemp = streamSpec;
2343*f6dc9357SAndroid Build Coastguard Worker streamSpec->Handler = this;
2344*f6dc9357SAndroid Build Coastguard Worker unsigned cacheSizeLog = 22;
2345*f6dc9357SAndroid Build Coastguard Worker if (cacheSizeLog <= _h.BlockSizeLog)
2346*f6dc9357SAndroid Build Coastguard Worker cacheSizeLog = _h.BlockSizeLog + 1;
2347*f6dc9357SAndroid Build Coastguard Worker if (!streamSpec->Alloc(_h.BlockSizeLog, cacheSizeLog - _h.BlockSizeLog))
2348*f6dc9357SAndroid Build Coastguard Worker return E_OUTOFMEMORY;
2349*f6dc9357SAndroid Build Coastguard Worker streamSpec->Init(node.FileSize);
2350*f6dc9357SAndroid Build Coastguard Worker *stream = streamTemp.Detach();
2351*f6dc9357SAndroid Build Coastguard Worker
2352*f6dc9357SAndroid Build Coastguard Worker return S_OK;
2353*f6dc9357SAndroid Build Coastguard Worker
2354*f6dc9357SAndroid Build Coastguard Worker COM_TRY_END
2355*f6dc9357SAndroid Build Coastguard Worker }
2356*f6dc9357SAndroid Build Coastguard Worker
2357*f6dc9357SAndroid Build Coastguard Worker static const Byte k_Signature[] = {
2358*f6dc9357SAndroid Build Coastguard Worker 4, 'h', 's', 'q', 's',
2359*f6dc9357SAndroid Build Coastguard Worker 4, 's', 'q', 's', 'h',
2360*f6dc9357SAndroid Build Coastguard Worker 4, 's', 'h', 's', 'q',
2361*f6dc9357SAndroid Build Coastguard Worker 4, 'q', 's', 'h', 's' };
2362*f6dc9357SAndroid Build Coastguard Worker
2363*f6dc9357SAndroid Build Coastguard Worker REGISTER_ARC_I(
2364*f6dc9357SAndroid Build Coastguard Worker "SquashFS", "squashfs", NULL, 0xD2,
2365*f6dc9357SAndroid Build Coastguard Worker k_Signature,
2366*f6dc9357SAndroid Build Coastguard Worker 0,
2367*f6dc9357SAndroid Build Coastguard Worker NArcInfoFlags::kMultiSignature,
2368*f6dc9357SAndroid Build Coastguard Worker NULL)
2369*f6dc9357SAndroid Build Coastguard Worker
2370*f6dc9357SAndroid Build Coastguard Worker }}
2371