1*f6dc9357SAndroid Build Coastguard Worker // CpioHandler.cpp
2*f6dc9357SAndroid Build Coastguard Worker
3*f6dc9357SAndroid Build Coastguard Worker #include "StdAfx.h"
4*f6dc9357SAndroid Build Coastguard Worker
5*f6dc9357SAndroid Build Coastguard Worker #include "../../../C/CpuArch.h"
6*f6dc9357SAndroid Build Coastguard Worker
7*f6dc9357SAndroid Build Coastguard Worker #include "../../Common/ComTry.h"
8*f6dc9357SAndroid Build Coastguard Worker #include "../../Common/MyLinux.h"
9*f6dc9357SAndroid Build Coastguard Worker #include "../../Common/StringConvert.h"
10*f6dc9357SAndroid Build Coastguard Worker #include "../../Common/StringToInt.h"
11*f6dc9357SAndroid Build Coastguard Worker #include "../../Common/UTFConvert.h"
12*f6dc9357SAndroid Build Coastguard Worker
13*f6dc9357SAndroid Build Coastguard Worker #include "../../Windows/PropVariant.h"
14*f6dc9357SAndroid Build Coastguard Worker #include "../../Windows/TimeUtils.h"
15*f6dc9357SAndroid Build Coastguard Worker
16*f6dc9357SAndroid Build Coastguard Worker #include "../Common/LimitedStreams.h"
17*f6dc9357SAndroid Build Coastguard Worker #include "../Common/ProgressUtils.h"
18*f6dc9357SAndroid Build Coastguard Worker #include "../Common/RegisterArc.h"
19*f6dc9357SAndroid Build Coastguard Worker #include "../Common/StreamUtils.h"
20*f6dc9357SAndroid Build Coastguard Worker
21*f6dc9357SAndroid Build Coastguard Worker #include "../Compress/CopyCoder.h"
22*f6dc9357SAndroid Build Coastguard Worker
23*f6dc9357SAndroid Build Coastguard Worker #include "Common/ItemNameUtils.h"
24*f6dc9357SAndroid Build Coastguard Worker
25*f6dc9357SAndroid Build Coastguard Worker using namespace NWindows;
26*f6dc9357SAndroid Build Coastguard Worker
27*f6dc9357SAndroid Build Coastguard Worker namespace NArchive {
28*f6dc9357SAndroid Build Coastguard Worker namespace NCpio {
29*f6dc9357SAndroid Build Coastguard Worker
30*f6dc9357SAndroid Build Coastguard Worker static const Byte kMagicBin0 = 0xC7;
31*f6dc9357SAndroid Build Coastguard Worker static const Byte kMagicBin1 = 0x71;
32*f6dc9357SAndroid Build Coastguard Worker
33*f6dc9357SAndroid Build Coastguard Worker static const Byte kMagicHex = '1'; // New ASCII Format
34*f6dc9357SAndroid Build Coastguard Worker static const Byte kMagicHexCrc = '2'; // New CRC Format
35*f6dc9357SAndroid Build Coastguard Worker static const Byte kMagicOct = '7'; // Portable ASCII Format
36*f6dc9357SAndroid Build Coastguard Worker
37*f6dc9357SAndroid Build Coastguard Worker static const char * const kName_TRAILER = "TRAILER!!!";
38*f6dc9357SAndroid Build Coastguard Worker
39*f6dc9357SAndroid Build Coastguard Worker static const unsigned k_BinRecord_Size = 2 + 8 * 2 + 2 * 4;
40*f6dc9357SAndroid Build Coastguard Worker static const unsigned k_OctRecord_Size = 6 + 8 * 6 + 2 * 11;
41*f6dc9357SAndroid Build Coastguard Worker static const unsigned k_HexRecord_Size = 6 + 13 * 8;
42*f6dc9357SAndroid Build Coastguard Worker
43*f6dc9357SAndroid Build Coastguard Worker static const unsigned k_RecordSize_Max = k_HexRecord_Size;
44*f6dc9357SAndroid Build Coastguard Worker
45*f6dc9357SAndroid Build Coastguard Worker enum EType
46*f6dc9357SAndroid Build Coastguard Worker {
47*f6dc9357SAndroid Build Coastguard Worker k_Type_BinLe,
48*f6dc9357SAndroid Build Coastguard Worker k_Type_BinBe,
49*f6dc9357SAndroid Build Coastguard Worker k_Type_Oct,
50*f6dc9357SAndroid Build Coastguard Worker k_Type_Hex,
51*f6dc9357SAndroid Build Coastguard Worker k_Type_HexCrc
52*f6dc9357SAndroid Build Coastguard Worker };
53*f6dc9357SAndroid Build Coastguard Worker
54*f6dc9357SAndroid Build Coastguard Worker static const char * const k_Types[] =
55*f6dc9357SAndroid Build Coastguard Worker {
56*f6dc9357SAndroid Build Coastguard Worker "Binary LE"
57*f6dc9357SAndroid Build Coastguard Worker , "Binary BE"
58*f6dc9357SAndroid Build Coastguard Worker , "Portable ASCII"
59*f6dc9357SAndroid Build Coastguard Worker , "New ASCII"
60*f6dc9357SAndroid Build Coastguard Worker , "New CRC"
61*f6dc9357SAndroid Build Coastguard Worker };
62*f6dc9357SAndroid Build Coastguard Worker
63*f6dc9357SAndroid Build Coastguard Worker struct CItem
64*f6dc9357SAndroid Build Coastguard Worker {
65*f6dc9357SAndroid Build Coastguard Worker UInt32 inode;
66*f6dc9357SAndroid Build Coastguard Worker unsigned MainIndex_ForInode;
67*f6dc9357SAndroid Build Coastguard Worker UInt32 Mode;
68*f6dc9357SAndroid Build Coastguard Worker UInt32 MTime;
69*f6dc9357SAndroid Build Coastguard Worker UInt32 DevMajor;
70*f6dc9357SAndroid Build Coastguard Worker UInt32 DevMinor;
71*f6dc9357SAndroid Build Coastguard Worker UInt64 Size;
72*f6dc9357SAndroid Build Coastguard Worker AString Name;
73*f6dc9357SAndroid Build Coastguard Worker UInt32 NumLinks;
74*f6dc9357SAndroid Build Coastguard Worker UInt32 UID;
75*f6dc9357SAndroid Build Coastguard Worker UInt32 GID;
76*f6dc9357SAndroid Build Coastguard Worker UInt32 RDevMajor;
77*f6dc9357SAndroid Build Coastguard Worker UInt32 RDevMinor;
78*f6dc9357SAndroid Build Coastguard Worker UInt32 ChkSum;
79*f6dc9357SAndroid Build Coastguard Worker
80*f6dc9357SAndroid Build Coastguard Worker UInt32 AlignMask;
81*f6dc9357SAndroid Build Coastguard Worker EType Type;
82*f6dc9357SAndroid Build Coastguard Worker
83*f6dc9357SAndroid Build Coastguard Worker UInt32 HeaderSize;
84*f6dc9357SAndroid Build Coastguard Worker UInt64 HeaderPos;
85*f6dc9357SAndroid Build Coastguard Worker
86*f6dc9357SAndroid Build Coastguard Worker CByteBuffer Data; // for symlink
87*f6dc9357SAndroid Build Coastguard Worker
88*f6dc9357SAndroid Build Coastguard Worker
GetAlignedSizeNArchive::NCpio::CItem89*f6dc9357SAndroid Build Coastguard Worker UInt32 GetAlignedSize(UInt32 size) const
90*f6dc9357SAndroid Build Coastguard Worker {
91*f6dc9357SAndroid Build Coastguard Worker return (size + AlignMask) & ~(UInt32)AlignMask;
92*f6dc9357SAndroid Build Coastguard Worker }
93*f6dc9357SAndroid Build Coastguard Worker
GetPackSizeNArchive::NCpio::CItem94*f6dc9357SAndroid Build Coastguard Worker UInt64 GetPackSize() const
95*f6dc9357SAndroid Build Coastguard Worker {
96*f6dc9357SAndroid Build Coastguard Worker const UInt64 alignMask64 = AlignMask;
97*f6dc9357SAndroid Build Coastguard Worker return (Size + alignMask64) & ~(UInt64)alignMask64;
98*f6dc9357SAndroid Build Coastguard Worker }
99*f6dc9357SAndroid Build Coastguard Worker
IsSame_inode_DevNArchive::NCpio::CItem100*f6dc9357SAndroid Build Coastguard Worker bool IsSame_inode_Dev(const CItem &item) const
101*f6dc9357SAndroid Build Coastguard Worker {
102*f6dc9357SAndroid Build Coastguard Worker return inode == item.inode
103*f6dc9357SAndroid Build Coastguard Worker && DevMajor == item.DevMajor
104*f6dc9357SAndroid Build Coastguard Worker && DevMinor == item.DevMinor;
105*f6dc9357SAndroid Build Coastguard Worker }
106*f6dc9357SAndroid Build Coastguard Worker
IsBinNArchive::NCpio::CItem107*f6dc9357SAndroid Build Coastguard Worker bool IsBin() const { return Type == k_Type_BinLe || Type == k_Type_BinBe; }
IsCrcFormatNArchive::NCpio::CItem108*f6dc9357SAndroid Build Coastguard Worker bool IsCrcFormat() const { return Type == k_Type_HexCrc; }
IsDirNArchive::NCpio::CItem109*f6dc9357SAndroid Build Coastguard Worker bool IsDir() const { return MY_LIN_S_ISDIR(Mode); }
Is_SymLinkNArchive::NCpio::CItem110*f6dc9357SAndroid Build Coastguard Worker bool Is_SymLink() const { return MY_LIN_S_ISLNK(Mode); }
IsTrailerNArchive::NCpio::CItem111*f6dc9357SAndroid Build Coastguard Worker bool IsTrailer() const { return strcmp(Name, kName_TRAILER) == 0; }
GetDataPositionNArchive::NCpio::CItem112*f6dc9357SAndroid Build Coastguard Worker UInt64 GetDataPosition() const { return HeaderPos + HeaderSize; }
113*f6dc9357SAndroid Build Coastguard Worker };
114*f6dc9357SAndroid Build Coastguard Worker
115*f6dc9357SAndroid Build Coastguard Worker
116*f6dc9357SAndroid Build Coastguard Worker enum EErrorType
117*f6dc9357SAndroid Build Coastguard Worker {
118*f6dc9357SAndroid Build Coastguard Worker k_ErrorType_OK,
119*f6dc9357SAndroid Build Coastguard Worker k_ErrorType_BadSignature,
120*f6dc9357SAndroid Build Coastguard Worker k_ErrorType_Corrupted,
121*f6dc9357SAndroid Build Coastguard Worker k_ErrorType_UnexpectedEnd
122*f6dc9357SAndroid Build Coastguard Worker };
123*f6dc9357SAndroid Build Coastguard Worker
124*f6dc9357SAndroid Build Coastguard Worker
125*f6dc9357SAndroid Build Coastguard Worker struct CInArchive
126*f6dc9357SAndroid Build Coastguard Worker {
127*f6dc9357SAndroid Build Coastguard Worker EErrorType errorType;
128*f6dc9357SAndroid Build Coastguard Worker ISequentialInStream *Stream;
129*f6dc9357SAndroid Build Coastguard Worker UInt64 Processed;
130*f6dc9357SAndroid Build Coastguard Worker CItem item;
131*f6dc9357SAndroid Build Coastguard Worker
132*f6dc9357SAndroid Build Coastguard Worker HRESULT Read(void *data, size_t *size);
133*f6dc9357SAndroid Build Coastguard Worker HRESULT GetNextItem();
134*f6dc9357SAndroid Build Coastguard Worker };
135*f6dc9357SAndroid Build Coastguard Worker
Read(void * data,size_t * size)136*f6dc9357SAndroid Build Coastguard Worker HRESULT CInArchive::Read(void *data, size_t *size)
137*f6dc9357SAndroid Build Coastguard Worker {
138*f6dc9357SAndroid Build Coastguard Worker const HRESULT res = ReadStream(Stream, data, size);
139*f6dc9357SAndroid Build Coastguard Worker Processed += *size;
140*f6dc9357SAndroid Build Coastguard Worker return res;
141*f6dc9357SAndroid Build Coastguard Worker }
142*f6dc9357SAndroid Build Coastguard Worker
143*f6dc9357SAndroid Build Coastguard Worker
CheckOctRecord(const Byte * p)144*f6dc9357SAndroid Build Coastguard Worker static bool CheckOctRecord(const Byte *p)
145*f6dc9357SAndroid Build Coastguard Worker {
146*f6dc9357SAndroid Build Coastguard Worker for (unsigned i = 6; i < k_OctRecord_Size; i++)
147*f6dc9357SAndroid Build Coastguard Worker {
148*f6dc9357SAndroid Build Coastguard Worker const unsigned c = (unsigned)p[i] - '0';
149*f6dc9357SAndroid Build Coastguard Worker if (c > 7)
150*f6dc9357SAndroid Build Coastguard Worker return false;
151*f6dc9357SAndroid Build Coastguard Worker }
152*f6dc9357SAndroid Build Coastguard Worker return true;
153*f6dc9357SAndroid Build Coastguard Worker }
154*f6dc9357SAndroid Build Coastguard Worker
CheckHexRecord(const Byte * p)155*f6dc9357SAndroid Build Coastguard Worker static bool CheckHexRecord(const Byte *p)
156*f6dc9357SAndroid Build Coastguard Worker {
157*f6dc9357SAndroid Build Coastguard Worker for (unsigned i = 6; i < k_HexRecord_Size; i++)
158*f6dc9357SAndroid Build Coastguard Worker {
159*f6dc9357SAndroid Build Coastguard Worker unsigned c = p[i];
160*f6dc9357SAndroid Build Coastguard Worker c -= '0';
161*f6dc9357SAndroid Build Coastguard Worker if (c > 9)
162*f6dc9357SAndroid Build Coastguard Worker {
163*f6dc9357SAndroid Build Coastguard Worker c -= 'A' - '0';
164*f6dc9357SAndroid Build Coastguard Worker c &= ~0x20u;
165*f6dc9357SAndroid Build Coastguard Worker if (c > 5)
166*f6dc9357SAndroid Build Coastguard Worker return false;
167*f6dc9357SAndroid Build Coastguard Worker }
168*f6dc9357SAndroid Build Coastguard Worker }
169*f6dc9357SAndroid Build Coastguard Worker return true;
170*f6dc9357SAndroid Build Coastguard Worker }
171*f6dc9357SAndroid Build Coastguard Worker
ReadHex(const Byte * p)172*f6dc9357SAndroid Build Coastguard Worker static UInt32 ReadHex(const Byte *p)
173*f6dc9357SAndroid Build Coastguard Worker {
174*f6dc9357SAndroid Build Coastguard Worker char sz[16];
175*f6dc9357SAndroid Build Coastguard Worker memcpy(sz, p, 8);
176*f6dc9357SAndroid Build Coastguard Worker sz[8] = 0;
177*f6dc9357SAndroid Build Coastguard Worker const char *end;
178*f6dc9357SAndroid Build Coastguard Worker return ConvertHexStringToUInt32(sz, &end);
179*f6dc9357SAndroid Build Coastguard Worker }
180*f6dc9357SAndroid Build Coastguard Worker
ReadOct6(const Byte * p)181*f6dc9357SAndroid Build Coastguard Worker static UInt32 ReadOct6(const Byte *p)
182*f6dc9357SAndroid Build Coastguard Worker {
183*f6dc9357SAndroid Build Coastguard Worker char sz[16];
184*f6dc9357SAndroid Build Coastguard Worker memcpy(sz, p, 6);
185*f6dc9357SAndroid Build Coastguard Worker sz[6] = 0;
186*f6dc9357SAndroid Build Coastguard Worker const char *end;
187*f6dc9357SAndroid Build Coastguard Worker return ConvertOctStringToUInt32(sz, &end);
188*f6dc9357SAndroid Build Coastguard Worker }
189*f6dc9357SAndroid Build Coastguard Worker
ReadOct11(const Byte * p)190*f6dc9357SAndroid Build Coastguard Worker static UInt64 ReadOct11(const Byte *p)
191*f6dc9357SAndroid Build Coastguard Worker {
192*f6dc9357SAndroid Build Coastguard Worker char sz[16];
193*f6dc9357SAndroid Build Coastguard Worker memcpy(sz, p, 11);
194*f6dc9357SAndroid Build Coastguard Worker sz[11] = 0;
195*f6dc9357SAndroid Build Coastguard Worker const char *end;
196*f6dc9357SAndroid Build Coastguard Worker return ConvertOctStringToUInt64(sz, &end);
197*f6dc9357SAndroid Build Coastguard Worker }
198*f6dc9357SAndroid Build Coastguard Worker
199*f6dc9357SAndroid Build Coastguard Worker
200*f6dc9357SAndroid Build Coastguard Worker #define READ_HEX( y, dest) dest = ReadHex (p + 6 + (y) * 8);
201*f6dc9357SAndroid Build Coastguard Worker #define READ_OCT_6( y, dest) dest = ReadOct6 (p + 6 + (y));
202*f6dc9357SAndroid Build Coastguard Worker #define READ_OCT_11( y, dest) dest = ReadOct11(p + 6 + (y));
203*f6dc9357SAndroid Build Coastguard Worker
204*f6dc9357SAndroid Build Coastguard Worker #define Get32spec(p) (((UInt32)GetUi16(p) << 16) + GetUi16(p + 2))
205*f6dc9357SAndroid Build Coastguard Worker #define G16(offs, v) v = GetUi16(p + (offs))
206*f6dc9357SAndroid Build Coastguard Worker #define G32(offs, v) v = Get32spec(p + (offs))
207*f6dc9357SAndroid Build Coastguard Worker
208*f6dc9357SAndroid Build Coastguard Worker static const unsigned kNameSizeMax = 1 << 12;
209*f6dc9357SAndroid Build Coastguard Worker
210*f6dc9357SAndroid Build Coastguard Worker
IsArc_Cpio(const Byte * p,size_t size)211*f6dc9357SAndroid Build Coastguard Worker API_FUNC_static_IsArc IsArc_Cpio(const Byte *p, size_t size)
212*f6dc9357SAndroid Build Coastguard Worker {
213*f6dc9357SAndroid Build Coastguard Worker if (size < k_BinRecord_Size)
214*f6dc9357SAndroid Build Coastguard Worker return k_IsArc_Res_NEED_MORE;
215*f6dc9357SAndroid Build Coastguard Worker
216*f6dc9357SAndroid Build Coastguard Worker UInt32 namePos;
217*f6dc9357SAndroid Build Coastguard Worker UInt32 nameSize;
218*f6dc9357SAndroid Build Coastguard Worker UInt32 mode;
219*f6dc9357SAndroid Build Coastguard Worker // UInt32 rDevMinor;
220*f6dc9357SAndroid Build Coastguard Worker UInt32 rDevMajor = 0;
221*f6dc9357SAndroid Build Coastguard Worker
222*f6dc9357SAndroid Build Coastguard Worker if (p[0] == '0')
223*f6dc9357SAndroid Build Coastguard Worker {
224*f6dc9357SAndroid Build Coastguard Worker if (p[1] != '7' ||
225*f6dc9357SAndroid Build Coastguard Worker p[2] != '0' ||
226*f6dc9357SAndroid Build Coastguard Worker p[3] != '7' ||
227*f6dc9357SAndroid Build Coastguard Worker p[4] != '0')
228*f6dc9357SAndroid Build Coastguard Worker return k_IsArc_Res_NO;
229*f6dc9357SAndroid Build Coastguard Worker if (p[5] == kMagicOct)
230*f6dc9357SAndroid Build Coastguard Worker {
231*f6dc9357SAndroid Build Coastguard Worker if (size < k_OctRecord_Size)
232*f6dc9357SAndroid Build Coastguard Worker return k_IsArc_Res_NEED_MORE;
233*f6dc9357SAndroid Build Coastguard Worker if (!CheckOctRecord(p))
234*f6dc9357SAndroid Build Coastguard Worker return k_IsArc_Res_NO;
235*f6dc9357SAndroid Build Coastguard Worker READ_OCT_6 (2 * 6, mode)
236*f6dc9357SAndroid Build Coastguard Worker // READ_OCT_6 (6 * 6, rDevMinor)
237*f6dc9357SAndroid Build Coastguard Worker READ_OCT_6 (7 * 6 + 11, nameSize)
238*f6dc9357SAndroid Build Coastguard Worker namePos = k_OctRecord_Size;
239*f6dc9357SAndroid Build Coastguard Worker }
240*f6dc9357SAndroid Build Coastguard Worker else if (p[5] == kMagicHex || p[5] == kMagicHexCrc)
241*f6dc9357SAndroid Build Coastguard Worker {
242*f6dc9357SAndroid Build Coastguard Worker if (size < k_HexRecord_Size)
243*f6dc9357SAndroid Build Coastguard Worker return k_IsArc_Res_NEED_MORE;
244*f6dc9357SAndroid Build Coastguard Worker if (!CheckHexRecord(p))
245*f6dc9357SAndroid Build Coastguard Worker return k_IsArc_Res_NO;
246*f6dc9357SAndroid Build Coastguard Worker READ_HEX (1, mode)
247*f6dc9357SAndroid Build Coastguard Worker READ_HEX (9, rDevMajor)
248*f6dc9357SAndroid Build Coastguard Worker // READ_HEX (10, rDevMinor)
249*f6dc9357SAndroid Build Coastguard Worker READ_HEX (11, nameSize)
250*f6dc9357SAndroid Build Coastguard Worker namePos = k_HexRecord_Size;
251*f6dc9357SAndroid Build Coastguard Worker }
252*f6dc9357SAndroid Build Coastguard Worker else
253*f6dc9357SAndroid Build Coastguard Worker return k_IsArc_Res_NO;
254*f6dc9357SAndroid Build Coastguard Worker }
255*f6dc9357SAndroid Build Coastguard Worker else
256*f6dc9357SAndroid Build Coastguard Worker {
257*f6dc9357SAndroid Build Coastguard Worker if (p[0] == kMagicBin0 && p[1] == kMagicBin1)
258*f6dc9357SAndroid Build Coastguard Worker {
259*f6dc9357SAndroid Build Coastguard Worker mode = GetUi16(p + 6);
260*f6dc9357SAndroid Build Coastguard Worker // rDevMinor = GetUi16(p + 14);
261*f6dc9357SAndroid Build Coastguard Worker nameSize = GetUi16(p + 20);
262*f6dc9357SAndroid Build Coastguard Worker }
263*f6dc9357SAndroid Build Coastguard Worker else if (p[0] == kMagicBin1 && p[1] == kMagicBin0)
264*f6dc9357SAndroid Build Coastguard Worker {
265*f6dc9357SAndroid Build Coastguard Worker mode = GetBe16(p + 6);
266*f6dc9357SAndroid Build Coastguard Worker // rDevMinor = GetBe16(p + 14);
267*f6dc9357SAndroid Build Coastguard Worker nameSize = GetBe16(p + 20);
268*f6dc9357SAndroid Build Coastguard Worker }
269*f6dc9357SAndroid Build Coastguard Worker else
270*f6dc9357SAndroid Build Coastguard Worker return k_IsArc_Res_NO;
271*f6dc9357SAndroid Build Coastguard Worker namePos = k_BinRecord_Size;
272*f6dc9357SAndroid Build Coastguard Worker }
273*f6dc9357SAndroid Build Coastguard Worker
274*f6dc9357SAndroid Build Coastguard Worker if (mode >= (1 << 16))
275*f6dc9357SAndroid Build Coastguard Worker return k_IsArc_Res_NO;
276*f6dc9357SAndroid Build Coastguard Worker
277*f6dc9357SAndroid Build Coastguard Worker /* v23.02: we have disabled rDevMinor check because real file
278*f6dc9357SAndroid Build Coastguard Worker from Apple contains rDevMinor==255 by some unknown reason */
279*f6dc9357SAndroid Build Coastguard Worker if (rDevMajor != 0
280*f6dc9357SAndroid Build Coastguard Worker // || rDevMinor != 0
281*f6dc9357SAndroid Build Coastguard Worker )
282*f6dc9357SAndroid Build Coastguard Worker {
283*f6dc9357SAndroid Build Coastguard Worker if (!MY_LIN_S_ISCHR(mode) &&
284*f6dc9357SAndroid Build Coastguard Worker !MY_LIN_S_ISBLK(mode))
285*f6dc9357SAndroid Build Coastguard Worker return k_IsArc_Res_NO;
286*f6dc9357SAndroid Build Coastguard Worker }
287*f6dc9357SAndroid Build Coastguard Worker
288*f6dc9357SAndroid Build Coastguard Worker // nameSize must include the null byte
289*f6dc9357SAndroid Build Coastguard Worker if (nameSize == 0 || nameSize > kNameSizeMax)
290*f6dc9357SAndroid Build Coastguard Worker return k_IsArc_Res_NO;
291*f6dc9357SAndroid Build Coastguard Worker {
292*f6dc9357SAndroid Build Coastguard Worker unsigned lim = namePos + nameSize - 1;
293*f6dc9357SAndroid Build Coastguard Worker if (lim >= size)
294*f6dc9357SAndroid Build Coastguard Worker lim = (unsigned)size;
295*f6dc9357SAndroid Build Coastguard Worker else if (p[lim] != 0)
296*f6dc9357SAndroid Build Coastguard Worker return k_IsArc_Res_NO;
297*f6dc9357SAndroid Build Coastguard Worker for (unsigned i = namePos; i < lim; i++)
298*f6dc9357SAndroid Build Coastguard Worker if (p[i] == 0)
299*f6dc9357SAndroid Build Coastguard Worker return k_IsArc_Res_NO;
300*f6dc9357SAndroid Build Coastguard Worker }
301*f6dc9357SAndroid Build Coastguard Worker
302*f6dc9357SAndroid Build Coastguard Worker return k_IsArc_Res_YES;
303*f6dc9357SAndroid Build Coastguard Worker }
304*f6dc9357SAndroid Build Coastguard Worker }
305*f6dc9357SAndroid Build Coastguard Worker
306*f6dc9357SAndroid Build Coastguard Worker
307*f6dc9357SAndroid Build Coastguard Worker #define READ_STREAM(_dest_, _size_) \
308*f6dc9357SAndroid Build Coastguard Worker { size_t processed = (_size_); RINOK(Read(_dest_, &processed)); \
309*f6dc9357SAndroid Build Coastguard Worker if (processed != (_size_)) { errorType = k_ErrorType_UnexpectedEnd; return S_OK; } }
310*f6dc9357SAndroid Build Coastguard Worker
GetNextItem()311*f6dc9357SAndroid Build Coastguard Worker HRESULT CInArchive::GetNextItem()
312*f6dc9357SAndroid Build Coastguard Worker {
313*f6dc9357SAndroid Build Coastguard Worker errorType = k_ErrorType_BadSignature;
314*f6dc9357SAndroid Build Coastguard Worker
315*f6dc9357SAndroid Build Coastguard Worker Byte p[k_RecordSize_Max];
316*f6dc9357SAndroid Build Coastguard Worker
317*f6dc9357SAndroid Build Coastguard Worker READ_STREAM(p, k_BinRecord_Size)
318*f6dc9357SAndroid Build Coastguard Worker
319*f6dc9357SAndroid Build Coastguard Worker UInt32 nameSize;
320*f6dc9357SAndroid Build Coastguard Worker UInt32 namePos;
321*f6dc9357SAndroid Build Coastguard Worker
322*f6dc9357SAndroid Build Coastguard Worker /* we try to reduce probability of false detection,
323*f6dc9357SAndroid Build Coastguard Worker so we check some fields for unuxpected values */
324*f6dc9357SAndroid Build Coastguard Worker
325*f6dc9357SAndroid Build Coastguard Worker if (p[0] != '0')
326*f6dc9357SAndroid Build Coastguard Worker {
327*f6dc9357SAndroid Build Coastguard Worker if (p[0] == kMagicBin0 && p[1] == kMagicBin1) { item.Type = k_Type_BinLe; }
328*f6dc9357SAndroid Build Coastguard Worker else if (p[0] == kMagicBin1 && p[1] == kMagicBin0)
329*f6dc9357SAndroid Build Coastguard Worker {
330*f6dc9357SAndroid Build Coastguard Worker for (unsigned i = 2; i < k_BinRecord_Size; i += 2)
331*f6dc9357SAndroid Build Coastguard Worker {
332*f6dc9357SAndroid Build Coastguard Worker const Byte b = p[i];
333*f6dc9357SAndroid Build Coastguard Worker p[i] = p[i + 1];
334*f6dc9357SAndroid Build Coastguard Worker p[i + 1] = b;
335*f6dc9357SAndroid Build Coastguard Worker }
336*f6dc9357SAndroid Build Coastguard Worker item.Type = k_Type_BinBe;
337*f6dc9357SAndroid Build Coastguard Worker }
338*f6dc9357SAndroid Build Coastguard Worker else
339*f6dc9357SAndroid Build Coastguard Worker return S_OK;
340*f6dc9357SAndroid Build Coastguard Worker
341*f6dc9357SAndroid Build Coastguard Worker errorType = k_ErrorType_Corrupted;
342*f6dc9357SAndroid Build Coastguard Worker
343*f6dc9357SAndroid Build Coastguard Worker item.AlignMask = 2 - 1;
344*f6dc9357SAndroid Build Coastguard Worker item.DevMajor = 0;
345*f6dc9357SAndroid Build Coastguard Worker item.RDevMajor = 0;
346*f6dc9357SAndroid Build Coastguard Worker item.ChkSum = 0;
347*f6dc9357SAndroid Build Coastguard Worker
348*f6dc9357SAndroid Build Coastguard Worker G16(2, item.DevMinor);
349*f6dc9357SAndroid Build Coastguard Worker G16(4, item.inode);
350*f6dc9357SAndroid Build Coastguard Worker G16(6, item.Mode);
351*f6dc9357SAndroid Build Coastguard Worker G16(8, item.UID);
352*f6dc9357SAndroid Build Coastguard Worker G16(10, item.GID);
353*f6dc9357SAndroid Build Coastguard Worker G16(12, item.NumLinks);
354*f6dc9357SAndroid Build Coastguard Worker G16(14, item.RDevMinor);
355*f6dc9357SAndroid Build Coastguard Worker G32(16, item.MTime);
356*f6dc9357SAndroid Build Coastguard Worker G16(20, nameSize);
357*f6dc9357SAndroid Build Coastguard Worker G32(22, item.Size);
358*f6dc9357SAndroid Build Coastguard Worker
359*f6dc9357SAndroid Build Coastguard Worker namePos = k_BinRecord_Size;
360*f6dc9357SAndroid Build Coastguard Worker }
361*f6dc9357SAndroid Build Coastguard Worker else
362*f6dc9357SAndroid Build Coastguard Worker {
363*f6dc9357SAndroid Build Coastguard Worker if (p[1] != '7' ||
364*f6dc9357SAndroid Build Coastguard Worker p[2] != '0' ||
365*f6dc9357SAndroid Build Coastguard Worker p[3] != '7' ||
366*f6dc9357SAndroid Build Coastguard Worker p[4] != '0')
367*f6dc9357SAndroid Build Coastguard Worker return S_OK;
368*f6dc9357SAndroid Build Coastguard Worker if (p[5] == kMagicOct)
369*f6dc9357SAndroid Build Coastguard Worker {
370*f6dc9357SAndroid Build Coastguard Worker errorType = k_ErrorType_Corrupted;
371*f6dc9357SAndroid Build Coastguard Worker
372*f6dc9357SAndroid Build Coastguard Worker item.Type = k_Type_Oct;
373*f6dc9357SAndroid Build Coastguard Worker READ_STREAM(p + k_BinRecord_Size, k_OctRecord_Size - k_BinRecord_Size)
374*f6dc9357SAndroid Build Coastguard Worker item.AlignMask = 1 - 1;
375*f6dc9357SAndroid Build Coastguard Worker item.DevMajor = 0;
376*f6dc9357SAndroid Build Coastguard Worker item.RDevMajor = 0;
377*f6dc9357SAndroid Build Coastguard Worker item.ChkSum = 0;
378*f6dc9357SAndroid Build Coastguard Worker
379*f6dc9357SAndroid Build Coastguard Worker if (!CheckOctRecord(p))
380*f6dc9357SAndroid Build Coastguard Worker return S_OK;
381*f6dc9357SAndroid Build Coastguard Worker
382*f6dc9357SAndroid Build Coastguard Worker READ_OCT_6 (0, item.DevMinor)
383*f6dc9357SAndroid Build Coastguard Worker READ_OCT_6 (1 * 6, item.inode)
384*f6dc9357SAndroid Build Coastguard Worker READ_OCT_6 (2 * 6, item.Mode)
385*f6dc9357SAndroid Build Coastguard Worker READ_OCT_6 (3 * 6, item.UID)
386*f6dc9357SAndroid Build Coastguard Worker READ_OCT_6 (4 * 6, item.GID)
387*f6dc9357SAndroid Build Coastguard Worker READ_OCT_6 (5 * 6, item.NumLinks)
388*f6dc9357SAndroid Build Coastguard Worker READ_OCT_6 (6 * 6, item.RDevMinor)
389*f6dc9357SAndroid Build Coastguard Worker {
390*f6dc9357SAndroid Build Coastguard Worker UInt64 mTime64;
391*f6dc9357SAndroid Build Coastguard Worker READ_OCT_11 (7 * 6, mTime64)
392*f6dc9357SAndroid Build Coastguard Worker item.MTime = 0;
393*f6dc9357SAndroid Build Coastguard Worker if (mTime64 <= (UInt32)(Int32)-1)
394*f6dc9357SAndroid Build Coastguard Worker item.MTime = (UInt32)mTime64;
395*f6dc9357SAndroid Build Coastguard Worker }
396*f6dc9357SAndroid Build Coastguard Worker READ_OCT_6 (7 * 6 + 11, nameSize)
397*f6dc9357SAndroid Build Coastguard Worker READ_OCT_11 (8 * 6 + 11, item.Size) // ?????
398*f6dc9357SAndroid Build Coastguard Worker
399*f6dc9357SAndroid Build Coastguard Worker namePos = k_OctRecord_Size;
400*f6dc9357SAndroid Build Coastguard Worker }
401*f6dc9357SAndroid Build Coastguard Worker else
402*f6dc9357SAndroid Build Coastguard Worker {
403*f6dc9357SAndroid Build Coastguard Worker if (p[5] == kMagicHex) item.Type = k_Type_Hex;
404*f6dc9357SAndroid Build Coastguard Worker else if (p[5] == kMagicHexCrc) item.Type = k_Type_HexCrc;
405*f6dc9357SAndroid Build Coastguard Worker else return S_OK;
406*f6dc9357SAndroid Build Coastguard Worker
407*f6dc9357SAndroid Build Coastguard Worker errorType = k_ErrorType_Corrupted;
408*f6dc9357SAndroid Build Coastguard Worker
409*f6dc9357SAndroid Build Coastguard Worker READ_STREAM(p + k_BinRecord_Size, k_HexRecord_Size - k_BinRecord_Size)
410*f6dc9357SAndroid Build Coastguard Worker
411*f6dc9357SAndroid Build Coastguard Worker if (!CheckHexRecord(p))
412*f6dc9357SAndroid Build Coastguard Worker return S_OK;
413*f6dc9357SAndroid Build Coastguard Worker
414*f6dc9357SAndroid Build Coastguard Worker item.AlignMask = 4 - 1;
415*f6dc9357SAndroid Build Coastguard Worker READ_HEX (0, item.inode)
416*f6dc9357SAndroid Build Coastguard Worker READ_HEX (1, item.Mode)
417*f6dc9357SAndroid Build Coastguard Worker READ_HEX (2, item.UID)
418*f6dc9357SAndroid Build Coastguard Worker READ_HEX (3, item.GID)
419*f6dc9357SAndroid Build Coastguard Worker READ_HEX (4, item.NumLinks)
420*f6dc9357SAndroid Build Coastguard Worker READ_HEX (5, item.MTime)
421*f6dc9357SAndroid Build Coastguard Worker READ_HEX (6, item.Size)
422*f6dc9357SAndroid Build Coastguard Worker READ_HEX (7, item.DevMajor)
423*f6dc9357SAndroid Build Coastguard Worker READ_HEX (8, item.DevMinor)
424*f6dc9357SAndroid Build Coastguard Worker READ_HEX (9, item.RDevMajor)
425*f6dc9357SAndroid Build Coastguard Worker READ_HEX (10, item.RDevMinor)
426*f6dc9357SAndroid Build Coastguard Worker READ_HEX (11, nameSize)
427*f6dc9357SAndroid Build Coastguard Worker READ_HEX (12, item.ChkSum)
428*f6dc9357SAndroid Build Coastguard Worker
429*f6dc9357SAndroid Build Coastguard Worker if (item.Type == k_Type_Hex && item.ChkSum != 0)
430*f6dc9357SAndroid Build Coastguard Worker return S_OK;
431*f6dc9357SAndroid Build Coastguard Worker
432*f6dc9357SAndroid Build Coastguard Worker namePos = k_HexRecord_Size;
433*f6dc9357SAndroid Build Coastguard Worker }
434*f6dc9357SAndroid Build Coastguard Worker }
435*f6dc9357SAndroid Build Coastguard Worker
436*f6dc9357SAndroid Build Coastguard Worker if (item.Mode >= (1 << 16))
437*f6dc9357SAndroid Build Coastguard Worker return S_OK;
438*f6dc9357SAndroid Build Coastguard Worker
439*f6dc9357SAndroid Build Coastguard Worker /* v23.02: we have disabled rDevMinor check because real file
440*f6dc9357SAndroid Build Coastguard Worker from Apple contains rDevMinor==255 by some unknown reason */
441*f6dc9357SAndroid Build Coastguard Worker if (item.RDevMajor != 0
442*f6dc9357SAndroid Build Coastguard Worker // || item.RDevMinor != 0
443*f6dc9357SAndroid Build Coastguard Worker )
444*f6dc9357SAndroid Build Coastguard Worker {
445*f6dc9357SAndroid Build Coastguard Worker if (!MY_LIN_S_ISCHR(item.Mode) &&
446*f6dc9357SAndroid Build Coastguard Worker !MY_LIN_S_ISBLK(item.Mode))
447*f6dc9357SAndroid Build Coastguard Worker return S_OK;
448*f6dc9357SAndroid Build Coastguard Worker }
449*f6dc9357SAndroid Build Coastguard Worker
450*f6dc9357SAndroid Build Coastguard Worker // Size must be 0 for FIFOs and directories
451*f6dc9357SAndroid Build Coastguard Worker if (item.IsDir() || MY_LIN_S_ISFIFO(item.Mode))
452*f6dc9357SAndroid Build Coastguard Worker if (item.Size != 0)
453*f6dc9357SAndroid Build Coastguard Worker return S_OK;
454*f6dc9357SAndroid Build Coastguard Worker
455*f6dc9357SAndroid Build Coastguard Worker // nameSize must include the null byte
456*f6dc9357SAndroid Build Coastguard Worker if (nameSize == 0 || nameSize > kNameSizeMax)
457*f6dc9357SAndroid Build Coastguard Worker return S_OK;
458*f6dc9357SAndroid Build Coastguard Worker item.HeaderSize = item.GetAlignedSize(namePos + nameSize);
459*f6dc9357SAndroid Build Coastguard Worker const UInt32 rem = item.HeaderSize - namePos;
460*f6dc9357SAndroid Build Coastguard Worker char *s = item.Name.GetBuf(rem);
461*f6dc9357SAndroid Build Coastguard Worker size_t processedSize = rem;
462*f6dc9357SAndroid Build Coastguard Worker RINOK(Read(s, &processedSize))
463*f6dc9357SAndroid Build Coastguard Worker if (processedSize != rem)
464*f6dc9357SAndroid Build Coastguard Worker {
465*f6dc9357SAndroid Build Coastguard Worker item.Name.ReleaseBuf_SetEnd(0);
466*f6dc9357SAndroid Build Coastguard Worker errorType = k_ErrorType_UnexpectedEnd;
467*f6dc9357SAndroid Build Coastguard Worker return S_OK;
468*f6dc9357SAndroid Build Coastguard Worker }
469*f6dc9357SAndroid Build Coastguard Worker bool pad_error = false;
470*f6dc9357SAndroid Build Coastguard Worker for (size_t i = nameSize; i < processedSize; i++)
471*f6dc9357SAndroid Build Coastguard Worker if (s[i] != 0)
472*f6dc9357SAndroid Build Coastguard Worker pad_error = true;
473*f6dc9357SAndroid Build Coastguard Worker item.Name.ReleaseBuf_CalcLen(nameSize);
474*f6dc9357SAndroid Build Coastguard Worker if (item.Name.Len() + 1 != nameSize || pad_error)
475*f6dc9357SAndroid Build Coastguard Worker return S_OK;
476*f6dc9357SAndroid Build Coastguard Worker errorType = k_ErrorType_OK;
477*f6dc9357SAndroid Build Coastguard Worker return S_OK;
478*f6dc9357SAndroid Build Coastguard Worker }
479*f6dc9357SAndroid Build Coastguard Worker
480*f6dc9357SAndroid Build Coastguard Worker
481*f6dc9357SAndroid Build Coastguard Worker
482*f6dc9357SAndroid Build Coastguard Worker Z7_CLASS_IMP_CHandler_IInArchive_1(
483*f6dc9357SAndroid Build Coastguard Worker IInArchiveGetStream
484*f6dc9357SAndroid Build Coastguard Worker )
485*f6dc9357SAndroid Build Coastguard Worker CObjectVector<CItem> _items;
486*f6dc9357SAndroid Build Coastguard Worker CMyComPtr<IInStream> _stream;
487*f6dc9357SAndroid Build Coastguard Worker UInt64 _phySize;
488*f6dc9357SAndroid Build Coastguard Worker EType _type;
489*f6dc9357SAndroid Build Coastguard Worker EErrorType _error;
490*f6dc9357SAndroid Build Coastguard Worker bool _isArc;
491*f6dc9357SAndroid Build Coastguard Worker bool _moreThanOneHardLinks_Error;
492*f6dc9357SAndroid Build Coastguard Worker bool _numLinks_Error;
493*f6dc9357SAndroid Build Coastguard Worker bool _pad_Error;
494*f6dc9357SAndroid Build Coastguard Worker bool _symLink_Error;
495*f6dc9357SAndroid Build Coastguard Worker };
496*f6dc9357SAndroid Build Coastguard Worker
497*f6dc9357SAndroid Build Coastguard Worker static const Byte kArcProps[] =
498*f6dc9357SAndroid Build Coastguard Worker {
499*f6dc9357SAndroid Build Coastguard Worker kpidSubType
500*f6dc9357SAndroid Build Coastguard Worker };
501*f6dc9357SAndroid Build Coastguard Worker
502*f6dc9357SAndroid Build Coastguard Worker static const Byte kProps[] =
503*f6dc9357SAndroid Build Coastguard Worker {
504*f6dc9357SAndroid Build Coastguard Worker kpidPath,
505*f6dc9357SAndroid Build Coastguard Worker kpidIsDir,
506*f6dc9357SAndroid Build Coastguard Worker kpidSize,
507*f6dc9357SAndroid Build Coastguard Worker kpidPackSize,
508*f6dc9357SAndroid Build Coastguard Worker kpidMTime,
509*f6dc9357SAndroid Build Coastguard Worker kpidPosixAttrib,
510*f6dc9357SAndroid Build Coastguard Worker kpidLinks,
511*f6dc9357SAndroid Build Coastguard Worker kpidINode,
512*f6dc9357SAndroid Build Coastguard Worker kpidUserId,
513*f6dc9357SAndroid Build Coastguard Worker kpidGroupId,
514*f6dc9357SAndroid Build Coastguard Worker kpidDevMajor,
515*f6dc9357SAndroid Build Coastguard Worker kpidDevMinor,
516*f6dc9357SAndroid Build Coastguard Worker kpidDeviceMajor,
517*f6dc9357SAndroid Build Coastguard Worker kpidDeviceMinor,
518*f6dc9357SAndroid Build Coastguard Worker kpidChecksum,
519*f6dc9357SAndroid Build Coastguard Worker kpidSymLink,
520*f6dc9357SAndroid Build Coastguard Worker kpidStreamId, // for debug
521*f6dc9357SAndroid Build Coastguard Worker kpidOffset
522*f6dc9357SAndroid Build Coastguard Worker };
523*f6dc9357SAndroid Build Coastguard Worker
524*f6dc9357SAndroid Build Coastguard Worker IMP_IInArchive_Props
525*f6dc9357SAndroid Build Coastguard Worker IMP_IInArchive_ArcProps
526*f6dc9357SAndroid Build Coastguard Worker
Z7_COM7F_IMF(CHandler::GetArchiveProperty (PROPID propID,PROPVARIANT * value))527*f6dc9357SAndroid Build Coastguard Worker Z7_COM7F_IMF(CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value))
528*f6dc9357SAndroid Build Coastguard Worker {
529*f6dc9357SAndroid Build Coastguard Worker COM_TRY_BEGIN
530*f6dc9357SAndroid Build Coastguard Worker NCOM::CPropVariant prop;
531*f6dc9357SAndroid Build Coastguard Worker switch (propID)
532*f6dc9357SAndroid Build Coastguard Worker {
533*f6dc9357SAndroid Build Coastguard Worker case kpidSubType: prop = k_Types[(unsigned)_type]; break;
534*f6dc9357SAndroid Build Coastguard Worker case kpidPhySize: prop = _phySize; break;
535*f6dc9357SAndroid Build Coastguard Worker case kpidINode: prop = true; break;
536*f6dc9357SAndroid Build Coastguard Worker case kpidErrorFlags:
537*f6dc9357SAndroid Build Coastguard Worker {
538*f6dc9357SAndroid Build Coastguard Worker UInt32 v = 0;
539*f6dc9357SAndroid Build Coastguard Worker if (!_isArc)
540*f6dc9357SAndroid Build Coastguard Worker v |= kpv_ErrorFlags_IsNotArc;
541*f6dc9357SAndroid Build Coastguard Worker switch (_error)
542*f6dc9357SAndroid Build Coastguard Worker {
543*f6dc9357SAndroid Build Coastguard Worker case k_ErrorType_UnexpectedEnd: v |= kpv_ErrorFlags_UnexpectedEnd; break;
544*f6dc9357SAndroid Build Coastguard Worker case k_ErrorType_Corrupted: v |= kpv_ErrorFlags_HeadersError; break;
545*f6dc9357SAndroid Build Coastguard Worker case k_ErrorType_OK:
546*f6dc9357SAndroid Build Coastguard Worker case k_ErrorType_BadSignature:
547*f6dc9357SAndroid Build Coastguard Worker // default:
548*f6dc9357SAndroid Build Coastguard Worker break;
549*f6dc9357SAndroid Build Coastguard Worker }
550*f6dc9357SAndroid Build Coastguard Worker prop = v;
551*f6dc9357SAndroid Build Coastguard Worker break;
552*f6dc9357SAndroid Build Coastguard Worker }
553*f6dc9357SAndroid Build Coastguard Worker case kpidWarningFlags:
554*f6dc9357SAndroid Build Coastguard Worker {
555*f6dc9357SAndroid Build Coastguard Worker UInt32 v = 0;
556*f6dc9357SAndroid Build Coastguard Worker if (_moreThanOneHardLinks_Error)
557*f6dc9357SAndroid Build Coastguard Worker v |= kpv_ErrorFlags_UnsupportedFeature; // kpv_ErrorFlags_HeadersError
558*f6dc9357SAndroid Build Coastguard Worker if (_numLinks_Error
559*f6dc9357SAndroid Build Coastguard Worker || _pad_Error
560*f6dc9357SAndroid Build Coastguard Worker || _symLink_Error)
561*f6dc9357SAndroid Build Coastguard Worker v |= kpv_ErrorFlags_HeadersError;
562*f6dc9357SAndroid Build Coastguard Worker if (v != 0)
563*f6dc9357SAndroid Build Coastguard Worker prop = v;
564*f6dc9357SAndroid Build Coastguard Worker break;
565*f6dc9357SAndroid Build Coastguard Worker }
566*f6dc9357SAndroid Build Coastguard Worker }
567*f6dc9357SAndroid Build Coastguard Worker prop.Detach(value);
568*f6dc9357SAndroid Build Coastguard Worker return S_OK;
569*f6dc9357SAndroid Build Coastguard Worker COM_TRY_END
570*f6dc9357SAndroid Build Coastguard Worker }
571*f6dc9357SAndroid Build Coastguard Worker
572*f6dc9357SAndroid Build Coastguard Worker
CompareItems(const unsigned * p1,const unsigned * p2,void * param)573*f6dc9357SAndroid Build Coastguard Worker static int CompareItems(const unsigned *p1, const unsigned *p2, void *param)
574*f6dc9357SAndroid Build Coastguard Worker {
575*f6dc9357SAndroid Build Coastguard Worker const CObjectVector<CItem> &items = *(const CObjectVector<CItem> *)param;
576*f6dc9357SAndroid Build Coastguard Worker const unsigned index1 = *p1;
577*f6dc9357SAndroid Build Coastguard Worker const unsigned index2 = *p2;
578*f6dc9357SAndroid Build Coastguard Worker const CItem &i1 = items[index1];
579*f6dc9357SAndroid Build Coastguard Worker const CItem &i2 = items[index2];
580*f6dc9357SAndroid Build Coastguard Worker if (i1.DevMajor < i2.DevMajor) return -1;
581*f6dc9357SAndroid Build Coastguard Worker if (i1.DevMajor > i2.DevMajor) return 1;
582*f6dc9357SAndroid Build Coastguard Worker if (i1.DevMinor < i2.DevMinor) return -1;
583*f6dc9357SAndroid Build Coastguard Worker if (i1.DevMinor > i2.DevMinor) return 1;
584*f6dc9357SAndroid Build Coastguard Worker if (i1.inode < i2.inode) return -1;
585*f6dc9357SAndroid Build Coastguard Worker if (i1.inode > i2.inode) return 1;
586*f6dc9357SAndroid Build Coastguard Worker if (i1.IsDir())
587*f6dc9357SAndroid Build Coastguard Worker {
588*f6dc9357SAndroid Build Coastguard Worker if (!i2.IsDir())
589*f6dc9357SAndroid Build Coastguard Worker return -1;
590*f6dc9357SAndroid Build Coastguard Worker }
591*f6dc9357SAndroid Build Coastguard Worker else if (i2.IsDir())
592*f6dc9357SAndroid Build Coastguard Worker return 1;
593*f6dc9357SAndroid Build Coastguard Worker return MyCompare(index1, index2);
594*f6dc9357SAndroid Build Coastguard Worker }
595*f6dc9357SAndroid Build Coastguard Worker
596*f6dc9357SAndroid Build Coastguard Worker
Z7_COM7F_IMF(CHandler::Open (IInStream * stream,const UInt64 *,IArchiveOpenCallback * callback))597*f6dc9357SAndroid Build Coastguard Worker Z7_COM7F_IMF(CHandler::Open(IInStream *stream, const UInt64 *, IArchiveOpenCallback *callback))
598*f6dc9357SAndroid Build Coastguard Worker {
599*f6dc9357SAndroid Build Coastguard Worker COM_TRY_BEGIN
600*f6dc9357SAndroid Build Coastguard Worker {
601*f6dc9357SAndroid Build Coastguard Worker Close();
602*f6dc9357SAndroid Build Coastguard Worker
603*f6dc9357SAndroid Build Coastguard Worker UInt64 endPos;
604*f6dc9357SAndroid Build Coastguard Worker RINOK(InStream_AtBegin_GetSize(stream, endPos))
605*f6dc9357SAndroid Build Coastguard Worker if (callback)
606*f6dc9357SAndroid Build Coastguard Worker {
607*f6dc9357SAndroid Build Coastguard Worker RINOK(callback->SetTotal(NULL, &endPos))
608*f6dc9357SAndroid Build Coastguard Worker }
609*f6dc9357SAndroid Build Coastguard Worker
610*f6dc9357SAndroid Build Coastguard Worker CInArchive arc;
611*f6dc9357SAndroid Build Coastguard Worker
612*f6dc9357SAndroid Build Coastguard Worker arc.Stream = stream;
613*f6dc9357SAndroid Build Coastguard Worker arc.Processed = 0;
614*f6dc9357SAndroid Build Coastguard Worker
615*f6dc9357SAndroid Build Coastguard Worker for (;;)
616*f6dc9357SAndroid Build Coastguard Worker {
617*f6dc9357SAndroid Build Coastguard Worker CItem &item = arc.item;
618*f6dc9357SAndroid Build Coastguard Worker item.HeaderPos = arc.Processed;
619*f6dc9357SAndroid Build Coastguard Worker
620*f6dc9357SAndroid Build Coastguard Worker RINOK(arc.GetNextItem())
621*f6dc9357SAndroid Build Coastguard Worker
622*f6dc9357SAndroid Build Coastguard Worker _error = arc.errorType;
623*f6dc9357SAndroid Build Coastguard Worker
624*f6dc9357SAndroid Build Coastguard Worker if (_error != k_ErrorType_OK)
625*f6dc9357SAndroid Build Coastguard Worker {
626*f6dc9357SAndroid Build Coastguard Worker if (_error == k_ErrorType_BadSignature ||
627*f6dc9357SAndroid Build Coastguard Worker _error == k_ErrorType_Corrupted)
628*f6dc9357SAndroid Build Coastguard Worker arc.Processed = item.HeaderPos;
629*f6dc9357SAndroid Build Coastguard Worker break;
630*f6dc9357SAndroid Build Coastguard Worker }
631*f6dc9357SAndroid Build Coastguard Worker
632*f6dc9357SAndroid Build Coastguard Worker if (_items.IsEmpty())
633*f6dc9357SAndroid Build Coastguard Worker _type = item.Type;
634*f6dc9357SAndroid Build Coastguard Worker else if (_items.Back().Type != item.Type)
635*f6dc9357SAndroid Build Coastguard Worker {
636*f6dc9357SAndroid Build Coastguard Worker _error = k_ErrorType_Corrupted;
637*f6dc9357SAndroid Build Coastguard Worker arc.Processed = item.HeaderPos;
638*f6dc9357SAndroid Build Coastguard Worker break;
639*f6dc9357SAndroid Build Coastguard Worker }
640*f6dc9357SAndroid Build Coastguard Worker
641*f6dc9357SAndroid Build Coastguard Worker if (item.IsTrailer())
642*f6dc9357SAndroid Build Coastguard Worker break;
643*f6dc9357SAndroid Build Coastguard Worker
644*f6dc9357SAndroid Build Coastguard Worker item.MainIndex_ForInode = _items.Size();
645*f6dc9357SAndroid Build Coastguard Worker _items.Add(item);
646*f6dc9357SAndroid Build Coastguard Worker
647*f6dc9357SAndroid Build Coastguard Worker const UInt64 dataSize = item.GetPackSize();
648*f6dc9357SAndroid Build Coastguard Worker arc.Processed += dataSize;
649*f6dc9357SAndroid Build Coastguard Worker if (arc.Processed > endPos)
650*f6dc9357SAndroid Build Coastguard Worker {
651*f6dc9357SAndroid Build Coastguard Worker _error = k_ErrorType_UnexpectedEnd;
652*f6dc9357SAndroid Build Coastguard Worker break;
653*f6dc9357SAndroid Build Coastguard Worker }
654*f6dc9357SAndroid Build Coastguard Worker
655*f6dc9357SAndroid Build Coastguard Worker if (item.Is_SymLink() && dataSize <= (1 << 12) && item.Size != 0)
656*f6dc9357SAndroid Build Coastguard Worker {
657*f6dc9357SAndroid Build Coastguard Worker size_t cur = (size_t)dataSize;
658*f6dc9357SAndroid Build Coastguard Worker CByteBuffer buf;
659*f6dc9357SAndroid Build Coastguard Worker buf.Alloc(cur);
660*f6dc9357SAndroid Build Coastguard Worker RINOK(ReadStream(stream, buf, &cur))
661*f6dc9357SAndroid Build Coastguard Worker if (cur != dataSize)
662*f6dc9357SAndroid Build Coastguard Worker {
663*f6dc9357SAndroid Build Coastguard Worker _error = k_ErrorType_UnexpectedEnd;
664*f6dc9357SAndroid Build Coastguard Worker break;
665*f6dc9357SAndroid Build Coastguard Worker }
666*f6dc9357SAndroid Build Coastguard Worker size_t i;
667*f6dc9357SAndroid Build Coastguard Worker
668*f6dc9357SAndroid Build Coastguard Worker for (i = (size_t)item.Size; i < dataSize; i++)
669*f6dc9357SAndroid Build Coastguard Worker if (buf[i] != 0)
670*f6dc9357SAndroid Build Coastguard Worker break;
671*f6dc9357SAndroid Build Coastguard Worker if (i != dataSize)
672*f6dc9357SAndroid Build Coastguard Worker _pad_Error = true;
673*f6dc9357SAndroid Build Coastguard Worker
674*f6dc9357SAndroid Build Coastguard Worker for (i = 0; i < (size_t)item.Size; i++)
675*f6dc9357SAndroid Build Coastguard Worker if (buf[i] == 0)
676*f6dc9357SAndroid Build Coastguard Worker break;
677*f6dc9357SAndroid Build Coastguard Worker if (i != (size_t)item.Size)
678*f6dc9357SAndroid Build Coastguard Worker _symLink_Error = true;
679*f6dc9357SAndroid Build Coastguard Worker else
680*f6dc9357SAndroid Build Coastguard Worker _items.Back().Data.CopyFrom(buf, (size_t)item.Size);
681*f6dc9357SAndroid Build Coastguard Worker }
682*f6dc9357SAndroid Build Coastguard Worker else if (dataSize != 0)
683*f6dc9357SAndroid Build Coastguard Worker {
684*f6dc9357SAndroid Build Coastguard Worker UInt64 newPos;
685*f6dc9357SAndroid Build Coastguard Worker RINOK(stream->Seek((Int64)dataSize, STREAM_SEEK_CUR, &newPos))
686*f6dc9357SAndroid Build Coastguard Worker if (arc.Processed != newPos)
687*f6dc9357SAndroid Build Coastguard Worker return E_FAIL;
688*f6dc9357SAndroid Build Coastguard Worker }
689*f6dc9357SAndroid Build Coastguard Worker
690*f6dc9357SAndroid Build Coastguard Worker if (callback && (_items.Size() & 0xFFF) == 0)
691*f6dc9357SAndroid Build Coastguard Worker {
692*f6dc9357SAndroid Build Coastguard Worker const UInt64 numFiles = _items.Size();
693*f6dc9357SAndroid Build Coastguard Worker RINOK(callback->SetCompleted(&numFiles, &item.HeaderPos))
694*f6dc9357SAndroid Build Coastguard Worker }
695*f6dc9357SAndroid Build Coastguard Worker }
696*f6dc9357SAndroid Build Coastguard Worker
697*f6dc9357SAndroid Build Coastguard Worker _phySize = arc.Processed;
698*f6dc9357SAndroid Build Coastguard Worker }
699*f6dc9357SAndroid Build Coastguard Worker
700*f6dc9357SAndroid Build Coastguard Worker {
701*f6dc9357SAndroid Build Coastguard Worker if (_error != k_ErrorType_OK)
702*f6dc9357SAndroid Build Coastguard Worker {
703*f6dc9357SAndroid Build Coastguard Worker // we try to reduce probability of false detection
704*f6dc9357SAndroid Build Coastguard Worker if (_items.Size() == 0)
705*f6dc9357SAndroid Build Coastguard Worker return S_FALSE;
706*f6dc9357SAndroid Build Coastguard Worker // bin file uses small signature. So we do additional check for single item case.
707*f6dc9357SAndroid Build Coastguard Worker if (_items.Size() == 1 && _items[0].IsBin())
708*f6dc9357SAndroid Build Coastguard Worker return S_FALSE;
709*f6dc9357SAndroid Build Coastguard Worker }
710*f6dc9357SAndroid Build Coastguard Worker else
711*f6dc9357SAndroid Build Coastguard Worker {
712*f6dc9357SAndroid Build Coastguard Worker // Read tailing zeros.
713*f6dc9357SAndroid Build Coastguard Worker // Most of cpio files use 512-bytes aligned zeros
714*f6dc9357SAndroid Build Coastguard Worker // rare case: 4K/8K aligment is possible also
715*f6dc9357SAndroid Build Coastguard Worker const unsigned kTailSize_MAX = 1 << 9;
716*f6dc9357SAndroid Build Coastguard Worker Byte buf[kTailSize_MAX];
717*f6dc9357SAndroid Build Coastguard Worker
718*f6dc9357SAndroid Build Coastguard Worker unsigned pos = (unsigned)_phySize & (kTailSize_MAX - 1);
719*f6dc9357SAndroid Build Coastguard Worker if (pos != 0) // use this check to support 512 bytes alignment only
720*f6dc9357SAndroid Build Coastguard Worker for (;;)
721*f6dc9357SAndroid Build Coastguard Worker {
722*f6dc9357SAndroid Build Coastguard Worker const unsigned rem = kTailSize_MAX - pos;
723*f6dc9357SAndroid Build Coastguard Worker size_t processed = rem;
724*f6dc9357SAndroid Build Coastguard Worker RINOK(ReadStream(stream, buf + pos, &processed))
725*f6dc9357SAndroid Build Coastguard Worker if (processed != rem)
726*f6dc9357SAndroid Build Coastguard Worker break;
727*f6dc9357SAndroid Build Coastguard Worker for (; pos < kTailSize_MAX && buf[pos] == 0; pos++)
728*f6dc9357SAndroid Build Coastguard Worker {}
729*f6dc9357SAndroid Build Coastguard Worker if (pos != kTailSize_MAX)
730*f6dc9357SAndroid Build Coastguard Worker break;
731*f6dc9357SAndroid Build Coastguard Worker _phySize += processed;
732*f6dc9357SAndroid Build Coastguard Worker pos = 0;
733*f6dc9357SAndroid Build Coastguard Worker
734*f6dc9357SAndroid Build Coastguard Worker // use break to support 512 bytes alignment zero tail
735*f6dc9357SAndroid Build Coastguard Worker // don't use break to support 512*n bytes alignment zero tail
736*f6dc9357SAndroid Build Coastguard Worker break;
737*f6dc9357SAndroid Build Coastguard Worker }
738*f6dc9357SAndroid Build Coastguard Worker }
739*f6dc9357SAndroid Build Coastguard Worker }
740*f6dc9357SAndroid Build Coastguard Worker
741*f6dc9357SAndroid Build Coastguard Worker {
742*f6dc9357SAndroid Build Coastguard Worker /* there was such cpio archive example with hard links:
743*f6dc9357SAndroid Build Coastguard Worker {
744*f6dc9357SAndroid Build Coastguard Worker all hard links (same dev/inode) are stored in neighboring items, and
745*f6dc9357SAndroid Build Coastguard Worker (item.Size == 0) for non last hard link items
746*f6dc9357SAndroid Build Coastguard Worker (item.Size != 0) for last hard link item
747*f6dc9357SAndroid Build Coastguard Worker }
748*f6dc9357SAndroid Build Coastguard Worker but here we sort items by (dev/inode) to support cases
749*f6dc9357SAndroid Build Coastguard Worker where hard links (same dev/inode) are not stored in neighboring items.
750*f6dc9357SAndroid Build Coastguard Worker
751*f6dc9357SAndroid Build Coastguard Worker // note: some cpio files have (numLinks == 0) ??
752*f6dc9357SAndroid Build Coastguard Worker */
753*f6dc9357SAndroid Build Coastguard Worker
754*f6dc9357SAndroid Build Coastguard Worker CUIntVector indices;
755*f6dc9357SAndroid Build Coastguard Worker {
756*f6dc9357SAndroid Build Coastguard Worker const unsigned numItems = _items.Size();
757*f6dc9357SAndroid Build Coastguard Worker indices.ClearAndSetSize(numItems);
758*f6dc9357SAndroid Build Coastguard Worker if (numItems != 0)
759*f6dc9357SAndroid Build Coastguard Worker {
760*f6dc9357SAndroid Build Coastguard Worker unsigned *vals = &indices[0];
761*f6dc9357SAndroid Build Coastguard Worker for (unsigned i = 0; i < numItems; i++)
762*f6dc9357SAndroid Build Coastguard Worker vals[i] = i;
763*f6dc9357SAndroid Build Coastguard Worker indices.Sort(CompareItems, (void *)&_items);
764*f6dc9357SAndroid Build Coastguard Worker }
765*f6dc9357SAndroid Build Coastguard Worker }
766*f6dc9357SAndroid Build Coastguard Worker
767*f6dc9357SAndroid Build Coastguard Worker /* Note: if cpio archive (maybe incorrect) contains
768*f6dc9357SAndroid Build Coastguard Worker more then one non empty streams with identical inode number,
769*f6dc9357SAndroid Build Coastguard Worker we want to extract all such data streams too.
770*f6dc9357SAndroid Build Coastguard Worker
771*f6dc9357SAndroid Build Coastguard Worker So we place items with identical inode to groups:
772*f6dc9357SAndroid Build Coastguard Worker all items in group will have same MainIndex_ForInode,
773*f6dc9357SAndroid Build Coastguard Worker that is index of last item in group with (Size != 0).
774*f6dc9357SAndroid Build Coastguard Worker Another (non last) items in group have (Size == 0).
775*f6dc9357SAndroid Build Coastguard Worker If there are another hard links with same inode number
776*f6dc9357SAndroid Build Coastguard Worker after (Size != 0) item, we place them to another next group(s).
777*f6dc9357SAndroid Build Coastguard Worker
778*f6dc9357SAndroid Build Coastguard Worker Check it: maybe we should use single group for items
779*f6dc9357SAndroid Build Coastguard Worker with identical inode instead, and ignore some extra data streams ?
780*f6dc9357SAndroid Build Coastguard Worker */
781*f6dc9357SAndroid Build Coastguard Worker
782*f6dc9357SAndroid Build Coastguard Worker for (unsigned i = 0; i < indices.Size();)
783*f6dc9357SAndroid Build Coastguard Worker {
784*f6dc9357SAndroid Build Coastguard Worker unsigned k;
785*f6dc9357SAndroid Build Coastguard Worker {
786*f6dc9357SAndroid Build Coastguard Worker const CItem &item_Base = _items[indices[i]];
787*f6dc9357SAndroid Build Coastguard Worker
788*f6dc9357SAndroid Build Coastguard Worker if (item_Base.IsDir())
789*f6dc9357SAndroid Build Coastguard Worker {
790*f6dc9357SAndroid Build Coastguard Worker i++;
791*f6dc9357SAndroid Build Coastguard Worker continue;
792*f6dc9357SAndroid Build Coastguard Worker }
793*f6dc9357SAndroid Build Coastguard Worker
794*f6dc9357SAndroid Build Coastguard Worker if (i != 0)
795*f6dc9357SAndroid Build Coastguard Worker {
796*f6dc9357SAndroid Build Coastguard Worker const CItem &item_Prev = _items[indices[i - 1]];
797*f6dc9357SAndroid Build Coastguard Worker if (!item_Prev.IsDir())
798*f6dc9357SAndroid Build Coastguard Worker if (item_Base.IsSame_inode_Dev(item_Prev))
799*f6dc9357SAndroid Build Coastguard Worker _moreThanOneHardLinks_Error = true;
800*f6dc9357SAndroid Build Coastguard Worker }
801*f6dc9357SAndroid Build Coastguard Worker
802*f6dc9357SAndroid Build Coastguard Worker if (item_Base.Size != 0)
803*f6dc9357SAndroid Build Coastguard Worker {
804*f6dc9357SAndroid Build Coastguard Worker if (item_Base.NumLinks != 1)
805*f6dc9357SAndroid Build Coastguard Worker _numLinks_Error = true;
806*f6dc9357SAndroid Build Coastguard Worker i++;
807*f6dc9357SAndroid Build Coastguard Worker continue;
808*f6dc9357SAndroid Build Coastguard Worker }
809*f6dc9357SAndroid Build Coastguard Worker
810*f6dc9357SAndroid Build Coastguard Worker for (k = i + 1; k < indices.Size();)
811*f6dc9357SAndroid Build Coastguard Worker {
812*f6dc9357SAndroid Build Coastguard Worker const CItem &item = _items[indices[k]];
813*f6dc9357SAndroid Build Coastguard Worker if (item.IsDir())
814*f6dc9357SAndroid Build Coastguard Worker break;
815*f6dc9357SAndroid Build Coastguard Worker if (!item.IsSame_inode_Dev(item_Base))
816*f6dc9357SAndroid Build Coastguard Worker break;
817*f6dc9357SAndroid Build Coastguard Worker k++;
818*f6dc9357SAndroid Build Coastguard Worker if (item.Size != 0)
819*f6dc9357SAndroid Build Coastguard Worker break;
820*f6dc9357SAndroid Build Coastguard Worker }
821*f6dc9357SAndroid Build Coastguard Worker }
822*f6dc9357SAndroid Build Coastguard Worker
823*f6dc9357SAndroid Build Coastguard Worker const unsigned numLinks = k - i;
824*f6dc9357SAndroid Build Coastguard Worker for (;;)
825*f6dc9357SAndroid Build Coastguard Worker {
826*f6dc9357SAndroid Build Coastguard Worker CItem &item = _items[indices[i]];
827*f6dc9357SAndroid Build Coastguard Worker if (item.NumLinks != numLinks)
828*f6dc9357SAndroid Build Coastguard Worker _numLinks_Error = true;
829*f6dc9357SAndroid Build Coastguard Worker if (++i == k)
830*f6dc9357SAndroid Build Coastguard Worker break;
831*f6dc9357SAndroid Build Coastguard Worker // if (item.Size == 0)
832*f6dc9357SAndroid Build Coastguard Worker item.MainIndex_ForInode = indices[k - 1];
833*f6dc9357SAndroid Build Coastguard Worker }
834*f6dc9357SAndroid Build Coastguard Worker }
835*f6dc9357SAndroid Build Coastguard Worker }
836*f6dc9357SAndroid Build Coastguard Worker
837*f6dc9357SAndroid Build Coastguard Worker _isArc = true;
838*f6dc9357SAndroid Build Coastguard Worker _stream = stream;
839*f6dc9357SAndroid Build Coastguard Worker
840*f6dc9357SAndroid Build Coastguard Worker return S_OK;
841*f6dc9357SAndroid Build Coastguard Worker COM_TRY_END
842*f6dc9357SAndroid Build Coastguard Worker }
843*f6dc9357SAndroid Build Coastguard Worker
844*f6dc9357SAndroid Build Coastguard Worker
Z7_COM7F_IMF(CHandler::Close ())845*f6dc9357SAndroid Build Coastguard Worker Z7_COM7F_IMF(CHandler::Close())
846*f6dc9357SAndroid Build Coastguard Worker {
847*f6dc9357SAndroid Build Coastguard Worker _items.Clear();
848*f6dc9357SAndroid Build Coastguard Worker _stream.Release();
849*f6dc9357SAndroid Build Coastguard Worker _phySize = 0;
850*f6dc9357SAndroid Build Coastguard Worker _type = k_Type_BinLe;
851*f6dc9357SAndroid Build Coastguard Worker _isArc = false;
852*f6dc9357SAndroid Build Coastguard Worker _moreThanOneHardLinks_Error = false;
853*f6dc9357SAndroid Build Coastguard Worker _numLinks_Error = false;
854*f6dc9357SAndroid Build Coastguard Worker _pad_Error = false;
855*f6dc9357SAndroid Build Coastguard Worker _symLink_Error = false;
856*f6dc9357SAndroid Build Coastguard Worker _error = k_ErrorType_OK;
857*f6dc9357SAndroid Build Coastguard Worker return S_OK;
858*f6dc9357SAndroid Build Coastguard Worker }
859*f6dc9357SAndroid Build Coastguard Worker
Z7_COM7F_IMF(CHandler::GetNumberOfItems (UInt32 * numItems))860*f6dc9357SAndroid Build Coastguard Worker Z7_COM7F_IMF(CHandler::GetNumberOfItems(UInt32 *numItems))
861*f6dc9357SAndroid Build Coastguard Worker {
862*f6dc9357SAndroid Build Coastguard Worker *numItems = _items.Size();
863*f6dc9357SAndroid Build Coastguard Worker return S_OK;
864*f6dc9357SAndroid Build Coastguard Worker }
865*f6dc9357SAndroid Build Coastguard Worker
Z7_COM7F_IMF(CHandler::GetProperty (UInt32 index,PROPID propID,PROPVARIANT * value))866*f6dc9357SAndroid Build Coastguard Worker Z7_COM7F_IMF(CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *value))
867*f6dc9357SAndroid Build Coastguard Worker {
868*f6dc9357SAndroid Build Coastguard Worker COM_TRY_BEGIN
869*f6dc9357SAndroid Build Coastguard Worker NCOM::CPropVariant prop;
870*f6dc9357SAndroid Build Coastguard Worker const CItem &item = _items[index];
871*f6dc9357SAndroid Build Coastguard Worker
872*f6dc9357SAndroid Build Coastguard Worker switch (propID)
873*f6dc9357SAndroid Build Coastguard Worker {
874*f6dc9357SAndroid Build Coastguard Worker case kpidPath:
875*f6dc9357SAndroid Build Coastguard Worker {
876*f6dc9357SAndroid Build Coastguard Worker UString res;
877*f6dc9357SAndroid Build Coastguard Worker bool needConvert = true;
878*f6dc9357SAndroid Build Coastguard Worker #ifdef _WIN32
879*f6dc9357SAndroid Build Coastguard Worker // if (
880*f6dc9357SAndroid Build Coastguard Worker ConvertUTF8ToUnicode(item.Name, res);
881*f6dc9357SAndroid Build Coastguard Worker // )
882*f6dc9357SAndroid Build Coastguard Worker needConvert = false;
883*f6dc9357SAndroid Build Coastguard Worker #endif
884*f6dc9357SAndroid Build Coastguard Worker if (needConvert)
885*f6dc9357SAndroid Build Coastguard Worker res = MultiByteToUnicodeString(item.Name, CP_OEMCP);
886*f6dc9357SAndroid Build Coastguard Worker prop = NItemName::GetOsPath(res);
887*f6dc9357SAndroid Build Coastguard Worker break;
888*f6dc9357SAndroid Build Coastguard Worker }
889*f6dc9357SAndroid Build Coastguard Worker case kpidIsDir: prop = item.IsDir(); break;
890*f6dc9357SAndroid Build Coastguard Worker
891*f6dc9357SAndroid Build Coastguard Worker case kpidSize:
892*f6dc9357SAndroid Build Coastguard Worker prop = (UInt64)_items[item.MainIndex_ForInode].Size;
893*f6dc9357SAndroid Build Coastguard Worker break;
894*f6dc9357SAndroid Build Coastguard Worker
895*f6dc9357SAndroid Build Coastguard Worker case kpidPackSize:
896*f6dc9357SAndroid Build Coastguard Worker prop = (UInt64)item.GetPackSize();
897*f6dc9357SAndroid Build Coastguard Worker break;
898*f6dc9357SAndroid Build Coastguard Worker
899*f6dc9357SAndroid Build Coastguard Worker case kpidMTime:
900*f6dc9357SAndroid Build Coastguard Worker {
901*f6dc9357SAndroid Build Coastguard Worker if (item.MTime != 0)
902*f6dc9357SAndroid Build Coastguard Worker PropVariant_SetFrom_UnixTime(prop, item.MTime);
903*f6dc9357SAndroid Build Coastguard Worker break;
904*f6dc9357SAndroid Build Coastguard Worker }
905*f6dc9357SAndroid Build Coastguard Worker case kpidPosixAttrib: prop = item.Mode; break;
906*f6dc9357SAndroid Build Coastguard Worker case kpidINode: prop = item.inode; break;
907*f6dc9357SAndroid Build Coastguard Worker case kpidStreamId:
908*f6dc9357SAndroid Build Coastguard Worker if (!item.IsDir())
909*f6dc9357SAndroid Build Coastguard Worker prop = (UInt32)item.MainIndex_ForInode;
910*f6dc9357SAndroid Build Coastguard Worker break;
911*f6dc9357SAndroid Build Coastguard Worker case kpidDevMajor: prop = (UInt32)item.DevMajor; break;
912*f6dc9357SAndroid Build Coastguard Worker case kpidDevMinor: prop = (UInt32)item.DevMinor; break;
913*f6dc9357SAndroid Build Coastguard Worker
914*f6dc9357SAndroid Build Coastguard Worker case kpidUserId: prop = item.UID; break;
915*f6dc9357SAndroid Build Coastguard Worker case kpidGroupId: prop = item.GID; break;
916*f6dc9357SAndroid Build Coastguard Worker
917*f6dc9357SAndroid Build Coastguard Worker case kpidSymLink:
918*f6dc9357SAndroid Build Coastguard Worker if (item.Is_SymLink() && item.Data.Size() != 0)
919*f6dc9357SAndroid Build Coastguard Worker {
920*f6dc9357SAndroid Build Coastguard Worker AString s;
921*f6dc9357SAndroid Build Coastguard Worker s.SetFrom_CalcLen((const char *)(const void *)(const Byte *)item.Data, (unsigned)item.Data.Size());
922*f6dc9357SAndroid Build Coastguard Worker if (s.Len() == item.Data.Size())
923*f6dc9357SAndroid Build Coastguard Worker {
924*f6dc9357SAndroid Build Coastguard Worker UString u;
925*f6dc9357SAndroid Build Coastguard Worker bool needConvert = true;
926*f6dc9357SAndroid Build Coastguard Worker #ifdef _WIN32
927*f6dc9357SAndroid Build Coastguard Worker // if (
928*f6dc9357SAndroid Build Coastguard Worker ConvertUTF8ToUnicode(item.Name, u);
929*f6dc9357SAndroid Build Coastguard Worker // )
930*f6dc9357SAndroid Build Coastguard Worker needConvert = false;
931*f6dc9357SAndroid Build Coastguard Worker #endif
932*f6dc9357SAndroid Build Coastguard Worker if (needConvert)
933*f6dc9357SAndroid Build Coastguard Worker u = MultiByteToUnicodeString(s, CP_OEMCP);
934*f6dc9357SAndroid Build Coastguard Worker prop = u;
935*f6dc9357SAndroid Build Coastguard Worker }
936*f6dc9357SAndroid Build Coastguard Worker }
937*f6dc9357SAndroid Build Coastguard Worker break;
938*f6dc9357SAndroid Build Coastguard Worker
939*f6dc9357SAndroid Build Coastguard Worker case kpidLinks: prop = item.NumLinks; break;
940*f6dc9357SAndroid Build Coastguard Worker case kpidDeviceMajor:
941*f6dc9357SAndroid Build Coastguard Worker // if (item.RDevMajor != 0)
942*f6dc9357SAndroid Build Coastguard Worker prop = (UInt32)item.RDevMajor;
943*f6dc9357SAndroid Build Coastguard Worker break;
944*f6dc9357SAndroid Build Coastguard Worker case kpidDeviceMinor:
945*f6dc9357SAndroid Build Coastguard Worker // if (item.RDevMinor != 0)
946*f6dc9357SAndroid Build Coastguard Worker prop = (UInt32)item.RDevMinor;
947*f6dc9357SAndroid Build Coastguard Worker break;
948*f6dc9357SAndroid Build Coastguard Worker case kpidChecksum:
949*f6dc9357SAndroid Build Coastguard Worker if (item.IsCrcFormat())
950*f6dc9357SAndroid Build Coastguard Worker prop = item.ChkSum;
951*f6dc9357SAndroid Build Coastguard Worker break;
952*f6dc9357SAndroid Build Coastguard Worker case kpidOffset: prop = item.GetDataPosition(); break;
953*f6dc9357SAndroid Build Coastguard Worker }
954*f6dc9357SAndroid Build Coastguard Worker prop.Detach(value);
955*f6dc9357SAndroid Build Coastguard Worker return S_OK;
956*f6dc9357SAndroid Build Coastguard Worker COM_TRY_END
957*f6dc9357SAndroid Build Coastguard Worker }
958*f6dc9357SAndroid Build Coastguard Worker
959*f6dc9357SAndroid Build Coastguard Worker
960*f6dc9357SAndroid Build Coastguard Worker Z7_CLASS_IMP_NOQIB_1(
961*f6dc9357SAndroid Build Coastguard Worker COutStreamWithSum
962*f6dc9357SAndroid Build Coastguard Worker , ISequentialOutStream
963*f6dc9357SAndroid Build Coastguard Worker )
964*f6dc9357SAndroid Build Coastguard Worker CMyComPtr<ISequentialOutStream> _stream;
965*f6dc9357SAndroid Build Coastguard Worker UInt32 _checksum;
966*f6dc9357SAndroid Build Coastguard Worker bool _calculate;
967*f6dc9357SAndroid Build Coastguard Worker public:
968*f6dc9357SAndroid Build Coastguard Worker void SetStream(ISequentialOutStream *stream) { _stream = stream; }
969*f6dc9357SAndroid Build Coastguard Worker void ReleaseStream() { _stream.Release(); }
970*f6dc9357SAndroid Build Coastguard Worker void Init(bool calculate)
971*f6dc9357SAndroid Build Coastguard Worker {
972*f6dc9357SAndroid Build Coastguard Worker _calculate = calculate;
973*f6dc9357SAndroid Build Coastguard Worker _checksum = 0;
974*f6dc9357SAndroid Build Coastguard Worker }
975*f6dc9357SAndroid Build Coastguard Worker UInt32 GetChecksum() const { return _checksum; }
976*f6dc9357SAndroid Build Coastguard Worker };
977*f6dc9357SAndroid Build Coastguard Worker
978*f6dc9357SAndroid Build Coastguard Worker
979*f6dc9357SAndroid Build Coastguard Worker Z7_COM7F_IMF(COutStreamWithSum::Write(const void *data, UInt32 size, UInt32 *processedSize))
980*f6dc9357SAndroid Build Coastguard Worker {
981*f6dc9357SAndroid Build Coastguard Worker HRESULT result = S_OK;
982*f6dc9357SAndroid Build Coastguard Worker if (_stream)
983*f6dc9357SAndroid Build Coastguard Worker result = _stream->Write(data, size, &size);
984*f6dc9357SAndroid Build Coastguard Worker if (processedSize)
985*f6dc9357SAndroid Build Coastguard Worker *processedSize = size;
986*f6dc9357SAndroid Build Coastguard Worker if (_calculate)
987*f6dc9357SAndroid Build Coastguard Worker {
988*f6dc9357SAndroid Build Coastguard Worker const Byte *p = (const Byte *)data;
989*f6dc9357SAndroid Build Coastguard Worker const Byte *lim = p + size;
990*f6dc9357SAndroid Build Coastguard Worker UInt32 sum = _checksum;
991*f6dc9357SAndroid Build Coastguard Worker if (size >= 4)
992*f6dc9357SAndroid Build Coastguard Worker {
993*f6dc9357SAndroid Build Coastguard Worker lim -= 4 - 1;
994*f6dc9357SAndroid Build Coastguard Worker do
995*f6dc9357SAndroid Build Coastguard Worker {
996*f6dc9357SAndroid Build Coastguard Worker sum += p[0] + p[1] + p[2] + p[3];
997*f6dc9357SAndroid Build Coastguard Worker p += 4;
998*f6dc9357SAndroid Build Coastguard Worker }
999*f6dc9357SAndroid Build Coastguard Worker while (p < lim);
1000*f6dc9357SAndroid Build Coastguard Worker lim += 4 - 1;
1001*f6dc9357SAndroid Build Coastguard Worker }
1002*f6dc9357SAndroid Build Coastguard Worker if (p != lim) { sum += *p++;
1003*f6dc9357SAndroid Build Coastguard Worker if (p != lim) { sum += *p++;
1004*f6dc9357SAndroid Build Coastguard Worker if (p != lim) { sum += *p++; }}}
1005*f6dc9357SAndroid Build Coastguard Worker _checksum = sum;
1006*f6dc9357SAndroid Build Coastguard Worker }
1007*f6dc9357SAndroid Build Coastguard Worker return result;
1008*f6dc9357SAndroid Build Coastguard Worker }
1009*f6dc9357SAndroid Build Coastguard Worker
1010*f6dc9357SAndroid Build Coastguard Worker Z7_COM7F_IMF(CHandler::Extract(const UInt32 *indices, UInt32 numItems,
1011*f6dc9357SAndroid Build Coastguard Worker Int32 testMode, IArchiveExtractCallback *extractCallback))
1012*f6dc9357SAndroid Build Coastguard Worker {
1013*f6dc9357SAndroid Build Coastguard Worker COM_TRY_BEGIN
1014*f6dc9357SAndroid Build Coastguard Worker const bool allFilesMode = (numItems == (UInt32)(Int32)-1);
1015*f6dc9357SAndroid Build Coastguard Worker if (allFilesMode)
1016*f6dc9357SAndroid Build Coastguard Worker numItems = _items.Size();
1017*f6dc9357SAndroid Build Coastguard Worker if (numItems == 0)
1018*f6dc9357SAndroid Build Coastguard Worker return S_OK;
1019*f6dc9357SAndroid Build Coastguard Worker UInt64 totalSize = 0;
1020*f6dc9357SAndroid Build Coastguard Worker UInt32 i;
1021*f6dc9357SAndroid Build Coastguard Worker for (i = 0; i < numItems; i++)
1022*f6dc9357SAndroid Build Coastguard Worker {
1023*f6dc9357SAndroid Build Coastguard Worker const UInt32 index = allFilesMode ? i : indices[i];
1024*f6dc9357SAndroid Build Coastguard Worker const CItem &item2 = _items[index];
1025*f6dc9357SAndroid Build Coastguard Worker const CItem &item = _items[item2.MainIndex_ForInode];
1026*f6dc9357SAndroid Build Coastguard Worker totalSize += item.Size;
1027*f6dc9357SAndroid Build Coastguard Worker }
1028*f6dc9357SAndroid Build Coastguard Worker RINOK(extractCallback->SetTotal(totalSize))
1029*f6dc9357SAndroid Build Coastguard Worker
1030*f6dc9357SAndroid Build Coastguard Worker CMyComPtr2_Create<ICompressCoder, NCompress::CCopyCoder> copyCoder;
1031*f6dc9357SAndroid Build Coastguard Worker CMyComPtr2_Create<ICompressProgressInfo, CLocalProgress> lps;
1032*f6dc9357SAndroid Build Coastguard Worker lps->Init(extractCallback, false);
1033*f6dc9357SAndroid Build Coastguard Worker CMyComPtr2_Create<ISequentialInStream, CLimitedSequentialInStream> inStream;
1034*f6dc9357SAndroid Build Coastguard Worker inStream->SetStream(_stream);
1035*f6dc9357SAndroid Build Coastguard Worker CMyComPtr2_Create<ISequentialOutStream, COutStreamWithSum> outStreamSum;
1036*f6dc9357SAndroid Build Coastguard Worker
1037*f6dc9357SAndroid Build Coastguard Worker UInt64 total_PackSize = 0;
1038*f6dc9357SAndroid Build Coastguard Worker UInt64 total_UnpackSize = 0;
1039*f6dc9357SAndroid Build Coastguard Worker
1040*f6dc9357SAndroid Build Coastguard Worker for (i = 0;; i++)
1041*f6dc9357SAndroid Build Coastguard Worker {
1042*f6dc9357SAndroid Build Coastguard Worker lps->InSize = total_PackSize;
1043*f6dc9357SAndroid Build Coastguard Worker lps->OutSize = total_UnpackSize;
1044*f6dc9357SAndroid Build Coastguard Worker RINOK(lps->SetCur())
1045*f6dc9357SAndroid Build Coastguard Worker if (i >= numItems)
1046*f6dc9357SAndroid Build Coastguard Worker break;
1047*f6dc9357SAndroid Build Coastguard Worker const Int32 askMode = testMode ?
1048*f6dc9357SAndroid Build Coastguard Worker NExtract::NAskMode::kTest :
1049*f6dc9357SAndroid Build Coastguard Worker NExtract::NAskMode::kExtract;
1050*f6dc9357SAndroid Build Coastguard Worker const UInt32 index = allFilesMode ? i : indices[i];
1051*f6dc9357SAndroid Build Coastguard Worker const CItem &item2 = _items[index];
1052*f6dc9357SAndroid Build Coastguard Worker const CItem &item = _items[item2.MainIndex_ForInode];
1053*f6dc9357SAndroid Build Coastguard Worker {
1054*f6dc9357SAndroid Build Coastguard Worker CMyComPtr<ISequentialOutStream> outStream;
1055*f6dc9357SAndroid Build Coastguard Worker RINOK(extractCallback->GetStream(index, &outStream, askMode))
1056*f6dc9357SAndroid Build Coastguard Worker
1057*f6dc9357SAndroid Build Coastguard Worker total_PackSize += item2.GetPackSize();
1058*f6dc9357SAndroid Build Coastguard Worker total_UnpackSize += item.Size;
1059*f6dc9357SAndroid Build Coastguard Worker
1060*f6dc9357SAndroid Build Coastguard Worker if (item2.IsDir())
1061*f6dc9357SAndroid Build Coastguard Worker {
1062*f6dc9357SAndroid Build Coastguard Worker RINOK(extractCallback->PrepareOperation(askMode))
1063*f6dc9357SAndroid Build Coastguard Worker RINOK(extractCallback->SetOperationResult(NExtract::NOperationResult::kOK))
1064*f6dc9357SAndroid Build Coastguard Worker continue;
1065*f6dc9357SAndroid Build Coastguard Worker }
1066*f6dc9357SAndroid Build Coastguard Worker if (!testMode && !outStream)
1067*f6dc9357SAndroid Build Coastguard Worker continue;
1068*f6dc9357SAndroid Build Coastguard Worker outStreamSum->Init(item.IsCrcFormat());
1069*f6dc9357SAndroid Build Coastguard Worker outStreamSum->SetStream(outStream);
1070*f6dc9357SAndroid Build Coastguard Worker RINOK(extractCallback->PrepareOperation(askMode))
1071*f6dc9357SAndroid Build Coastguard Worker }
1072*f6dc9357SAndroid Build Coastguard Worker RINOK(InStream_SeekSet(_stream, item.GetDataPosition()))
1073*f6dc9357SAndroid Build Coastguard Worker inStream->Init(item.Size);
1074*f6dc9357SAndroid Build Coastguard Worker RINOK(copyCoder.Interface()->Code(inStream, outStreamSum, NULL, NULL, lps))
1075*f6dc9357SAndroid Build Coastguard Worker outStreamSum->ReleaseStream();
1076*f6dc9357SAndroid Build Coastguard Worker Int32 res = NExtract::NOperationResult::kDataError;
1077*f6dc9357SAndroid Build Coastguard Worker if (copyCoder->TotalSize == item.Size)
1078*f6dc9357SAndroid Build Coastguard Worker {
1079*f6dc9357SAndroid Build Coastguard Worker res = NExtract::NOperationResult::kOK;
1080*f6dc9357SAndroid Build Coastguard Worker if (item.IsCrcFormat() && item.ChkSum != outStreamSum->GetChecksum())
1081*f6dc9357SAndroid Build Coastguard Worker res = NExtract::NOperationResult::kCRCError;
1082*f6dc9357SAndroid Build Coastguard Worker }
1083*f6dc9357SAndroid Build Coastguard Worker RINOK(extractCallback->SetOperationResult(res))
1084*f6dc9357SAndroid Build Coastguard Worker }
1085*f6dc9357SAndroid Build Coastguard Worker return S_OK;
1086*f6dc9357SAndroid Build Coastguard Worker COM_TRY_END
1087*f6dc9357SAndroid Build Coastguard Worker }
1088*f6dc9357SAndroid Build Coastguard Worker
1089*f6dc9357SAndroid Build Coastguard Worker Z7_COM7F_IMF(CHandler::GetStream(UInt32 index, ISequentialInStream **stream))
1090*f6dc9357SAndroid Build Coastguard Worker {
1091*f6dc9357SAndroid Build Coastguard Worker COM_TRY_BEGIN
1092*f6dc9357SAndroid Build Coastguard Worker const CItem &item2 = _items[index];
1093*f6dc9357SAndroid Build Coastguard Worker const CItem &item = _items[item2.MainIndex_ForInode];
1094*f6dc9357SAndroid Build Coastguard Worker return CreateLimitedInStream(_stream, item.GetDataPosition(), item.Size, stream);
1095*f6dc9357SAndroid Build Coastguard Worker COM_TRY_END
1096*f6dc9357SAndroid Build Coastguard Worker }
1097*f6dc9357SAndroid Build Coastguard Worker
1098*f6dc9357SAndroid Build Coastguard Worker static const Byte k_Signature[] = {
1099*f6dc9357SAndroid Build Coastguard Worker 5, '0', '7', '0', '7', '0',
1100*f6dc9357SAndroid Build Coastguard Worker 2, kMagicBin0, kMagicBin1,
1101*f6dc9357SAndroid Build Coastguard Worker 2, kMagicBin1, kMagicBin0 };
1102*f6dc9357SAndroid Build Coastguard Worker
1103*f6dc9357SAndroid Build Coastguard Worker REGISTER_ARC_I(
1104*f6dc9357SAndroid Build Coastguard Worker "Cpio", "cpio", NULL, 0xED,
1105*f6dc9357SAndroid Build Coastguard Worker k_Signature,
1106*f6dc9357SAndroid Build Coastguard Worker 0,
1107*f6dc9357SAndroid Build Coastguard Worker NArcInfoFlags::kMultiSignature,
1108*f6dc9357SAndroid Build Coastguard Worker IsArc_Cpio)
1109*f6dc9357SAndroid Build Coastguard Worker
1110*f6dc9357SAndroid Build Coastguard Worker }}
1111