1*f6dc9357SAndroid Build Coastguard Worker // GzHandler.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 <stdio.h>
6*f6dc9357SAndroid Build Coastguard Worker
7*f6dc9357SAndroid Build Coastguard Worker #include "../../../C/CpuArch.h"
8*f6dc9357SAndroid Build Coastguard Worker
9*f6dc9357SAndroid Build Coastguard Worker #include "../../Common/ComTry.h"
10*f6dc9357SAndroid Build Coastguard Worker #include "../../Common/Defs.h"
11*f6dc9357SAndroid Build Coastguard Worker #include "../../Common/StringConvert.h"
12*f6dc9357SAndroid Build Coastguard Worker
13*f6dc9357SAndroid Build Coastguard Worker #include "../../Windows/PropVariantUtils.h"
14*f6dc9357SAndroid Build Coastguard Worker #include "../../Windows/TimeUtils.h"
15*f6dc9357SAndroid Build Coastguard Worker
16*f6dc9357SAndroid Build Coastguard Worker #include "../Common/ProgressUtils.h"
17*f6dc9357SAndroid Build Coastguard Worker #include "../Common/RegisterArc.h"
18*f6dc9357SAndroid Build Coastguard Worker #include "../Common/StreamUtils.h"
19*f6dc9357SAndroid Build Coastguard Worker
20*f6dc9357SAndroid Build Coastguard Worker #include "../Compress/CopyCoder.h"
21*f6dc9357SAndroid Build Coastguard Worker #include "../Compress/DeflateDecoder.h"
22*f6dc9357SAndroid Build Coastguard Worker #include "../Compress/DeflateEncoder.h"
23*f6dc9357SAndroid Build Coastguard Worker
24*f6dc9357SAndroid Build Coastguard Worker #include "Common/HandlerOut.h"
25*f6dc9357SAndroid Build Coastguard Worker #include "Common/InStreamWithCRC.h"
26*f6dc9357SAndroid Build Coastguard Worker #include "Common/OutStreamWithCRC.h"
27*f6dc9357SAndroid Build Coastguard Worker
28*f6dc9357SAndroid Build Coastguard Worker #define Get32(p) GetUi32(p)
29*f6dc9357SAndroid Build Coastguard Worker
30*f6dc9357SAndroid Build Coastguard Worker using namespace NWindows;
31*f6dc9357SAndroid Build Coastguard Worker
32*f6dc9357SAndroid Build Coastguard Worker using namespace NCompress;
33*f6dc9357SAndroid Build Coastguard Worker using namespace NDeflate;
34*f6dc9357SAndroid Build Coastguard Worker
35*f6dc9357SAndroid Build Coastguard Worker namespace NArchive {
36*f6dc9357SAndroid Build Coastguard Worker namespace NGz {
37*f6dc9357SAndroid Build Coastguard Worker
38*f6dc9357SAndroid Build Coastguard Worker static const Byte kSignature_0 = 0x1F;
39*f6dc9357SAndroid Build Coastguard Worker static const Byte kSignature_1 = 0x8B;
40*f6dc9357SAndroid Build Coastguard Worker static const Byte kSignature_2 = 8; // NCompressionMethod::kDeflate
41*f6dc9357SAndroid Build Coastguard Worker
42*f6dc9357SAndroid Build Coastguard Worker // Latest versions of gzip program don't write comment field to gz archive.
43*f6dc9357SAndroid Build Coastguard Worker // We also don't write comment field to gz archive.
44*f6dc9357SAndroid Build Coastguard Worker
45*f6dc9357SAndroid Build Coastguard Worker namespace NFlags
46*f6dc9357SAndroid Build Coastguard Worker {
47*f6dc9357SAndroid Build Coastguard Worker // const Byte kIsText = 1 << 0;
48*f6dc9357SAndroid Build Coastguard Worker const Byte kCrc = 1 << 1;
49*f6dc9357SAndroid Build Coastguard Worker const Byte kExtra = 1 << 2;
50*f6dc9357SAndroid Build Coastguard Worker const Byte kName = 1 << 3;
51*f6dc9357SAndroid Build Coastguard Worker const Byte kComment = 1 << 4;
52*f6dc9357SAndroid Build Coastguard Worker const Byte kReserved = 0xE0;
53*f6dc9357SAndroid Build Coastguard Worker }
54*f6dc9357SAndroid Build Coastguard Worker
55*f6dc9357SAndroid Build Coastguard Worker namespace NExtraFlags
56*f6dc9357SAndroid Build Coastguard Worker {
57*f6dc9357SAndroid Build Coastguard Worker const Byte kMaximum = 2;
58*f6dc9357SAndroid Build Coastguard Worker const Byte kFastest = 4;
59*f6dc9357SAndroid Build Coastguard Worker }
60*f6dc9357SAndroid Build Coastguard Worker
61*f6dc9357SAndroid Build Coastguard Worker namespace NHostOS
62*f6dc9357SAndroid Build Coastguard Worker {
63*f6dc9357SAndroid Build Coastguard Worker enum EEnum
64*f6dc9357SAndroid Build Coastguard Worker {
65*f6dc9357SAndroid Build Coastguard Worker kFAT = 0,
66*f6dc9357SAndroid Build Coastguard Worker kAMIGA,
67*f6dc9357SAndroid Build Coastguard Worker kVMS,
68*f6dc9357SAndroid Build Coastguard Worker kUnix,
69*f6dc9357SAndroid Build Coastguard Worker kVM_CMS,
70*f6dc9357SAndroid Build Coastguard Worker kAtari,
71*f6dc9357SAndroid Build Coastguard Worker kHPFS,
72*f6dc9357SAndroid Build Coastguard Worker kMac,
73*f6dc9357SAndroid Build Coastguard Worker kZ_System,
74*f6dc9357SAndroid Build Coastguard Worker kCPM,
75*f6dc9357SAndroid Build Coastguard Worker kTOPS20,
76*f6dc9357SAndroid Build Coastguard Worker kNTFS,
77*f6dc9357SAndroid Build Coastguard Worker kQDOS,
78*f6dc9357SAndroid Build Coastguard Worker kAcorn,
79*f6dc9357SAndroid Build Coastguard Worker kVFAT,
80*f6dc9357SAndroid Build Coastguard Worker kMVS,
81*f6dc9357SAndroid Build Coastguard Worker kBeOS,
82*f6dc9357SAndroid Build Coastguard Worker kTandem,
83*f6dc9357SAndroid Build Coastguard Worker
84*f6dc9357SAndroid Build Coastguard Worker kUnknown = 255
85*f6dc9357SAndroid Build Coastguard Worker };
86*f6dc9357SAndroid Build Coastguard Worker }
87*f6dc9357SAndroid Build Coastguard Worker
88*f6dc9357SAndroid Build Coastguard Worker static const char * const kHostOSes[] =
89*f6dc9357SAndroid Build Coastguard Worker {
90*f6dc9357SAndroid Build Coastguard Worker "FAT"
91*f6dc9357SAndroid Build Coastguard Worker , "AMIGA"
92*f6dc9357SAndroid Build Coastguard Worker , "VMS"
93*f6dc9357SAndroid Build Coastguard Worker , "Unix"
94*f6dc9357SAndroid Build Coastguard Worker , "VM/CMS"
95*f6dc9357SAndroid Build Coastguard Worker , "Atari"
96*f6dc9357SAndroid Build Coastguard Worker , "HPFS"
97*f6dc9357SAndroid Build Coastguard Worker , "Macintosh"
98*f6dc9357SAndroid Build Coastguard Worker , "Z-System"
99*f6dc9357SAndroid Build Coastguard Worker , "CP/M"
100*f6dc9357SAndroid Build Coastguard Worker , "TOPS-20"
101*f6dc9357SAndroid Build Coastguard Worker , "NTFS"
102*f6dc9357SAndroid Build Coastguard Worker , "SMS/QDOS"
103*f6dc9357SAndroid Build Coastguard Worker , "Acorn"
104*f6dc9357SAndroid Build Coastguard Worker , "VFAT"
105*f6dc9357SAndroid Build Coastguard Worker , "MVS"
106*f6dc9357SAndroid Build Coastguard Worker , "BeOS"
107*f6dc9357SAndroid Build Coastguard Worker , "Tandem"
108*f6dc9357SAndroid Build Coastguard Worker , "OS/400"
109*f6dc9357SAndroid Build Coastguard Worker , "OS/X"
110*f6dc9357SAndroid Build Coastguard Worker };
111*f6dc9357SAndroid Build Coastguard Worker
112*f6dc9357SAndroid Build Coastguard Worker
113*f6dc9357SAndroid Build Coastguard Worker class CItem
114*f6dc9357SAndroid Build Coastguard Worker {
TestFlag(Byte flag) const115*f6dc9357SAndroid Build Coastguard Worker bool TestFlag(Byte flag) const { return (Flags & flag) != 0; }
116*f6dc9357SAndroid Build Coastguard Worker public:
117*f6dc9357SAndroid Build Coastguard Worker Byte Flags;
118*f6dc9357SAndroid Build Coastguard Worker Byte ExtraFlags;
119*f6dc9357SAndroid Build Coastguard Worker Byte HostOS;
120*f6dc9357SAndroid Build Coastguard Worker UInt32 Time;
121*f6dc9357SAndroid Build Coastguard Worker UInt32 Crc;
122*f6dc9357SAndroid Build Coastguard Worker UInt32 Size32;
123*f6dc9357SAndroid Build Coastguard Worker
124*f6dc9357SAndroid Build Coastguard Worker AString Name;
125*f6dc9357SAndroid Build Coastguard Worker AString Comment;
126*f6dc9357SAndroid Build Coastguard Worker // CByteBuffer Extra;
127*f6dc9357SAndroid Build Coastguard Worker
CItem()128*f6dc9357SAndroid Build Coastguard Worker CItem():
129*f6dc9357SAndroid Build Coastguard Worker Flags(0),
130*f6dc9357SAndroid Build Coastguard Worker ExtraFlags(0),
131*f6dc9357SAndroid Build Coastguard Worker HostOS(0),
132*f6dc9357SAndroid Build Coastguard Worker Time(0),
133*f6dc9357SAndroid Build Coastguard Worker Crc(0),
134*f6dc9357SAndroid Build Coastguard Worker Size32(0) {}
135*f6dc9357SAndroid Build Coastguard Worker
Clear()136*f6dc9357SAndroid Build Coastguard Worker void Clear()
137*f6dc9357SAndroid Build Coastguard Worker {
138*f6dc9357SAndroid Build Coastguard Worker Name.Empty();
139*f6dc9357SAndroid Build Coastguard Worker Comment.Empty();
140*f6dc9357SAndroid Build Coastguard Worker // Extra.Free();
141*f6dc9357SAndroid Build Coastguard Worker }
142*f6dc9357SAndroid Build Coastguard Worker
CopyMetaPropsFrom(const CItem & a)143*f6dc9357SAndroid Build Coastguard Worker void CopyMetaPropsFrom(const CItem &a)
144*f6dc9357SAndroid Build Coastguard Worker {
145*f6dc9357SAndroid Build Coastguard Worker Flags = a.Flags;
146*f6dc9357SAndroid Build Coastguard Worker HostOS = a.HostOS;
147*f6dc9357SAndroid Build Coastguard Worker Time = a.Time;
148*f6dc9357SAndroid Build Coastguard Worker Name = a.Name;
149*f6dc9357SAndroid Build Coastguard Worker Comment = a.Comment;
150*f6dc9357SAndroid Build Coastguard Worker // Extra = a.Extra;
151*f6dc9357SAndroid Build Coastguard Worker }
152*f6dc9357SAndroid Build Coastguard Worker
CopyDataPropsFrom(const CItem & a)153*f6dc9357SAndroid Build Coastguard Worker void CopyDataPropsFrom(const CItem &a)
154*f6dc9357SAndroid Build Coastguard Worker {
155*f6dc9357SAndroid Build Coastguard Worker ExtraFlags = a.ExtraFlags;
156*f6dc9357SAndroid Build Coastguard Worker Crc = a.Crc;
157*f6dc9357SAndroid Build Coastguard Worker Size32 = a.Size32;
158*f6dc9357SAndroid Build Coastguard Worker }
159*f6dc9357SAndroid Build Coastguard Worker
160*f6dc9357SAndroid Build Coastguard Worker // bool IsText() const { return TestFlag(NFlags::kIsText); }
HeaderCrcIsPresent() const161*f6dc9357SAndroid Build Coastguard Worker bool HeaderCrcIsPresent() const { return TestFlag(NFlags::kCrc); }
ExtraFieldIsPresent() const162*f6dc9357SAndroid Build Coastguard Worker bool ExtraFieldIsPresent() const { return TestFlag(NFlags::kExtra); }
NameIsPresent() const163*f6dc9357SAndroid Build Coastguard Worker bool NameIsPresent() const { return TestFlag(NFlags::kName); }
CommentIsPresent() const164*f6dc9357SAndroid Build Coastguard Worker bool CommentIsPresent() const { return TestFlag(NFlags::kComment); }
IsSupported() const165*f6dc9357SAndroid Build Coastguard Worker bool IsSupported() const { return (Flags & NFlags::kReserved) == 0; }
166*f6dc9357SAndroid Build Coastguard Worker
167*f6dc9357SAndroid Build Coastguard Worker HRESULT ReadHeader(NDecoder::CCOMCoder *stream);
168*f6dc9357SAndroid Build Coastguard Worker HRESULT ReadFooter1(NDecoder::CCOMCoder *stream);
169*f6dc9357SAndroid Build Coastguard Worker HRESULT ReadFooter2(ISequentialInStream *stream);
170*f6dc9357SAndroid Build Coastguard Worker
171*f6dc9357SAndroid Build Coastguard Worker HRESULT WriteHeader(ISequentialOutStream *stream);
172*f6dc9357SAndroid Build Coastguard Worker HRESULT WriteFooter(ISequentialOutStream *stream);
173*f6dc9357SAndroid Build Coastguard Worker };
174*f6dc9357SAndroid Build Coastguard Worker
ReadBytes(NDecoder::CCOMCoder * stream,Byte * data,UInt32 size)175*f6dc9357SAndroid Build Coastguard Worker static HRESULT ReadBytes(NDecoder::CCOMCoder *stream, Byte *data, UInt32 size)
176*f6dc9357SAndroid Build Coastguard Worker {
177*f6dc9357SAndroid Build Coastguard Worker for (UInt32 i = 0; i < size; i++)
178*f6dc9357SAndroid Build Coastguard Worker data[i] = stream->ReadAlignedByte();
179*f6dc9357SAndroid Build Coastguard Worker return stream->InputEofError() ? S_FALSE : S_OK;
180*f6dc9357SAndroid Build Coastguard Worker }
181*f6dc9357SAndroid Build Coastguard Worker
SkipBytes(NDecoder::CCOMCoder * stream,UInt32 size)182*f6dc9357SAndroid Build Coastguard Worker static HRESULT SkipBytes(NDecoder::CCOMCoder *stream, UInt32 size)
183*f6dc9357SAndroid Build Coastguard Worker {
184*f6dc9357SAndroid Build Coastguard Worker for (UInt32 i = 0; i < size; i++)
185*f6dc9357SAndroid Build Coastguard Worker stream->ReadAlignedByte();
186*f6dc9357SAndroid Build Coastguard Worker return stream->InputEofError() ? S_FALSE : S_OK;
187*f6dc9357SAndroid Build Coastguard Worker }
188*f6dc9357SAndroid Build Coastguard Worker
ReadUInt16(NDecoder::CCOMCoder * stream,UInt32 & value)189*f6dc9357SAndroid Build Coastguard Worker static HRESULT ReadUInt16(NDecoder::CCOMCoder *stream, UInt32 &value /* , UInt32 &crc */)
190*f6dc9357SAndroid Build Coastguard Worker {
191*f6dc9357SAndroid Build Coastguard Worker value = 0;
192*f6dc9357SAndroid Build Coastguard Worker for (int i = 0; i < 2; i++)
193*f6dc9357SAndroid Build Coastguard Worker {
194*f6dc9357SAndroid Build Coastguard Worker Byte b = stream->ReadAlignedByte();
195*f6dc9357SAndroid Build Coastguard Worker if (stream->InputEofError())
196*f6dc9357SAndroid Build Coastguard Worker return S_FALSE;
197*f6dc9357SAndroid Build Coastguard Worker // crc = CRC_UPDATE_BYTE(crc, b);
198*f6dc9357SAndroid Build Coastguard Worker value |= ((UInt32)(b) << (8 * i));
199*f6dc9357SAndroid Build Coastguard Worker }
200*f6dc9357SAndroid Build Coastguard Worker return S_OK;
201*f6dc9357SAndroid Build Coastguard Worker }
202*f6dc9357SAndroid Build Coastguard Worker
ReadString(NDecoder::CCOMCoder * stream,AString & s,size_t limit)203*f6dc9357SAndroid Build Coastguard Worker static HRESULT ReadString(NDecoder::CCOMCoder *stream, AString &s, size_t limit /* , UInt32 &crc */)
204*f6dc9357SAndroid Build Coastguard Worker {
205*f6dc9357SAndroid Build Coastguard Worker s.Empty();
206*f6dc9357SAndroid Build Coastguard Worker for (size_t i = 0; i < limit; i++)
207*f6dc9357SAndroid Build Coastguard Worker {
208*f6dc9357SAndroid Build Coastguard Worker const Byte b = stream->ReadAlignedByte();
209*f6dc9357SAndroid Build Coastguard Worker if (stream->InputEofError())
210*f6dc9357SAndroid Build Coastguard Worker return S_FALSE;
211*f6dc9357SAndroid Build Coastguard Worker // crc = CRC_UPDATE_BYTE(crc, b);
212*f6dc9357SAndroid Build Coastguard Worker if (b == 0)
213*f6dc9357SAndroid Build Coastguard Worker return S_OK;
214*f6dc9357SAndroid Build Coastguard Worker s.Add_Char((char)b);
215*f6dc9357SAndroid Build Coastguard Worker }
216*f6dc9357SAndroid Build Coastguard Worker return S_FALSE;
217*f6dc9357SAndroid Build Coastguard Worker }
218*f6dc9357SAndroid Build Coastguard Worker
Is_Deflate(const Byte * p,size_t size)219*f6dc9357SAndroid Build Coastguard Worker static UInt32 Is_Deflate(const Byte *p, size_t size)
220*f6dc9357SAndroid Build Coastguard Worker {
221*f6dc9357SAndroid Build Coastguard Worker if (size < 1)
222*f6dc9357SAndroid Build Coastguard Worker return k_IsArc_Res_NEED_MORE;
223*f6dc9357SAndroid Build Coastguard Worker Byte b = *p;
224*f6dc9357SAndroid Build Coastguard Worker p++;
225*f6dc9357SAndroid Build Coastguard Worker size--;
226*f6dc9357SAndroid Build Coastguard Worker unsigned type = ((unsigned)b >> 1) & 3;
227*f6dc9357SAndroid Build Coastguard Worker if (type == 3)
228*f6dc9357SAndroid Build Coastguard Worker return k_IsArc_Res_NO;
229*f6dc9357SAndroid Build Coastguard Worker if (type == 0)
230*f6dc9357SAndroid Build Coastguard Worker {
231*f6dc9357SAndroid Build Coastguard Worker // Stored (uncompreessed data)
232*f6dc9357SAndroid Build Coastguard Worker if ((b >> 3) != 0)
233*f6dc9357SAndroid Build Coastguard Worker return k_IsArc_Res_NO;
234*f6dc9357SAndroid Build Coastguard Worker if (size < 4)
235*f6dc9357SAndroid Build Coastguard Worker return k_IsArc_Res_NEED_MORE;
236*f6dc9357SAndroid Build Coastguard Worker UInt16 r = (UInt16)~GetUi16(p + 2);
237*f6dc9357SAndroid Build Coastguard Worker if (GetUi16(p) != r)
238*f6dc9357SAndroid Build Coastguard Worker return k_IsArc_Res_NO;
239*f6dc9357SAndroid Build Coastguard Worker }
240*f6dc9357SAndroid Build Coastguard Worker else if (type == 2)
241*f6dc9357SAndroid Build Coastguard Worker {
242*f6dc9357SAndroid Build Coastguard Worker // Dynamic Huffman
243*f6dc9357SAndroid Build Coastguard Worker if (size < 1)
244*f6dc9357SAndroid Build Coastguard Worker return k_IsArc_Res_NEED_MORE;
245*f6dc9357SAndroid Build Coastguard Worker if ((*p & 0x1F) + 1 > 30) // numDistLevels
246*f6dc9357SAndroid Build Coastguard Worker return k_IsArc_Res_NO;
247*f6dc9357SAndroid Build Coastguard Worker }
248*f6dc9357SAndroid Build Coastguard Worker return k_IsArc_Res_YES;
249*f6dc9357SAndroid Build Coastguard Worker }
250*f6dc9357SAndroid Build Coastguard Worker
251*f6dc9357SAndroid Build Coastguard Worker static const unsigned kNameMaxLen = 1 << 12;
252*f6dc9357SAndroid Build Coastguard Worker static const unsigned kCommentMaxLen = 1 << 16;
253*f6dc9357SAndroid Build Coastguard Worker
IsArc_Gz(const Byte * p,size_t size)254*f6dc9357SAndroid Build Coastguard Worker API_FUNC_static_IsArc IsArc_Gz(const Byte *p, size_t size)
255*f6dc9357SAndroid Build Coastguard Worker {
256*f6dc9357SAndroid Build Coastguard Worker if (size < 10)
257*f6dc9357SAndroid Build Coastguard Worker return k_IsArc_Res_NEED_MORE;
258*f6dc9357SAndroid Build Coastguard Worker if (p[0] != kSignature_0 ||
259*f6dc9357SAndroid Build Coastguard Worker p[1] != kSignature_1 ||
260*f6dc9357SAndroid Build Coastguard Worker p[2] != kSignature_2)
261*f6dc9357SAndroid Build Coastguard Worker return k_IsArc_Res_NO;
262*f6dc9357SAndroid Build Coastguard Worker
263*f6dc9357SAndroid Build Coastguard Worker const Byte flags = p[3];
264*f6dc9357SAndroid Build Coastguard Worker if ((flags & NFlags::kReserved) != 0)
265*f6dc9357SAndroid Build Coastguard Worker return k_IsArc_Res_NO;
266*f6dc9357SAndroid Build Coastguard Worker
267*f6dc9357SAndroid Build Coastguard Worker const Byte extraFlags = p[8];
268*f6dc9357SAndroid Build Coastguard Worker // maybe that flag can have another values for some gz archives?
269*f6dc9357SAndroid Build Coastguard Worker if (extraFlags != 0 &&
270*f6dc9357SAndroid Build Coastguard Worker extraFlags != NExtraFlags::kMaximum &&
271*f6dc9357SAndroid Build Coastguard Worker extraFlags != NExtraFlags::kFastest)
272*f6dc9357SAndroid Build Coastguard Worker return k_IsArc_Res_NO;
273*f6dc9357SAndroid Build Coastguard Worker
274*f6dc9357SAndroid Build Coastguard Worker size -= 10;
275*f6dc9357SAndroid Build Coastguard Worker p += 10;
276*f6dc9357SAndroid Build Coastguard Worker
277*f6dc9357SAndroid Build Coastguard Worker if ((flags & NFlags::kExtra) != 0)
278*f6dc9357SAndroid Build Coastguard Worker {
279*f6dc9357SAndroid Build Coastguard Worker if (size < 2)
280*f6dc9357SAndroid Build Coastguard Worker return k_IsArc_Res_NEED_MORE;
281*f6dc9357SAndroid Build Coastguard Worker unsigned xlen = GetUi16(p);
282*f6dc9357SAndroid Build Coastguard Worker size -= 2;
283*f6dc9357SAndroid Build Coastguard Worker p += 2;
284*f6dc9357SAndroid Build Coastguard Worker while (xlen != 0)
285*f6dc9357SAndroid Build Coastguard Worker {
286*f6dc9357SAndroid Build Coastguard Worker if (xlen < 4)
287*f6dc9357SAndroid Build Coastguard Worker return k_IsArc_Res_NO;
288*f6dc9357SAndroid Build Coastguard Worker if (size < 4)
289*f6dc9357SAndroid Build Coastguard Worker return k_IsArc_Res_NEED_MORE;
290*f6dc9357SAndroid Build Coastguard Worker const unsigned len = GetUi16(p + 2);
291*f6dc9357SAndroid Build Coastguard Worker size -= 4;
292*f6dc9357SAndroid Build Coastguard Worker xlen -= 4;
293*f6dc9357SAndroid Build Coastguard Worker p += 4;
294*f6dc9357SAndroid Build Coastguard Worker if (len > xlen)
295*f6dc9357SAndroid Build Coastguard Worker return k_IsArc_Res_NO;
296*f6dc9357SAndroid Build Coastguard Worker if (len > size)
297*f6dc9357SAndroid Build Coastguard Worker return k_IsArc_Res_NEED_MORE;
298*f6dc9357SAndroid Build Coastguard Worker size -= len;
299*f6dc9357SAndroid Build Coastguard Worker xlen -= len;
300*f6dc9357SAndroid Build Coastguard Worker p += len;
301*f6dc9357SAndroid Build Coastguard Worker }
302*f6dc9357SAndroid Build Coastguard Worker }
303*f6dc9357SAndroid Build Coastguard Worker
304*f6dc9357SAndroid Build Coastguard Worker if ((flags & NFlags::kName) != 0)
305*f6dc9357SAndroid Build Coastguard Worker {
306*f6dc9357SAndroid Build Coastguard Worker size_t limit = kNameMaxLen;
307*f6dc9357SAndroid Build Coastguard Worker if (limit > size)
308*f6dc9357SAndroid Build Coastguard Worker limit = size;
309*f6dc9357SAndroid Build Coastguard Worker size_t i;
310*f6dc9357SAndroid Build Coastguard Worker for (i = 0; i < limit && p[i] != 0; i++);
311*f6dc9357SAndroid Build Coastguard Worker if (i == size)
312*f6dc9357SAndroid Build Coastguard Worker return k_IsArc_Res_NEED_MORE;
313*f6dc9357SAndroid Build Coastguard Worker if (i == limit)
314*f6dc9357SAndroid Build Coastguard Worker return k_IsArc_Res_NO;
315*f6dc9357SAndroid Build Coastguard Worker i++;
316*f6dc9357SAndroid Build Coastguard Worker p += i;
317*f6dc9357SAndroid Build Coastguard Worker size -= i;
318*f6dc9357SAndroid Build Coastguard Worker }
319*f6dc9357SAndroid Build Coastguard Worker
320*f6dc9357SAndroid Build Coastguard Worker if ((flags & NFlags::kComment) != 0)
321*f6dc9357SAndroid Build Coastguard Worker {
322*f6dc9357SAndroid Build Coastguard Worker size_t limit = kCommentMaxLen;
323*f6dc9357SAndroid Build Coastguard Worker if (limit > size)
324*f6dc9357SAndroid Build Coastguard Worker limit = size;
325*f6dc9357SAndroid Build Coastguard Worker size_t i;
326*f6dc9357SAndroid Build Coastguard Worker for (i = 0; i < limit && p[i] != 0; i++);
327*f6dc9357SAndroid Build Coastguard Worker if (i == size)
328*f6dc9357SAndroid Build Coastguard Worker return k_IsArc_Res_NEED_MORE;
329*f6dc9357SAndroid Build Coastguard Worker if (i == limit)
330*f6dc9357SAndroid Build Coastguard Worker return k_IsArc_Res_NO;
331*f6dc9357SAndroid Build Coastguard Worker i++;
332*f6dc9357SAndroid Build Coastguard Worker p += i;
333*f6dc9357SAndroid Build Coastguard Worker size -= i;
334*f6dc9357SAndroid Build Coastguard Worker }
335*f6dc9357SAndroid Build Coastguard Worker
336*f6dc9357SAndroid Build Coastguard Worker if ((flags & NFlags::kCrc) != 0)
337*f6dc9357SAndroid Build Coastguard Worker {
338*f6dc9357SAndroid Build Coastguard Worker if (size < 2)
339*f6dc9357SAndroid Build Coastguard Worker return k_IsArc_Res_NEED_MORE;
340*f6dc9357SAndroid Build Coastguard Worker p += 2;
341*f6dc9357SAndroid Build Coastguard Worker size -= 2;
342*f6dc9357SAndroid Build Coastguard Worker }
343*f6dc9357SAndroid Build Coastguard Worker
344*f6dc9357SAndroid Build Coastguard Worker return Is_Deflate(p, size);
345*f6dc9357SAndroid Build Coastguard Worker }
346*f6dc9357SAndroid Build Coastguard Worker }
347*f6dc9357SAndroid Build Coastguard Worker
ReadHeader(NDecoder::CCOMCoder * stream)348*f6dc9357SAndroid Build Coastguard Worker HRESULT CItem::ReadHeader(NDecoder::CCOMCoder *stream)
349*f6dc9357SAndroid Build Coastguard Worker {
350*f6dc9357SAndroid Build Coastguard Worker Clear();
351*f6dc9357SAndroid Build Coastguard Worker
352*f6dc9357SAndroid Build Coastguard Worker // Header-CRC field had another meaning in old version of gzip!
353*f6dc9357SAndroid Build Coastguard Worker // UInt32 crc = CRC_INIT_VAL;
354*f6dc9357SAndroid Build Coastguard Worker Byte buf[10];
355*f6dc9357SAndroid Build Coastguard Worker
356*f6dc9357SAndroid Build Coastguard Worker RINOK(ReadBytes(stream, buf, 10))
357*f6dc9357SAndroid Build Coastguard Worker
358*f6dc9357SAndroid Build Coastguard Worker if (buf[0] != kSignature_0 ||
359*f6dc9357SAndroid Build Coastguard Worker buf[1] != kSignature_1 ||
360*f6dc9357SAndroid Build Coastguard Worker buf[2] != kSignature_2)
361*f6dc9357SAndroid Build Coastguard Worker return S_FALSE;
362*f6dc9357SAndroid Build Coastguard Worker
363*f6dc9357SAndroid Build Coastguard Worker Flags = buf[3];
364*f6dc9357SAndroid Build Coastguard Worker if (!IsSupported())
365*f6dc9357SAndroid Build Coastguard Worker return S_FALSE;
366*f6dc9357SAndroid Build Coastguard Worker
367*f6dc9357SAndroid Build Coastguard Worker Time = Get32(buf + 4);
368*f6dc9357SAndroid Build Coastguard Worker ExtraFlags = buf[8];
369*f6dc9357SAndroid Build Coastguard Worker HostOS = buf[9];
370*f6dc9357SAndroid Build Coastguard Worker
371*f6dc9357SAndroid Build Coastguard Worker // crc = CrcUpdate(crc, buf, 10);
372*f6dc9357SAndroid Build Coastguard Worker
373*f6dc9357SAndroid Build Coastguard Worker if (ExtraFieldIsPresent())
374*f6dc9357SAndroid Build Coastguard Worker {
375*f6dc9357SAndroid Build Coastguard Worker UInt32 xlen;
376*f6dc9357SAndroid Build Coastguard Worker RINOK(ReadUInt16(stream, xlen /* , crc */))
377*f6dc9357SAndroid Build Coastguard Worker RINOK(SkipBytes(stream, xlen))
378*f6dc9357SAndroid Build Coastguard Worker // Extra.SetCapacity(xlen);
379*f6dc9357SAndroid Build Coastguard Worker // RINOK(ReadStream_FALSE(stream, Extra, xlen));
380*f6dc9357SAndroid Build Coastguard Worker // crc = CrcUpdate(crc, Extra, xlen);
381*f6dc9357SAndroid Build Coastguard Worker }
382*f6dc9357SAndroid Build Coastguard Worker if (NameIsPresent())
383*f6dc9357SAndroid Build Coastguard Worker RINOK(ReadString(stream, Name, kNameMaxLen /* , crc */))
384*f6dc9357SAndroid Build Coastguard Worker if (CommentIsPresent())
385*f6dc9357SAndroid Build Coastguard Worker RINOK(ReadString(stream, Comment, kCommentMaxLen /* , crc */))
386*f6dc9357SAndroid Build Coastguard Worker
387*f6dc9357SAndroid Build Coastguard Worker if (HeaderCrcIsPresent())
388*f6dc9357SAndroid Build Coastguard Worker {
389*f6dc9357SAndroid Build Coastguard Worker UInt32 headerCRC;
390*f6dc9357SAndroid Build Coastguard Worker // UInt32 dummy = 0;
391*f6dc9357SAndroid Build Coastguard Worker RINOK(ReadUInt16(stream, headerCRC /* , dummy */))
392*f6dc9357SAndroid Build Coastguard Worker /*
393*f6dc9357SAndroid Build Coastguard Worker if ((UInt16)CRC_GET_DIGEST(crc) != headerCRC)
394*f6dc9357SAndroid Build Coastguard Worker return S_FALSE;
395*f6dc9357SAndroid Build Coastguard Worker */
396*f6dc9357SAndroid Build Coastguard Worker }
397*f6dc9357SAndroid Build Coastguard Worker return stream->InputEofError() ? S_FALSE : S_OK;
398*f6dc9357SAndroid Build Coastguard Worker }
399*f6dc9357SAndroid Build Coastguard Worker
ReadFooter1(NDecoder::CCOMCoder * stream)400*f6dc9357SAndroid Build Coastguard Worker HRESULT CItem::ReadFooter1(NDecoder::CCOMCoder *stream)
401*f6dc9357SAndroid Build Coastguard Worker {
402*f6dc9357SAndroid Build Coastguard Worker Byte buf[8];
403*f6dc9357SAndroid Build Coastguard Worker RINOK(ReadBytes(stream, buf, 8))
404*f6dc9357SAndroid Build Coastguard Worker Crc = Get32(buf);
405*f6dc9357SAndroid Build Coastguard Worker Size32 = Get32(buf + 4);
406*f6dc9357SAndroid Build Coastguard Worker return stream->InputEofError() ? S_FALSE : S_OK;
407*f6dc9357SAndroid Build Coastguard Worker }
408*f6dc9357SAndroid Build Coastguard Worker
ReadFooter2(ISequentialInStream * stream)409*f6dc9357SAndroid Build Coastguard Worker HRESULT CItem::ReadFooter2(ISequentialInStream *stream)
410*f6dc9357SAndroid Build Coastguard Worker {
411*f6dc9357SAndroid Build Coastguard Worker Byte buf[8];
412*f6dc9357SAndroid Build Coastguard Worker RINOK(ReadStream_FALSE(stream, buf, 8))
413*f6dc9357SAndroid Build Coastguard Worker Crc = Get32(buf);
414*f6dc9357SAndroid Build Coastguard Worker Size32 = Get32(buf + 4);
415*f6dc9357SAndroid Build Coastguard Worker return S_OK;
416*f6dc9357SAndroid Build Coastguard Worker }
417*f6dc9357SAndroid Build Coastguard Worker
WriteHeader(ISequentialOutStream * stream)418*f6dc9357SAndroid Build Coastguard Worker HRESULT CItem::WriteHeader(ISequentialOutStream *stream)
419*f6dc9357SAndroid Build Coastguard Worker {
420*f6dc9357SAndroid Build Coastguard Worker Byte buf[10];
421*f6dc9357SAndroid Build Coastguard Worker buf[0] = kSignature_0;
422*f6dc9357SAndroid Build Coastguard Worker buf[1] = kSignature_1;
423*f6dc9357SAndroid Build Coastguard Worker buf[2] = kSignature_2;
424*f6dc9357SAndroid Build Coastguard Worker buf[3] = (Byte)(Flags & NFlags::kName);
425*f6dc9357SAndroid Build Coastguard Worker // buf[3] |= NFlags::kCrc;
426*f6dc9357SAndroid Build Coastguard Worker SetUi32(buf + 4, Time)
427*f6dc9357SAndroid Build Coastguard Worker buf[8] = ExtraFlags;
428*f6dc9357SAndroid Build Coastguard Worker buf[9] = HostOS;
429*f6dc9357SAndroid Build Coastguard Worker RINOK(WriteStream(stream, buf, 10))
430*f6dc9357SAndroid Build Coastguard Worker // crc = CrcUpdate(CRC_INIT_VAL, buf, 10);
431*f6dc9357SAndroid Build Coastguard Worker if (NameIsPresent())
432*f6dc9357SAndroid Build Coastguard Worker {
433*f6dc9357SAndroid Build Coastguard Worker // crc = CrcUpdate(crc, (const char *)Name, Name.Len() + 1);
434*f6dc9357SAndroid Build Coastguard Worker RINOK(WriteStream(stream, (const char *)Name, Name.Len() + 1))
435*f6dc9357SAndroid Build Coastguard Worker }
436*f6dc9357SAndroid Build Coastguard Worker // SetUi16(buf, (UInt16)CRC_GET_DIGEST(crc));
437*f6dc9357SAndroid Build Coastguard Worker // RINOK(WriteStream(stream, buf, 2));
438*f6dc9357SAndroid Build Coastguard Worker return S_OK;
439*f6dc9357SAndroid Build Coastguard Worker }
440*f6dc9357SAndroid Build Coastguard Worker
WriteFooter(ISequentialOutStream * stream)441*f6dc9357SAndroid Build Coastguard Worker HRESULT CItem::WriteFooter(ISequentialOutStream *stream)
442*f6dc9357SAndroid Build Coastguard Worker {
443*f6dc9357SAndroid Build Coastguard Worker Byte buf[8];
444*f6dc9357SAndroid Build Coastguard Worker SetUi32(buf, Crc)
445*f6dc9357SAndroid Build Coastguard Worker SetUi32(buf + 4, Size32)
446*f6dc9357SAndroid Build Coastguard Worker return WriteStream(stream, buf, 8);
447*f6dc9357SAndroid Build Coastguard Worker }
448*f6dc9357SAndroid Build Coastguard Worker
449*f6dc9357SAndroid Build Coastguard Worker Z7_CLASS_IMP_CHandler_IInArchive_3(
450*f6dc9357SAndroid Build Coastguard Worker IArchiveOpenSeq,
451*f6dc9357SAndroid Build Coastguard Worker IOutArchive,
452*f6dc9357SAndroid Build Coastguard Worker ISetProperties
453*f6dc9357SAndroid Build Coastguard Worker )
454*f6dc9357SAndroid Build Coastguard Worker CItem _item;
455*f6dc9357SAndroid Build Coastguard Worker
456*f6dc9357SAndroid Build Coastguard Worker bool _isArc;
457*f6dc9357SAndroid Build Coastguard Worker bool _needSeekToStart;
458*f6dc9357SAndroid Build Coastguard Worker bool _dataAfterEnd;
459*f6dc9357SAndroid Build Coastguard Worker bool _needMoreInput;
460*f6dc9357SAndroid Build Coastguard Worker
461*f6dc9357SAndroid Build Coastguard Worker bool _packSize_Defined;
462*f6dc9357SAndroid Build Coastguard Worker bool _unpackSize_Defined;
463*f6dc9357SAndroid Build Coastguard Worker bool _numStreams_Defined;
464*f6dc9357SAndroid Build Coastguard Worker
465*f6dc9357SAndroid Build Coastguard Worker UInt64 _packSize;
466*f6dc9357SAndroid Build Coastguard Worker UInt64 _unpackSize; // real unpack size (NOT from footer)
467*f6dc9357SAndroid Build Coastguard Worker UInt64 _numStreams;
468*f6dc9357SAndroid Build Coastguard Worker UInt64 _headerSize; // only start header (without footer)
469*f6dc9357SAndroid Build Coastguard Worker
470*f6dc9357SAndroid Build Coastguard Worker CMyComPtr<IInStream> _stream;
471*f6dc9357SAndroid Build Coastguard Worker CMyComPtr2<ICompressCoder, NDecoder::CCOMCoder> _decoder;
472*f6dc9357SAndroid Build Coastguard Worker
473*f6dc9357SAndroid Build Coastguard Worker CSingleMethodProps _props;
474*f6dc9357SAndroid Build Coastguard Worker CHandlerTimeOptions _timeOptions;
475*f6dc9357SAndroid Build Coastguard Worker
476*f6dc9357SAndroid Build Coastguard Worker public:
477*f6dc9357SAndroid Build Coastguard Worker CHandler():
478*f6dc9357SAndroid Build Coastguard Worker _isArc(false)
479*f6dc9357SAndroid Build Coastguard Worker {}
480*f6dc9357SAndroid Build Coastguard Worker
481*f6dc9357SAndroid Build Coastguard Worker void CreateDecoder()
482*f6dc9357SAndroid Build Coastguard Worker {
483*f6dc9357SAndroid Build Coastguard Worker _decoder.Create_if_Empty();
484*f6dc9357SAndroid Build Coastguard Worker }
485*f6dc9357SAndroid Build Coastguard Worker };
486*f6dc9357SAndroid Build Coastguard Worker
487*f6dc9357SAndroid Build Coastguard Worker static const Byte kProps[] =
488*f6dc9357SAndroid Build Coastguard Worker {
489*f6dc9357SAndroid Build Coastguard Worker kpidPath,
490*f6dc9357SAndroid Build Coastguard Worker kpidSize,
491*f6dc9357SAndroid Build Coastguard Worker kpidPackSize,
492*f6dc9357SAndroid Build Coastguard Worker kpidMTime,
493*f6dc9357SAndroid Build Coastguard Worker kpidHostOS,
494*f6dc9357SAndroid Build Coastguard Worker kpidCRC
495*f6dc9357SAndroid Build Coastguard Worker // kpidComment
496*f6dc9357SAndroid Build Coastguard Worker };
497*f6dc9357SAndroid Build Coastguard Worker
498*f6dc9357SAndroid Build Coastguard Worker static const Byte kArcProps[] =
499*f6dc9357SAndroid Build Coastguard Worker {
500*f6dc9357SAndroid Build Coastguard Worker kpidHeadersSize,
501*f6dc9357SAndroid Build Coastguard Worker kpidNumStreams
502*f6dc9357SAndroid Build Coastguard Worker };
503*f6dc9357SAndroid Build Coastguard Worker
504*f6dc9357SAndroid Build Coastguard Worker
505*f6dc9357SAndroid Build Coastguard Worker IMP_IInArchive_Props
506*f6dc9357SAndroid Build Coastguard Worker IMP_IInArchive_ArcProps
507*f6dc9357SAndroid Build Coastguard Worker
508*f6dc9357SAndroid Build Coastguard Worker Z7_COM7F_IMF(CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value))
509*f6dc9357SAndroid Build Coastguard Worker {
510*f6dc9357SAndroid Build Coastguard Worker COM_TRY_BEGIN
511*f6dc9357SAndroid Build Coastguard Worker NCOM::CPropVariant prop;
512*f6dc9357SAndroid Build Coastguard Worker switch (propID)
513*f6dc9357SAndroid Build Coastguard Worker {
514*f6dc9357SAndroid Build Coastguard Worker case kpidPhySize: if (_packSize_Defined) prop = _packSize; break;
515*f6dc9357SAndroid Build Coastguard Worker case kpidUnpackSize: if (_unpackSize_Defined) prop = _unpackSize; break;
516*f6dc9357SAndroid Build Coastguard Worker case kpidNumStreams: if (_numStreams_Defined) prop = _numStreams; break;
517*f6dc9357SAndroid Build Coastguard Worker case kpidHeadersSize: if (_headerSize != 0) prop = _headerSize; break;
518*f6dc9357SAndroid Build Coastguard Worker case kpidErrorFlags:
519*f6dc9357SAndroid Build Coastguard Worker {
520*f6dc9357SAndroid Build Coastguard Worker UInt32 v = 0;
521*f6dc9357SAndroid Build Coastguard Worker if (!_isArc) v |= kpv_ErrorFlags_IsNotArc;
522*f6dc9357SAndroid Build Coastguard Worker if (_needMoreInput) v |= kpv_ErrorFlags_UnexpectedEnd;
523*f6dc9357SAndroid Build Coastguard Worker if (_dataAfterEnd) v |= kpv_ErrorFlags_DataAfterEnd;
524*f6dc9357SAndroid Build Coastguard Worker prop = v;
525*f6dc9357SAndroid Build Coastguard Worker break;
526*f6dc9357SAndroid Build Coastguard Worker }
527*f6dc9357SAndroid Build Coastguard Worker case kpidName:
528*f6dc9357SAndroid Build Coastguard Worker if (_item.NameIsPresent())
529*f6dc9357SAndroid Build Coastguard Worker {
530*f6dc9357SAndroid Build Coastguard Worker UString s = MultiByteToUnicodeString(_item.Name, CP_ACP);
531*f6dc9357SAndroid Build Coastguard Worker s += ".gz";
532*f6dc9357SAndroid Build Coastguard Worker prop = s;
533*f6dc9357SAndroid Build Coastguard Worker }
534*f6dc9357SAndroid Build Coastguard Worker break;
535*f6dc9357SAndroid Build Coastguard Worker default: break;
536*f6dc9357SAndroid Build Coastguard Worker }
537*f6dc9357SAndroid Build Coastguard Worker prop.Detach(value);
538*f6dc9357SAndroid Build Coastguard Worker return S_OK;
539*f6dc9357SAndroid Build Coastguard Worker COM_TRY_END
540*f6dc9357SAndroid Build Coastguard Worker }
541*f6dc9357SAndroid Build Coastguard Worker
542*f6dc9357SAndroid Build Coastguard Worker
543*f6dc9357SAndroid Build Coastguard Worker Z7_COM7F_IMF(CHandler::GetNumberOfItems(UInt32 *numItems))
544*f6dc9357SAndroid Build Coastguard Worker {
545*f6dc9357SAndroid Build Coastguard Worker *numItems = 1;
546*f6dc9357SAndroid Build Coastguard Worker return S_OK;
547*f6dc9357SAndroid Build Coastguard Worker }
548*f6dc9357SAndroid Build Coastguard Worker
549*f6dc9357SAndroid Build Coastguard Worker Z7_COM7F_IMF(CHandler::GetProperty(UInt32 /* index */, PROPID propID, PROPVARIANT *value))
550*f6dc9357SAndroid Build Coastguard Worker {
551*f6dc9357SAndroid Build Coastguard Worker COM_TRY_BEGIN
552*f6dc9357SAndroid Build Coastguard Worker NCOM::CPropVariant prop;
553*f6dc9357SAndroid Build Coastguard Worker switch (propID)
554*f6dc9357SAndroid Build Coastguard Worker {
555*f6dc9357SAndroid Build Coastguard Worker case kpidPath:
556*f6dc9357SAndroid Build Coastguard Worker if (_item.NameIsPresent())
557*f6dc9357SAndroid Build Coastguard Worker prop = MultiByteToUnicodeString(_item.Name, CP_ACP);
558*f6dc9357SAndroid Build Coastguard Worker break;
559*f6dc9357SAndroid Build Coastguard Worker // case kpidComment: if (_item.CommentIsPresent()) prop = MultiByteToUnicodeString(_item.Comment, CP_ACP); break;
560*f6dc9357SAndroid Build Coastguard Worker case kpidMTime:
561*f6dc9357SAndroid Build Coastguard Worker // gzip specification: MTIME = 0 means no time stamp is available.
562*f6dc9357SAndroid Build Coastguard Worker if (_item.Time != 0)
563*f6dc9357SAndroid Build Coastguard Worker PropVariant_SetFrom_UnixTime(prop, _item.Time);
564*f6dc9357SAndroid Build Coastguard Worker break;
565*f6dc9357SAndroid Build Coastguard Worker case kpidTimeType:
566*f6dc9357SAndroid Build Coastguard Worker if (_item.Time != 0)
567*f6dc9357SAndroid Build Coastguard Worker prop = (UInt32)NFileTimeType::kUnix;
568*f6dc9357SAndroid Build Coastguard Worker break;
569*f6dc9357SAndroid Build Coastguard Worker case kpidSize:
570*f6dc9357SAndroid Build Coastguard Worker {
571*f6dc9357SAndroid Build Coastguard Worker if (_unpackSize_Defined)
572*f6dc9357SAndroid Build Coastguard Worker prop = _unpackSize;
573*f6dc9357SAndroid Build Coastguard Worker else if (_stream)
574*f6dc9357SAndroid Build Coastguard Worker prop = (UInt64)_item.Size32;
575*f6dc9357SAndroid Build Coastguard Worker break;
576*f6dc9357SAndroid Build Coastguard Worker }
577*f6dc9357SAndroid Build Coastguard Worker case kpidPackSize:
578*f6dc9357SAndroid Build Coastguard Worker {
579*f6dc9357SAndroid Build Coastguard Worker if (_packSize_Defined || _stream)
580*f6dc9357SAndroid Build Coastguard Worker prop = _packSize;
581*f6dc9357SAndroid Build Coastguard Worker break;
582*f6dc9357SAndroid Build Coastguard Worker }
583*f6dc9357SAndroid Build Coastguard Worker case kpidHostOS: TYPE_TO_PROP(kHostOSes, _item.HostOS, prop); break;
584*f6dc9357SAndroid Build Coastguard Worker case kpidCRC: if (_stream) prop = _item.Crc; break;
585*f6dc9357SAndroid Build Coastguard Worker default: break;
586*f6dc9357SAndroid Build Coastguard Worker }
587*f6dc9357SAndroid Build Coastguard Worker prop.Detach(value);
588*f6dc9357SAndroid Build Coastguard Worker return S_OK;
589*f6dc9357SAndroid Build Coastguard Worker COM_TRY_END
590*f6dc9357SAndroid Build Coastguard Worker }
591*f6dc9357SAndroid Build Coastguard Worker
592*f6dc9357SAndroid Build Coastguard Worker Z7_CLASS_IMP_COM_1(
593*f6dc9357SAndroid Build Coastguard Worker CCompressProgressInfoImp,
594*f6dc9357SAndroid Build Coastguard Worker ICompressProgressInfo
595*f6dc9357SAndroid Build Coastguard Worker )
596*f6dc9357SAndroid Build Coastguard Worker CMyComPtr<IArchiveOpenCallback> Callback;
597*f6dc9357SAndroid Build Coastguard Worker public:
598*f6dc9357SAndroid Build Coastguard Worker UInt64 Offset;
599*f6dc9357SAndroid Build Coastguard Worker void Init(IArchiveOpenCallback *callback) { Callback = callback; }
600*f6dc9357SAndroid Build Coastguard Worker };
601*f6dc9357SAndroid Build Coastguard Worker
602*f6dc9357SAndroid Build Coastguard Worker Z7_COM7F_IMF(CCompressProgressInfoImp::SetRatioInfo(const UInt64 *inSize, const UInt64 * /* outSize */))
603*f6dc9357SAndroid Build Coastguard Worker {
604*f6dc9357SAndroid Build Coastguard Worker if (Callback)
605*f6dc9357SAndroid Build Coastguard Worker {
606*f6dc9357SAndroid Build Coastguard Worker UInt64 files = 0;
607*f6dc9357SAndroid Build Coastguard Worker UInt64 value = Offset + *inSize;
608*f6dc9357SAndroid Build Coastguard Worker return Callback->SetCompleted(&files, &value);
609*f6dc9357SAndroid Build Coastguard Worker }
610*f6dc9357SAndroid Build Coastguard Worker return S_OK;
611*f6dc9357SAndroid Build Coastguard Worker }
612*f6dc9357SAndroid Build Coastguard Worker
613*f6dc9357SAndroid Build Coastguard Worker /*
614*f6dc9357SAndroid Build Coastguard Worker */
615*f6dc9357SAndroid Build Coastguard Worker
616*f6dc9357SAndroid Build Coastguard Worker Z7_COM7F_IMF(CHandler::Open(IInStream *stream, const UInt64 *, IArchiveOpenCallback *))
617*f6dc9357SAndroid Build Coastguard Worker {
618*f6dc9357SAndroid Build Coastguard Worker COM_TRY_BEGIN
619*f6dc9357SAndroid Build Coastguard Worker RINOK(OpenSeq(stream))
620*f6dc9357SAndroid Build Coastguard Worker _isArc = false;
621*f6dc9357SAndroid Build Coastguard Worker UInt64 endPos;
622*f6dc9357SAndroid Build Coastguard Worker RINOK(stream->Seek(-8, STREAM_SEEK_END, &endPos))
623*f6dc9357SAndroid Build Coastguard Worker _packSize = endPos + 8;
624*f6dc9357SAndroid Build Coastguard Worker RINOK(_item.ReadFooter2(stream))
625*f6dc9357SAndroid Build Coastguard Worker _stream = stream;
626*f6dc9357SAndroid Build Coastguard Worker _isArc = true;
627*f6dc9357SAndroid Build Coastguard Worker _needSeekToStart = true;
628*f6dc9357SAndroid Build Coastguard Worker return S_OK;
629*f6dc9357SAndroid Build Coastguard Worker COM_TRY_END
630*f6dc9357SAndroid Build Coastguard Worker }
631*f6dc9357SAndroid Build Coastguard Worker
632*f6dc9357SAndroid Build Coastguard Worker Z7_COM7F_IMF(CHandler::OpenSeq(ISequentialInStream *stream))
633*f6dc9357SAndroid Build Coastguard Worker {
634*f6dc9357SAndroid Build Coastguard Worker COM_TRY_BEGIN
635*f6dc9357SAndroid Build Coastguard Worker try
636*f6dc9357SAndroid Build Coastguard Worker {
637*f6dc9357SAndroid Build Coastguard Worker Close();
638*f6dc9357SAndroid Build Coastguard Worker CreateDecoder();
639*f6dc9357SAndroid Build Coastguard Worker _decoder->SetInStream(stream);
640*f6dc9357SAndroid Build Coastguard Worker _decoder->InitInStream(true);
641*f6dc9357SAndroid Build Coastguard Worker RINOK(_item.ReadHeader(_decoder.ClsPtr()))
642*f6dc9357SAndroid Build Coastguard Worker if (_decoder->InputEofError())
643*f6dc9357SAndroid Build Coastguard Worker return S_FALSE;
644*f6dc9357SAndroid Build Coastguard Worker _headerSize = _decoder->GetInputProcessedSize();
645*f6dc9357SAndroid Build Coastguard Worker _isArc = true;
646*f6dc9357SAndroid Build Coastguard Worker return S_OK;
647*f6dc9357SAndroid Build Coastguard Worker }
648*f6dc9357SAndroid Build Coastguard Worker catch(const CInBufferException &e) { return e.ErrorCode; }
649*f6dc9357SAndroid Build Coastguard Worker COM_TRY_END
650*f6dc9357SAndroid Build Coastguard Worker }
651*f6dc9357SAndroid Build Coastguard Worker
652*f6dc9357SAndroid Build Coastguard Worker Z7_COM7F_IMF(CHandler::Close())
653*f6dc9357SAndroid Build Coastguard Worker {
654*f6dc9357SAndroid Build Coastguard Worker _isArc = false;
655*f6dc9357SAndroid Build Coastguard Worker _needSeekToStart = false;
656*f6dc9357SAndroid Build Coastguard Worker _dataAfterEnd = false;
657*f6dc9357SAndroid Build Coastguard Worker _needMoreInput = false;
658*f6dc9357SAndroid Build Coastguard Worker
659*f6dc9357SAndroid Build Coastguard Worker _packSize_Defined = false;
660*f6dc9357SAndroid Build Coastguard Worker _unpackSize_Defined = false;
661*f6dc9357SAndroid Build Coastguard Worker _numStreams_Defined = false;
662*f6dc9357SAndroid Build Coastguard Worker
663*f6dc9357SAndroid Build Coastguard Worker _packSize = 0;
664*f6dc9357SAndroid Build Coastguard Worker _headerSize = 0;
665*f6dc9357SAndroid Build Coastguard Worker
666*f6dc9357SAndroid Build Coastguard Worker _stream.Release();
667*f6dc9357SAndroid Build Coastguard Worker if (_decoder)
668*f6dc9357SAndroid Build Coastguard Worker _decoder->ReleaseInStream();
669*f6dc9357SAndroid Build Coastguard Worker return S_OK;
670*f6dc9357SAndroid Build Coastguard Worker }
671*f6dc9357SAndroid Build Coastguard Worker
672*f6dc9357SAndroid Build Coastguard Worker Z7_COM7F_IMF(CHandler::Extract(const UInt32 *indices, UInt32 numItems,
673*f6dc9357SAndroid Build Coastguard Worker Int32 testMode, IArchiveExtractCallback *extractCallback))
674*f6dc9357SAndroid Build Coastguard Worker {
675*f6dc9357SAndroid Build Coastguard Worker COM_TRY_BEGIN
676*f6dc9357SAndroid Build Coastguard Worker if (numItems == 0)
677*f6dc9357SAndroid Build Coastguard Worker return S_OK;
678*f6dc9357SAndroid Build Coastguard Worker if (numItems != (UInt32)(Int32)-1 && (numItems != 1 || indices[0] != 0))
679*f6dc9357SAndroid Build Coastguard Worker return E_INVALIDARG;
680*f6dc9357SAndroid Build Coastguard Worker
681*f6dc9357SAndroid Build Coastguard Worker if (_packSize_Defined)
682*f6dc9357SAndroid Build Coastguard Worker RINOK(extractCallback->SetTotal(_packSize))
683*f6dc9357SAndroid Build Coastguard Worker // UInt64 currentTotalPacked = 0;
684*f6dc9357SAndroid Build Coastguard Worker // RINOK(extractCallback->SetCompleted(¤tTotalPacked));
685*f6dc9357SAndroid Build Coastguard Worker Int32 retResult;
686*f6dc9357SAndroid Build Coastguard Worker {
687*f6dc9357SAndroid Build Coastguard Worker CMyComPtr<ISequentialOutStream> realOutStream;
688*f6dc9357SAndroid Build Coastguard Worker const Int32 askMode = testMode ?
689*f6dc9357SAndroid Build Coastguard Worker NExtract::NAskMode::kTest :
690*f6dc9357SAndroid Build Coastguard Worker NExtract::NAskMode::kExtract;
691*f6dc9357SAndroid Build Coastguard Worker RINOK(extractCallback->GetStream(0, &realOutStream, askMode))
692*f6dc9357SAndroid Build Coastguard Worker if (!testMode && !realOutStream)
693*f6dc9357SAndroid Build Coastguard Worker return S_OK;
694*f6dc9357SAndroid Build Coastguard Worker
695*f6dc9357SAndroid Build Coastguard Worker RINOK(extractCallback->PrepareOperation(askMode))
696*f6dc9357SAndroid Build Coastguard Worker
697*f6dc9357SAndroid Build Coastguard Worker CreateDecoder();
698*f6dc9357SAndroid Build Coastguard Worker
699*f6dc9357SAndroid Build Coastguard Worker CMyComPtr2_Create<ISequentialOutStream, COutStreamWithCRC> outStream;
700*f6dc9357SAndroid Build Coastguard Worker outStream->SetStream(realOutStream);
701*f6dc9357SAndroid Build Coastguard Worker outStream->Init();
702*f6dc9357SAndroid Build Coastguard Worker // realOutStream.Release();
703*f6dc9357SAndroid Build Coastguard Worker
704*f6dc9357SAndroid Build Coastguard Worker CMyComPtr2_Create<ICompressProgressInfo, CLocalProgress> lps;
705*f6dc9357SAndroid Build Coastguard Worker lps->Init(extractCallback, true);
706*f6dc9357SAndroid Build Coastguard Worker
707*f6dc9357SAndroid Build Coastguard Worker bool needReadFirstItem = _needSeekToStart;
708*f6dc9357SAndroid Build Coastguard Worker
709*f6dc9357SAndroid Build Coastguard Worker if (_needSeekToStart)
710*f6dc9357SAndroid Build Coastguard Worker {
711*f6dc9357SAndroid Build Coastguard Worker if (!_stream)
712*f6dc9357SAndroid Build Coastguard Worker return E_FAIL;
713*f6dc9357SAndroid Build Coastguard Worker RINOK(InStream_SeekToBegin(_stream))
714*f6dc9357SAndroid Build Coastguard Worker _decoder->InitInStream(true);
715*f6dc9357SAndroid Build Coastguard Worker // printf("\nSeek");
716*f6dc9357SAndroid Build Coastguard Worker }
717*f6dc9357SAndroid Build Coastguard Worker else
718*f6dc9357SAndroid Build Coastguard Worker _needSeekToStart = true;
719*f6dc9357SAndroid Build Coastguard Worker
720*f6dc9357SAndroid Build Coastguard Worker bool firstItem = true;
721*f6dc9357SAndroid Build Coastguard Worker
722*f6dc9357SAndroid Build Coastguard Worker UInt64 packSize = _decoder->GetInputProcessedSize();
723*f6dc9357SAndroid Build Coastguard Worker // printf("\npackSize = %d", (unsigned)packSize);
724*f6dc9357SAndroid Build Coastguard Worker
725*f6dc9357SAndroid Build Coastguard Worker UInt64 unpackedSize = 0;
726*f6dc9357SAndroid Build Coastguard Worker UInt64 numStreams = 0;
727*f6dc9357SAndroid Build Coastguard Worker
728*f6dc9357SAndroid Build Coastguard Worker bool crcError = false;
729*f6dc9357SAndroid Build Coastguard Worker
730*f6dc9357SAndroid Build Coastguard Worker HRESULT result = S_OK;
731*f6dc9357SAndroid Build Coastguard Worker
732*f6dc9357SAndroid Build Coastguard Worker try {
733*f6dc9357SAndroid Build Coastguard Worker
734*f6dc9357SAndroid Build Coastguard Worker for (;;)
735*f6dc9357SAndroid Build Coastguard Worker {
736*f6dc9357SAndroid Build Coastguard Worker lps->InSize = packSize;
737*f6dc9357SAndroid Build Coastguard Worker lps->OutSize = unpackedSize;
738*f6dc9357SAndroid Build Coastguard Worker
739*f6dc9357SAndroid Build Coastguard Worker RINOK(lps->SetCur())
740*f6dc9357SAndroid Build Coastguard Worker
741*f6dc9357SAndroid Build Coastguard Worker CItem item;
742*f6dc9357SAndroid Build Coastguard Worker
743*f6dc9357SAndroid Build Coastguard Worker if (!firstItem || needReadFirstItem)
744*f6dc9357SAndroid Build Coastguard Worker {
745*f6dc9357SAndroid Build Coastguard Worker result = item.ReadHeader(_decoder.ClsPtr());
746*f6dc9357SAndroid Build Coastguard Worker
747*f6dc9357SAndroid Build Coastguard Worker if (result != S_OK && result != S_FALSE)
748*f6dc9357SAndroid Build Coastguard Worker return result;
749*f6dc9357SAndroid Build Coastguard Worker
750*f6dc9357SAndroid Build Coastguard Worker if (_decoder->InputEofError())
751*f6dc9357SAndroid Build Coastguard Worker result = S_FALSE;
752*f6dc9357SAndroid Build Coastguard Worker
753*f6dc9357SAndroid Build Coastguard Worker if (result != S_OK && firstItem)
754*f6dc9357SAndroid Build Coastguard Worker {
755*f6dc9357SAndroid Build Coastguard Worker _isArc = false;
756*f6dc9357SAndroid Build Coastguard Worker break;
757*f6dc9357SAndroid Build Coastguard Worker }
758*f6dc9357SAndroid Build Coastguard Worker
759*f6dc9357SAndroid Build Coastguard Worker if (packSize == _decoder->GetStreamSize())
760*f6dc9357SAndroid Build Coastguard Worker {
761*f6dc9357SAndroid Build Coastguard Worker result = S_OK;
762*f6dc9357SAndroid Build Coastguard Worker break;
763*f6dc9357SAndroid Build Coastguard Worker }
764*f6dc9357SAndroid Build Coastguard Worker
765*f6dc9357SAndroid Build Coastguard Worker if (result != S_OK)
766*f6dc9357SAndroid Build Coastguard Worker {
767*f6dc9357SAndroid Build Coastguard Worker _dataAfterEnd = true;
768*f6dc9357SAndroid Build Coastguard Worker break;
769*f6dc9357SAndroid Build Coastguard Worker }
770*f6dc9357SAndroid Build Coastguard Worker }
771*f6dc9357SAndroid Build Coastguard Worker
772*f6dc9357SAndroid Build Coastguard Worker numStreams++;
773*f6dc9357SAndroid Build Coastguard Worker firstItem = false;
774*f6dc9357SAndroid Build Coastguard Worker
775*f6dc9357SAndroid Build Coastguard Worker const UInt64 startOffset = outStream->GetSize();
776*f6dc9357SAndroid Build Coastguard Worker outStream->InitCRC();
777*f6dc9357SAndroid Build Coastguard Worker
778*f6dc9357SAndroid Build Coastguard Worker result = _decoder->CodeResume(outStream, NULL, lps);
779*f6dc9357SAndroid Build Coastguard Worker
780*f6dc9357SAndroid Build Coastguard Worker packSize = _decoder->GetInputProcessedSize();
781*f6dc9357SAndroid Build Coastguard Worker unpackedSize = outStream->GetSize();
782*f6dc9357SAndroid Build Coastguard Worker
783*f6dc9357SAndroid Build Coastguard Worker if (result != S_OK && result != S_FALSE)
784*f6dc9357SAndroid Build Coastguard Worker return result;
785*f6dc9357SAndroid Build Coastguard Worker
786*f6dc9357SAndroid Build Coastguard Worker if (_decoder->InputEofError())
787*f6dc9357SAndroid Build Coastguard Worker {
788*f6dc9357SAndroid Build Coastguard Worker packSize = _decoder->GetStreamSize();
789*f6dc9357SAndroid Build Coastguard Worker _needMoreInput = true;
790*f6dc9357SAndroid Build Coastguard Worker result = S_FALSE;
791*f6dc9357SAndroid Build Coastguard Worker }
792*f6dc9357SAndroid Build Coastguard Worker
793*f6dc9357SAndroid Build Coastguard Worker if (result != S_OK)
794*f6dc9357SAndroid Build Coastguard Worker break;
795*f6dc9357SAndroid Build Coastguard Worker
796*f6dc9357SAndroid Build Coastguard Worker _decoder->AlignToByte();
797*f6dc9357SAndroid Build Coastguard Worker
798*f6dc9357SAndroid Build Coastguard Worker result = item.ReadFooter1(_decoder.ClsPtr());
799*f6dc9357SAndroid Build Coastguard Worker
800*f6dc9357SAndroid Build Coastguard Worker packSize = _decoder->GetInputProcessedSize();
801*f6dc9357SAndroid Build Coastguard Worker
802*f6dc9357SAndroid Build Coastguard Worker if (result != S_OK && result != S_FALSE)
803*f6dc9357SAndroid Build Coastguard Worker return result;
804*f6dc9357SAndroid Build Coastguard Worker
805*f6dc9357SAndroid Build Coastguard Worker if (result != S_OK)
806*f6dc9357SAndroid Build Coastguard Worker {
807*f6dc9357SAndroid Build Coastguard Worker if (_decoder->InputEofError())
808*f6dc9357SAndroid Build Coastguard Worker {
809*f6dc9357SAndroid Build Coastguard Worker _needMoreInput = true;
810*f6dc9357SAndroid Build Coastguard Worker result = S_FALSE;
811*f6dc9357SAndroid Build Coastguard Worker }
812*f6dc9357SAndroid Build Coastguard Worker break;
813*f6dc9357SAndroid Build Coastguard Worker }
814*f6dc9357SAndroid Build Coastguard Worker
815*f6dc9357SAndroid Build Coastguard Worker if (item.Crc != outStream->GetCRC() ||
816*f6dc9357SAndroid Build Coastguard Worker item.Size32 != (UInt32)(unpackedSize - startOffset))
817*f6dc9357SAndroid Build Coastguard Worker {
818*f6dc9357SAndroid Build Coastguard Worker crcError = true;
819*f6dc9357SAndroid Build Coastguard Worker result = S_FALSE;
820*f6dc9357SAndroid Build Coastguard Worker break;
821*f6dc9357SAndroid Build Coastguard Worker }
822*f6dc9357SAndroid Build Coastguard Worker
823*f6dc9357SAndroid Build Coastguard Worker // break; // we can use break, if we need only first stream
824*f6dc9357SAndroid Build Coastguard Worker }
825*f6dc9357SAndroid Build Coastguard Worker
826*f6dc9357SAndroid Build Coastguard Worker } catch(const CInBufferException &e) { return e.ErrorCode; }
827*f6dc9357SAndroid Build Coastguard Worker
828*f6dc9357SAndroid Build Coastguard Worker if (!firstItem)
829*f6dc9357SAndroid Build Coastguard Worker {
830*f6dc9357SAndroid Build Coastguard Worker _packSize = packSize;
831*f6dc9357SAndroid Build Coastguard Worker _unpackSize = unpackedSize;
832*f6dc9357SAndroid Build Coastguard Worker _numStreams = numStreams;
833*f6dc9357SAndroid Build Coastguard Worker
834*f6dc9357SAndroid Build Coastguard Worker _packSize_Defined = true;
835*f6dc9357SAndroid Build Coastguard Worker _unpackSize_Defined = true;
836*f6dc9357SAndroid Build Coastguard Worker _numStreams_Defined = true;
837*f6dc9357SAndroid Build Coastguard Worker }
838*f6dc9357SAndroid Build Coastguard Worker
839*f6dc9357SAndroid Build Coastguard Worker // outStream.Release();
840*f6dc9357SAndroid Build Coastguard Worker
841*f6dc9357SAndroid Build Coastguard Worker retResult = NExtract::NOperationResult::kDataError;
842*f6dc9357SAndroid Build Coastguard Worker
843*f6dc9357SAndroid Build Coastguard Worker if (!_isArc)
844*f6dc9357SAndroid Build Coastguard Worker retResult = NExtract::NOperationResult::kIsNotArc;
845*f6dc9357SAndroid Build Coastguard Worker else if (_needMoreInput)
846*f6dc9357SAndroid Build Coastguard Worker retResult = NExtract::NOperationResult::kUnexpectedEnd;
847*f6dc9357SAndroid Build Coastguard Worker else if (crcError)
848*f6dc9357SAndroid Build Coastguard Worker retResult = NExtract::NOperationResult::kCRCError;
849*f6dc9357SAndroid Build Coastguard Worker else if (_dataAfterEnd)
850*f6dc9357SAndroid Build Coastguard Worker retResult = NExtract::NOperationResult::kDataAfterEnd;
851*f6dc9357SAndroid Build Coastguard Worker else if (result == S_FALSE)
852*f6dc9357SAndroid Build Coastguard Worker retResult = NExtract::NOperationResult::kDataError;
853*f6dc9357SAndroid Build Coastguard Worker else if (result == S_OK)
854*f6dc9357SAndroid Build Coastguard Worker retResult = NExtract::NOperationResult::kOK;
855*f6dc9357SAndroid Build Coastguard Worker else
856*f6dc9357SAndroid Build Coastguard Worker return result;
857*f6dc9357SAndroid Build Coastguard Worker }
858*f6dc9357SAndroid Build Coastguard Worker
859*f6dc9357SAndroid Build Coastguard Worker return extractCallback->SetOperationResult(retResult);
860*f6dc9357SAndroid Build Coastguard Worker COM_TRY_END
861*f6dc9357SAndroid Build Coastguard Worker }
862*f6dc9357SAndroid Build Coastguard Worker
863*f6dc9357SAndroid Build Coastguard Worker static const Byte kHostOS =
864*f6dc9357SAndroid Build Coastguard Worker #ifdef _WIN32
865*f6dc9357SAndroid Build Coastguard Worker NHostOS::kFAT;
866*f6dc9357SAndroid Build Coastguard Worker #else
867*f6dc9357SAndroid Build Coastguard Worker NHostOS::kUnix;
868*f6dc9357SAndroid Build Coastguard Worker #endif
869*f6dc9357SAndroid Build Coastguard Worker
870*f6dc9357SAndroid Build Coastguard Worker
871*f6dc9357SAndroid Build Coastguard Worker /*
872*f6dc9357SAndroid Build Coastguard Worker static HRESULT ReportItemProp(IArchiveUpdateCallbackArcProp *reportArcProp, PROPID propID, const PROPVARIANT *value)
873*f6dc9357SAndroid Build Coastguard Worker {
874*f6dc9357SAndroid Build Coastguard Worker return reportArcProp->ReportProp(NEventIndexType::kOutArcIndex, 0, propID, value);
875*f6dc9357SAndroid Build Coastguard Worker }
876*f6dc9357SAndroid Build Coastguard Worker
877*f6dc9357SAndroid Build Coastguard Worker static HRESULT ReportArcProp(IArchiveUpdateCallbackArcProp *reportArcProp, PROPID propID, const PROPVARIANT *value)
878*f6dc9357SAndroid Build Coastguard Worker {
879*f6dc9357SAndroid Build Coastguard Worker return reportArcProp->ReportProp(NEventIndexType::kArcProp, 0, propID, value);
880*f6dc9357SAndroid Build Coastguard Worker }
881*f6dc9357SAndroid Build Coastguard Worker
882*f6dc9357SAndroid Build Coastguard Worker static HRESULT ReportArcProps(IArchiveUpdateCallbackArcProp *reportArcProp,
883*f6dc9357SAndroid Build Coastguard Worker const CItem &item,
884*f6dc9357SAndroid Build Coastguard Worker bool needTime,
885*f6dc9357SAndroid Build Coastguard Worker bool needCrc,
886*f6dc9357SAndroid Build Coastguard Worker const UInt64 *unpackSize)
887*f6dc9357SAndroid Build Coastguard Worker {
888*f6dc9357SAndroid Build Coastguard Worker NCOM::CPropVariant timeProp;
889*f6dc9357SAndroid Build Coastguard Worker NCOM::CPropVariant sizeProp;
890*f6dc9357SAndroid Build Coastguard Worker if (needTime)
891*f6dc9357SAndroid Build Coastguard Worker {
892*f6dc9357SAndroid Build Coastguard Worker FILETIME ft;
893*f6dc9357SAndroid Build Coastguard Worker NTime::UnixTimeToFileTime(item.Time, ft);
894*f6dc9357SAndroid Build Coastguard Worker timeProp.SetAsTimeFrom_FT_Prec(ft, k_PropVar_TimePrec_Unix);
895*f6dc9357SAndroid Build Coastguard Worker }
896*f6dc9357SAndroid Build Coastguard Worker if (unpackSize)
897*f6dc9357SAndroid Build Coastguard Worker {
898*f6dc9357SAndroid Build Coastguard Worker sizeProp = *unpackSize;
899*f6dc9357SAndroid Build Coastguard Worker RINOK(ReportItemProp(reportArcProp, kpidSize, &sizeProp));
900*f6dc9357SAndroid Build Coastguard Worker }
901*f6dc9357SAndroid Build Coastguard Worker if (needCrc)
902*f6dc9357SAndroid Build Coastguard Worker {
903*f6dc9357SAndroid Build Coastguard Worker NCOM::CPropVariant prop;
904*f6dc9357SAndroid Build Coastguard Worker prop = item.Crc;
905*f6dc9357SAndroid Build Coastguard Worker RINOK(ReportItemProp(reportArcProp, kpidCRC, &prop));
906*f6dc9357SAndroid Build Coastguard Worker }
907*f6dc9357SAndroid Build Coastguard Worker {
908*f6dc9357SAndroid Build Coastguard Worker RINOK(ReportItemProp(reportArcProp, kpidMTime, &timeProp));
909*f6dc9357SAndroid Build Coastguard Worker }
910*f6dc9357SAndroid Build Coastguard Worker
911*f6dc9357SAndroid Build Coastguard Worker RINOK(reportArcProp->ReportFinished(NEventIndexType::kOutArcIndex, 0, NArchive::NUpdate::NOperationResult::kOK));
912*f6dc9357SAndroid Build Coastguard Worker
913*f6dc9357SAndroid Build Coastguard Worker if (unpackSize)
914*f6dc9357SAndroid Build Coastguard Worker {
915*f6dc9357SAndroid Build Coastguard Worker RINOK(ReportArcProp(reportArcProp, kpidSize, &sizeProp));
916*f6dc9357SAndroid Build Coastguard Worker }
917*f6dc9357SAndroid Build Coastguard Worker {
918*f6dc9357SAndroid Build Coastguard Worker RINOK(ReportArcProp(reportArcProp, kpidComboMTime, &timeProp));
919*f6dc9357SAndroid Build Coastguard Worker }
920*f6dc9357SAndroid Build Coastguard Worker return S_OK;
921*f6dc9357SAndroid Build Coastguard Worker }
922*f6dc9357SAndroid Build Coastguard Worker */
923*f6dc9357SAndroid Build Coastguard Worker
924*f6dc9357SAndroid Build Coastguard Worker static HRESULT UpdateArchive(
925*f6dc9357SAndroid Build Coastguard Worker ISequentialOutStream *outStream,
926*f6dc9357SAndroid Build Coastguard Worker UInt64 unpackSize,
927*f6dc9357SAndroid Build Coastguard Worker CItem &item,
928*f6dc9357SAndroid Build Coastguard Worker const CSingleMethodProps &props,
929*f6dc9357SAndroid Build Coastguard Worker const CHandlerTimeOptions &timeOptions,
930*f6dc9357SAndroid Build Coastguard Worker IArchiveUpdateCallback *updateCallback
931*f6dc9357SAndroid Build Coastguard Worker // , IArchiveUpdateCallbackArcProp *reportArcProp
932*f6dc9357SAndroid Build Coastguard Worker )
933*f6dc9357SAndroid Build Coastguard Worker {
934*f6dc9357SAndroid Build Coastguard Worker UInt64 unpackSizeReal;
935*f6dc9357SAndroid Build Coastguard Worker {
936*f6dc9357SAndroid Build Coastguard Worker CMyComPtr<ISequentialInStream> fileInStream;
937*f6dc9357SAndroid Build Coastguard Worker
938*f6dc9357SAndroid Build Coastguard Worker RINOK(updateCallback->GetStream(0, &fileInStream))
939*f6dc9357SAndroid Build Coastguard Worker
940*f6dc9357SAndroid Build Coastguard Worker if (!fileInStream)
941*f6dc9357SAndroid Build Coastguard Worker return S_FALSE;
942*f6dc9357SAndroid Build Coastguard Worker
943*f6dc9357SAndroid Build Coastguard Worker {
944*f6dc9357SAndroid Build Coastguard Worker Z7_DECL_CMyComPtr_QI_FROM(
945*f6dc9357SAndroid Build Coastguard Worker IStreamGetProps,
946*f6dc9357SAndroid Build Coastguard Worker getProps, fileInStream)
947*f6dc9357SAndroid Build Coastguard Worker if (getProps)
948*f6dc9357SAndroid Build Coastguard Worker {
949*f6dc9357SAndroid Build Coastguard Worker FILETIME mTime;
950*f6dc9357SAndroid Build Coastguard Worker UInt64 size;
951*f6dc9357SAndroid Build Coastguard Worker if (getProps->GetProps(&size, NULL, NULL, &mTime, NULL) == S_OK)
952*f6dc9357SAndroid Build Coastguard Worker {
953*f6dc9357SAndroid Build Coastguard Worker unpackSize = size;
954*f6dc9357SAndroid Build Coastguard Worker if (timeOptions.Write_MTime.Val)
955*f6dc9357SAndroid Build Coastguard Worker NTime::FileTime_To_UnixTime(mTime, item.Time);
956*f6dc9357SAndroid Build Coastguard Worker }
957*f6dc9357SAndroid Build Coastguard Worker }
958*f6dc9357SAndroid Build Coastguard Worker }
959*f6dc9357SAndroid Build Coastguard Worker
960*f6dc9357SAndroid Build Coastguard Worker UInt64 complexity = 0;
961*f6dc9357SAndroid Build Coastguard Worker RINOK(updateCallback->SetTotal(unpackSize))
962*f6dc9357SAndroid Build Coastguard Worker RINOK(updateCallback->SetCompleted(&complexity))
963*f6dc9357SAndroid Build Coastguard Worker
964*f6dc9357SAndroid Build Coastguard Worker CMyComPtr2_Create<ISequentialInStream, CSequentialInStreamWithCRC> crcStream;
965*f6dc9357SAndroid Build Coastguard Worker crcStream->SetStream(fileInStream);
966*f6dc9357SAndroid Build Coastguard Worker crcStream->Init();
967*f6dc9357SAndroid Build Coastguard Worker
968*f6dc9357SAndroid Build Coastguard Worker CMyComPtr2_Create<ICompressProgressInfo, CLocalProgress> lps;
969*f6dc9357SAndroid Build Coastguard Worker lps->Init(updateCallback, true);
970*f6dc9357SAndroid Build Coastguard Worker
971*f6dc9357SAndroid Build Coastguard Worker item.ExtraFlags = props.GetLevel() >= 7 ?
972*f6dc9357SAndroid Build Coastguard Worker NExtraFlags::kMaximum :
973*f6dc9357SAndroid Build Coastguard Worker NExtraFlags::kFastest;
974*f6dc9357SAndroid Build Coastguard Worker
975*f6dc9357SAndroid Build Coastguard Worker item.HostOS = kHostOS;
976*f6dc9357SAndroid Build Coastguard Worker
977*f6dc9357SAndroid Build Coastguard Worker RINOK(item.WriteHeader(outStream))
978*f6dc9357SAndroid Build Coastguard Worker
979*f6dc9357SAndroid Build Coastguard Worker CMyComPtr2_Create<ICompressCoder, NEncoder::CCOMCoder> deflateEncoder;
980*f6dc9357SAndroid Build Coastguard Worker
981*f6dc9357SAndroid Build Coastguard Worker RINOK(props.SetCoderProps(deflateEncoder.ClsPtr(), NULL))
982*f6dc9357SAndroid Build Coastguard Worker RINOK(deflateEncoder.Interface()->Code(crcStream, outStream, NULL, NULL, lps))
983*f6dc9357SAndroid Build Coastguard Worker
984*f6dc9357SAndroid Build Coastguard Worker item.Crc = crcStream->GetCRC();
985*f6dc9357SAndroid Build Coastguard Worker unpackSizeReal = crcStream->GetSize();
986*f6dc9357SAndroid Build Coastguard Worker item.Size32 = (UInt32)unpackSizeReal;
987*f6dc9357SAndroid Build Coastguard Worker RINOK(item.WriteFooter(outStream))
988*f6dc9357SAndroid Build Coastguard Worker }
989*f6dc9357SAndroid Build Coastguard Worker /*
990*f6dc9357SAndroid Build Coastguard Worker if (reportArcProp)
991*f6dc9357SAndroid Build Coastguard Worker {
992*f6dc9357SAndroid Build Coastguard Worker RINOK(ReportArcProps(reportArcProp,
993*f6dc9357SAndroid Build Coastguard Worker item,
994*f6dc9357SAndroid Build Coastguard Worker props._Write_MTime, // item.Time != 0,
995*f6dc9357SAndroid Build Coastguard Worker true, // writeCrc
996*f6dc9357SAndroid Build Coastguard Worker &unpackSizeReal));
997*f6dc9357SAndroid Build Coastguard Worker }
998*f6dc9357SAndroid Build Coastguard Worker */
999*f6dc9357SAndroid Build Coastguard Worker return updateCallback->SetOperationResult(NUpdate::NOperationResult::kOK);
1000*f6dc9357SAndroid Build Coastguard Worker }
1001*f6dc9357SAndroid Build Coastguard Worker
1002*f6dc9357SAndroid Build Coastguard Worker
1003*f6dc9357SAndroid Build Coastguard Worker Z7_COM7F_IMF(CHandler::GetFileTimeType(UInt32 *timeType))
1004*f6dc9357SAndroid Build Coastguard Worker {
1005*f6dc9357SAndroid Build Coastguard Worker /*
1006*f6dc9357SAndroid Build Coastguard Worker if (_item.Time != 0)
1007*f6dc9357SAndroid Build Coastguard Worker {
1008*f6dc9357SAndroid Build Coastguard Worker we set NFileTimeType::kUnix in precision,
1009*f6dc9357SAndroid Build Coastguard Worker and we return NFileTimeType::kUnix in kpidTimeType
1010*f6dc9357SAndroid Build Coastguard Worker so GetFileTimeType() value is not used in any version of 7-zip.
1011*f6dc9357SAndroid Build Coastguard Worker }
1012*f6dc9357SAndroid Build Coastguard Worker else // (_item.Time == 0)
1013*f6dc9357SAndroid Build Coastguard Worker {
1014*f6dc9357SAndroid Build Coastguard Worker kpidMTime and kpidTimeType are not defined
1015*f6dc9357SAndroid Build Coastguard Worker before 22.00 : GetFileTimeType() value is used in GetUpdatePairInfoList();
1016*f6dc9357SAndroid Build Coastguard Worker 22.00 : GetFileTimeType() value is not used
1017*f6dc9357SAndroid Build Coastguard Worker }
1018*f6dc9357SAndroid Build Coastguard Worker */
1019*f6dc9357SAndroid Build Coastguard Worker
1020*f6dc9357SAndroid Build Coastguard Worker UInt32 t;
1021*f6dc9357SAndroid Build Coastguard Worker t = NFileTimeType::kUnix;
1022*f6dc9357SAndroid Build Coastguard Worker if (_isArc ? (_item.Time == 0) : !_timeOptions.Write_MTime.Val)
1023*f6dc9357SAndroid Build Coastguard Worker {
1024*f6dc9357SAndroid Build Coastguard Worker t = GET_FileTimeType_NotDefined_for_GetFileTimeType;
1025*f6dc9357SAndroid Build Coastguard Worker // t = k_PropVar_TimePrec_1ns; // failed in 7-Zip 21
1026*f6dc9357SAndroid Build Coastguard Worker // t = (UInt32)(Int32)NFileTimeType::kNotDefined; // failed in 7-Zip 21
1027*f6dc9357SAndroid Build Coastguard Worker }
1028*f6dc9357SAndroid Build Coastguard Worker *timeType = t;
1029*f6dc9357SAndroid Build Coastguard Worker return S_OK;
1030*f6dc9357SAndroid Build Coastguard Worker }
1031*f6dc9357SAndroid Build Coastguard Worker
1032*f6dc9357SAndroid Build Coastguard Worker Z7_COM7F_IMF(CHandler::UpdateItems(ISequentialOutStream *outStream, UInt32 numItems,
1033*f6dc9357SAndroid Build Coastguard Worker IArchiveUpdateCallback *updateCallback))
1034*f6dc9357SAndroid Build Coastguard Worker {
1035*f6dc9357SAndroid Build Coastguard Worker COM_TRY_BEGIN
1036*f6dc9357SAndroid Build Coastguard Worker
1037*f6dc9357SAndroid Build Coastguard Worker if (numItems != 1)
1038*f6dc9357SAndroid Build Coastguard Worker return E_INVALIDARG;
1039*f6dc9357SAndroid Build Coastguard Worker
1040*f6dc9357SAndroid Build Coastguard Worker {
1041*f6dc9357SAndroid Build Coastguard Worker Z7_DECL_CMyComPtr_QI_FROM(
1042*f6dc9357SAndroid Build Coastguard Worker IStreamSetRestriction,
1043*f6dc9357SAndroid Build Coastguard Worker setRestriction, outStream)
1044*f6dc9357SAndroid Build Coastguard Worker if (setRestriction)
1045*f6dc9357SAndroid Build Coastguard Worker RINOK(setRestriction->SetRestriction(0, 0))
1046*f6dc9357SAndroid Build Coastguard Worker }
1047*f6dc9357SAndroid Build Coastguard Worker
1048*f6dc9357SAndroid Build Coastguard Worker Int32 newData, newProps;
1049*f6dc9357SAndroid Build Coastguard Worker UInt32 indexInArchive;
1050*f6dc9357SAndroid Build Coastguard Worker if (!updateCallback)
1051*f6dc9357SAndroid Build Coastguard Worker return E_FAIL;
1052*f6dc9357SAndroid Build Coastguard Worker RINOK(updateCallback->GetUpdateItemInfo(0, &newData, &newProps, &indexInArchive))
1053*f6dc9357SAndroid Build Coastguard Worker
1054*f6dc9357SAndroid Build Coastguard Worker // Z7_DECL_CMyComPtr_QI_FROM(IArchiveUpdateCallbackArcProp, reportArcProp, updateCallback)
1055*f6dc9357SAndroid Build Coastguard Worker
1056*f6dc9357SAndroid Build Coastguard Worker CItem newItem;
1057*f6dc9357SAndroid Build Coastguard Worker
1058*f6dc9357SAndroid Build Coastguard Worker if (!IntToBool(newProps))
1059*f6dc9357SAndroid Build Coastguard Worker {
1060*f6dc9357SAndroid Build Coastguard Worker newItem.CopyMetaPropsFrom(_item);
1061*f6dc9357SAndroid Build Coastguard Worker }
1062*f6dc9357SAndroid Build Coastguard Worker else
1063*f6dc9357SAndroid Build Coastguard Worker {
1064*f6dc9357SAndroid Build Coastguard Worker newItem.HostOS = kHostOS;
1065*f6dc9357SAndroid Build Coastguard Worker if (_timeOptions.Write_MTime.Val)
1066*f6dc9357SAndroid Build Coastguard Worker {
1067*f6dc9357SAndroid Build Coastguard Worker NCOM::CPropVariant prop;
1068*f6dc9357SAndroid Build Coastguard Worker RINOK(updateCallback->GetProperty(0, kpidMTime, &prop))
1069*f6dc9357SAndroid Build Coastguard Worker if (prop.vt == VT_FILETIME)
1070*f6dc9357SAndroid Build Coastguard Worker NTime::FileTime_To_UnixTime(prop.filetime, newItem.Time);
1071*f6dc9357SAndroid Build Coastguard Worker else if (prop.vt == VT_EMPTY)
1072*f6dc9357SAndroid Build Coastguard Worker newItem.Time = 0;
1073*f6dc9357SAndroid Build Coastguard Worker else
1074*f6dc9357SAndroid Build Coastguard Worker return E_INVALIDARG;
1075*f6dc9357SAndroid Build Coastguard Worker }
1076*f6dc9357SAndroid Build Coastguard Worker {
1077*f6dc9357SAndroid Build Coastguard Worker NCOM::CPropVariant prop;
1078*f6dc9357SAndroid Build Coastguard Worker RINOK(updateCallback->GetProperty(0, kpidPath, &prop))
1079*f6dc9357SAndroid Build Coastguard Worker if (prop.vt == VT_BSTR)
1080*f6dc9357SAndroid Build Coastguard Worker {
1081*f6dc9357SAndroid Build Coastguard Worker UString name = prop.bstrVal;
1082*f6dc9357SAndroid Build Coastguard Worker int slashPos = name.ReverseFind_PathSepar();
1083*f6dc9357SAndroid Build Coastguard Worker if (slashPos >= 0)
1084*f6dc9357SAndroid Build Coastguard Worker name.DeleteFrontal((unsigned)(slashPos + 1));
1085*f6dc9357SAndroid Build Coastguard Worker newItem.Name = UnicodeStringToMultiByte(name, CP_ACP);
1086*f6dc9357SAndroid Build Coastguard Worker if (!newItem.Name.IsEmpty())
1087*f6dc9357SAndroid Build Coastguard Worker newItem.Flags |= NFlags::kName;
1088*f6dc9357SAndroid Build Coastguard Worker }
1089*f6dc9357SAndroid Build Coastguard Worker else if (prop.vt != VT_EMPTY)
1090*f6dc9357SAndroid Build Coastguard Worker return E_INVALIDARG;
1091*f6dc9357SAndroid Build Coastguard Worker }
1092*f6dc9357SAndroid Build Coastguard Worker {
1093*f6dc9357SAndroid Build Coastguard Worker NCOM::CPropVariant prop;
1094*f6dc9357SAndroid Build Coastguard Worker RINOK(updateCallback->GetProperty(0, kpidIsDir, &prop))
1095*f6dc9357SAndroid Build Coastguard Worker if (prop.vt != VT_EMPTY)
1096*f6dc9357SAndroid Build Coastguard Worker if (prop.vt != VT_BOOL || prop.boolVal != VARIANT_FALSE)
1097*f6dc9357SAndroid Build Coastguard Worker return E_INVALIDARG;
1098*f6dc9357SAndroid Build Coastguard Worker }
1099*f6dc9357SAndroid Build Coastguard Worker }
1100*f6dc9357SAndroid Build Coastguard Worker
1101*f6dc9357SAndroid Build Coastguard Worker if (IntToBool(newData))
1102*f6dc9357SAndroid Build Coastguard Worker {
1103*f6dc9357SAndroid Build Coastguard Worker UInt64 size;
1104*f6dc9357SAndroid Build Coastguard Worker {
1105*f6dc9357SAndroid Build Coastguard Worker NCOM::CPropVariant prop;
1106*f6dc9357SAndroid Build Coastguard Worker RINOK(updateCallback->GetProperty(0, kpidSize, &prop))
1107*f6dc9357SAndroid Build Coastguard Worker if (prop.vt != VT_UI8)
1108*f6dc9357SAndroid Build Coastguard Worker return E_INVALIDARG;
1109*f6dc9357SAndroid Build Coastguard Worker size = prop.uhVal.QuadPart;
1110*f6dc9357SAndroid Build Coastguard Worker }
1111*f6dc9357SAndroid Build Coastguard Worker return UpdateArchive(outStream, size, newItem, _props, _timeOptions, updateCallback);
1112*f6dc9357SAndroid Build Coastguard Worker }
1113*f6dc9357SAndroid Build Coastguard Worker
1114*f6dc9357SAndroid Build Coastguard Worker if (indexInArchive != 0)
1115*f6dc9357SAndroid Build Coastguard Worker return E_INVALIDARG;
1116*f6dc9357SAndroid Build Coastguard Worker
1117*f6dc9357SAndroid Build Coastguard Worker if (!_stream)
1118*f6dc9357SAndroid Build Coastguard Worker return E_NOTIMPL;
1119*f6dc9357SAndroid Build Coastguard Worker
1120*f6dc9357SAndroid Build Coastguard Worker CMyComPtr2_Create<ICompressProgressInfo, CLocalProgress> lps;
1121*f6dc9357SAndroid Build Coastguard Worker lps->Init(updateCallback, true);
1122*f6dc9357SAndroid Build Coastguard Worker
1123*f6dc9357SAndroid Build Coastguard Worker Z7_DECL_CMyComPtr_QI_FROM(
1124*f6dc9357SAndroid Build Coastguard Worker IArchiveUpdateCallbackFile,
1125*f6dc9357SAndroid Build Coastguard Worker opCallback, updateCallback)
1126*f6dc9357SAndroid Build Coastguard Worker if (opCallback)
1127*f6dc9357SAndroid Build Coastguard Worker {
1128*f6dc9357SAndroid Build Coastguard Worker RINOK(opCallback->ReportOperation(
1129*f6dc9357SAndroid Build Coastguard Worker NEventIndexType::kInArcIndex, 0,
1130*f6dc9357SAndroid Build Coastguard Worker NUpdateNotifyOp::kReplicate))
1131*f6dc9357SAndroid Build Coastguard Worker }
1132*f6dc9357SAndroid Build Coastguard Worker
1133*f6dc9357SAndroid Build Coastguard Worker newItem.CopyDataPropsFrom(_item);
1134*f6dc9357SAndroid Build Coastguard Worker
1135*f6dc9357SAndroid Build Coastguard Worker UInt64 offset = 0;
1136*f6dc9357SAndroid Build Coastguard Worker if (IntToBool(newProps))
1137*f6dc9357SAndroid Build Coastguard Worker {
1138*f6dc9357SAndroid Build Coastguard Worker newItem.WriteHeader(outStream);
1139*f6dc9357SAndroid Build Coastguard Worker offset += _headerSize;
1140*f6dc9357SAndroid Build Coastguard Worker }
1141*f6dc9357SAndroid Build Coastguard Worker RINOK(InStream_SeekSet(_stream, offset))
1142*f6dc9357SAndroid Build Coastguard Worker
1143*f6dc9357SAndroid Build Coastguard Worker /*
1144*f6dc9357SAndroid Build Coastguard Worker if (reportArcProp)
1145*f6dc9357SAndroid Build Coastguard Worker ReportArcProps(reportArcProp, newItem,
1146*f6dc9357SAndroid Build Coastguard Worker _props._Write_MTime,
1147*f6dc9357SAndroid Build Coastguard Worker false, // writeCrc
1148*f6dc9357SAndroid Build Coastguard Worker NULL); // unpacksize
1149*f6dc9357SAndroid Build Coastguard Worker */
1150*f6dc9357SAndroid Build Coastguard Worker
1151*f6dc9357SAndroid Build Coastguard Worker return NCompress::CopyStream(_stream, outStream, lps);
1152*f6dc9357SAndroid Build Coastguard Worker
1153*f6dc9357SAndroid Build Coastguard Worker COM_TRY_END
1154*f6dc9357SAndroid Build Coastguard Worker }
1155*f6dc9357SAndroid Build Coastguard Worker
1156*f6dc9357SAndroid Build Coastguard Worker Z7_COM7F_IMF(CHandler::SetProperties(const wchar_t * const *names, const PROPVARIANT *values, UInt32 numProps))
1157*f6dc9357SAndroid Build Coastguard Worker {
1158*f6dc9357SAndroid Build Coastguard Worker _timeOptions.Init();
1159*f6dc9357SAndroid Build Coastguard Worker _props.Init();
1160*f6dc9357SAndroid Build Coastguard Worker
1161*f6dc9357SAndroid Build Coastguard Worker for (UInt32 i = 0; i < numProps; i++)
1162*f6dc9357SAndroid Build Coastguard Worker {
1163*f6dc9357SAndroid Build Coastguard Worker UString name = names[i];
1164*f6dc9357SAndroid Build Coastguard Worker name.MakeLower_Ascii();
1165*f6dc9357SAndroid Build Coastguard Worker if (name.IsEmpty())
1166*f6dc9357SAndroid Build Coastguard Worker return E_INVALIDARG;
1167*f6dc9357SAndroid Build Coastguard Worker const PROPVARIANT &value = values[i];
1168*f6dc9357SAndroid Build Coastguard Worker {
1169*f6dc9357SAndroid Build Coastguard Worker bool processed = false;
1170*f6dc9357SAndroid Build Coastguard Worker RINOK(_timeOptions.Parse(name, value, processed))
1171*f6dc9357SAndroid Build Coastguard Worker if (processed)
1172*f6dc9357SAndroid Build Coastguard Worker {
1173*f6dc9357SAndroid Build Coastguard Worker if (_timeOptions.Write_CTime.Val ||
1174*f6dc9357SAndroid Build Coastguard Worker _timeOptions.Write_ATime.Val)
1175*f6dc9357SAndroid Build Coastguard Worker return E_INVALIDARG;
1176*f6dc9357SAndroid Build Coastguard Worker if ( _timeOptions.Prec != (UInt32)(Int32)-1
1177*f6dc9357SAndroid Build Coastguard Worker && _timeOptions.Prec != k_PropVar_TimePrec_0
1178*f6dc9357SAndroid Build Coastguard Worker && _timeOptions.Prec != k_PropVar_TimePrec_Unix
1179*f6dc9357SAndroid Build Coastguard Worker && _timeOptions.Prec != k_PropVar_TimePrec_HighPrec
1180*f6dc9357SAndroid Build Coastguard Worker && _timeOptions.Prec != k_PropVar_TimePrec_Base)
1181*f6dc9357SAndroid Build Coastguard Worker return E_INVALIDARG;
1182*f6dc9357SAndroid Build Coastguard Worker continue;
1183*f6dc9357SAndroid Build Coastguard Worker }
1184*f6dc9357SAndroid Build Coastguard Worker }
1185*f6dc9357SAndroid Build Coastguard Worker RINOK(_props.SetProperty(name, value))
1186*f6dc9357SAndroid Build Coastguard Worker }
1187*f6dc9357SAndroid Build Coastguard Worker return S_OK;
1188*f6dc9357SAndroid Build Coastguard Worker }
1189*f6dc9357SAndroid Build Coastguard Worker
1190*f6dc9357SAndroid Build Coastguard Worker static const Byte k_Signature[] = { kSignature_0, kSignature_1, kSignature_2 };
1191*f6dc9357SAndroid Build Coastguard Worker
1192*f6dc9357SAndroid Build Coastguard Worker REGISTER_ARC_IO(
1193*f6dc9357SAndroid Build Coastguard Worker "gzip", "gz gzip tgz tpz apk", "* * .tar .tar .tar", 0xEF,
1194*f6dc9357SAndroid Build Coastguard Worker k_Signature, 0,
1195*f6dc9357SAndroid Build Coastguard Worker NArcInfoFlags::kKeepName
1196*f6dc9357SAndroid Build Coastguard Worker | NArcInfoFlags::kMTime
1197*f6dc9357SAndroid Build Coastguard Worker | NArcInfoFlags::kMTime_Default
1198*f6dc9357SAndroid Build Coastguard Worker , TIME_PREC_TO_ARC_FLAGS_MASK (NFileTimeType::kUnix)
1199*f6dc9357SAndroid Build Coastguard Worker | TIME_PREC_TO_ARC_FLAGS_TIME_DEFAULT (NFileTimeType::kUnix)
1200*f6dc9357SAndroid Build Coastguard Worker , IsArc_Gz)
1201*f6dc9357SAndroid Build Coastguard Worker
1202*f6dc9357SAndroid Build Coastguard Worker }}
1203