1*f6dc9357SAndroid Build Coastguard Worker // TarHandler.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 "../../../Common/ComTry.h"
6*f6dc9357SAndroid Build Coastguard Worker #include "../../../Common/IntToString.h"
7*f6dc9357SAndroid Build Coastguard Worker #include "../../../Common/StringConvert.h"
8*f6dc9357SAndroid Build Coastguard Worker #include "../../../Common/UTFConvert.h"
9*f6dc9357SAndroid Build Coastguard Worker
10*f6dc9357SAndroid Build Coastguard Worker #include "../../../Windows/TimeUtils.h"
11*f6dc9357SAndroid Build Coastguard Worker
12*f6dc9357SAndroid Build Coastguard Worker #include "../../Common/LimitedStreams.h"
13*f6dc9357SAndroid Build Coastguard Worker #include "../../Common/MethodProps.h"
14*f6dc9357SAndroid Build Coastguard Worker #include "../../Common/ProgressUtils.h"
15*f6dc9357SAndroid Build Coastguard Worker #include "../../Common/StreamObjects.h"
16*f6dc9357SAndroid Build Coastguard Worker #include "../../Common/StreamUtils.h"
17*f6dc9357SAndroid Build Coastguard Worker
18*f6dc9357SAndroid Build Coastguard Worker #include "../Common/ItemNameUtils.h"
19*f6dc9357SAndroid Build Coastguard Worker
20*f6dc9357SAndroid Build Coastguard Worker #include "TarHandler.h"
21*f6dc9357SAndroid Build Coastguard Worker
22*f6dc9357SAndroid Build Coastguard Worker using namespace NWindows;
23*f6dc9357SAndroid Build Coastguard Worker
24*f6dc9357SAndroid Build Coastguard Worker namespace NArchive {
25*f6dc9357SAndroid Build Coastguard Worker namespace NTar {
26*f6dc9357SAndroid Build Coastguard Worker
27*f6dc9357SAndroid Build Coastguard Worker // 21.02: we use UTF8 code page by default, even if some files show error
28*f6dc9357SAndroid Build Coastguard Worker // before 21.02 : CP_OEMCP;
29*f6dc9357SAndroid Build Coastguard Worker // static const UINT k_DefaultCodePage = CP_UTF8;
30*f6dc9357SAndroid Build Coastguard Worker
31*f6dc9357SAndroid Build Coastguard Worker
32*f6dc9357SAndroid Build Coastguard Worker static const Byte kProps[] =
33*f6dc9357SAndroid Build Coastguard Worker {
34*f6dc9357SAndroid Build Coastguard Worker kpidPath,
35*f6dc9357SAndroid Build Coastguard Worker kpidIsDir,
36*f6dc9357SAndroid Build Coastguard Worker kpidSize,
37*f6dc9357SAndroid Build Coastguard Worker kpidPackSize,
38*f6dc9357SAndroid Build Coastguard Worker kpidMTime,
39*f6dc9357SAndroid Build Coastguard Worker kpidCTime,
40*f6dc9357SAndroid Build Coastguard Worker kpidATime,
41*f6dc9357SAndroid Build Coastguard Worker kpidPosixAttrib,
42*f6dc9357SAndroid Build Coastguard Worker #if 0
43*f6dc9357SAndroid Build Coastguard Worker kpidAttrib,
44*f6dc9357SAndroid Build Coastguard Worker #endif
45*f6dc9357SAndroid Build Coastguard Worker kpidUser,
46*f6dc9357SAndroid Build Coastguard Worker kpidGroup,
47*f6dc9357SAndroid Build Coastguard Worker kpidUserId,
48*f6dc9357SAndroid Build Coastguard Worker kpidGroupId,
49*f6dc9357SAndroid Build Coastguard Worker kpidSymLink,
50*f6dc9357SAndroid Build Coastguard Worker kpidHardLink,
51*f6dc9357SAndroid Build Coastguard Worker kpidCharacts,
52*f6dc9357SAndroid Build Coastguard Worker kpidComment
53*f6dc9357SAndroid Build Coastguard Worker , kpidDeviceMajor
54*f6dc9357SAndroid Build Coastguard Worker , kpidDeviceMinor
55*f6dc9357SAndroid Build Coastguard Worker // , kpidDevice
56*f6dc9357SAndroid Build Coastguard Worker // , kpidHeadersSize // for debug
57*f6dc9357SAndroid Build Coastguard Worker // , kpidOffset // for debug
58*f6dc9357SAndroid Build Coastguard Worker };
59*f6dc9357SAndroid Build Coastguard Worker
60*f6dc9357SAndroid Build Coastguard Worker static const Byte kArcProps[] =
61*f6dc9357SAndroid Build Coastguard Worker {
62*f6dc9357SAndroid Build Coastguard Worker kpidHeadersSize,
63*f6dc9357SAndroid Build Coastguard Worker kpidCodePage,
64*f6dc9357SAndroid Build Coastguard Worker kpidCharacts,
65*f6dc9357SAndroid Build Coastguard Worker kpidComment
66*f6dc9357SAndroid Build Coastguard Worker };
67*f6dc9357SAndroid Build Coastguard Worker
68*f6dc9357SAndroid Build Coastguard Worker static const char *k_Characts_Prefix = "PREFIX";
69*f6dc9357SAndroid Build Coastguard Worker
70*f6dc9357SAndroid Build Coastguard Worker IMP_IInArchive_Props
71*f6dc9357SAndroid Build Coastguard Worker IMP_IInArchive_ArcProps
72*f6dc9357SAndroid Build Coastguard Worker
Z7_COM7F_IMF(CHandler::GetArchiveProperty (PROPID propID,PROPVARIANT * value))73*f6dc9357SAndroid Build Coastguard Worker Z7_COM7F_IMF(CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value))
74*f6dc9357SAndroid Build Coastguard Worker {
75*f6dc9357SAndroid Build Coastguard Worker NCOM::CPropVariant prop;
76*f6dc9357SAndroid Build Coastguard Worker switch (propID)
77*f6dc9357SAndroid Build Coastguard Worker {
78*f6dc9357SAndroid Build Coastguard Worker case kpidPhySize: if (_arc._phySize_Defined) prop = _arc._phySize; break;
79*f6dc9357SAndroid Build Coastguard Worker case kpidHeadersSize: if (_arc._phySize_Defined) prop = _arc._headersSize; break;
80*f6dc9357SAndroid Build Coastguard Worker case kpidErrorFlags:
81*f6dc9357SAndroid Build Coastguard Worker {
82*f6dc9357SAndroid Build Coastguard Worker UInt32 flags = 0;
83*f6dc9357SAndroid Build Coastguard Worker if (!_isArc)
84*f6dc9357SAndroid Build Coastguard Worker flags |= kpv_ErrorFlags_IsNotArc;
85*f6dc9357SAndroid Build Coastguard Worker else switch ((int)_arc._error)
86*f6dc9357SAndroid Build Coastguard Worker {
87*f6dc9357SAndroid Build Coastguard Worker case k_ErrorType_UnexpectedEnd: flags = kpv_ErrorFlags_UnexpectedEnd; break;
88*f6dc9357SAndroid Build Coastguard Worker case k_ErrorType_Corrupted: flags = kpv_ErrorFlags_HeadersError; break;
89*f6dc9357SAndroid Build Coastguard Worker // case k_ErrorType_OK: break;
90*f6dc9357SAndroid Build Coastguard Worker // case k_ErrorType_Warning: break;
91*f6dc9357SAndroid Build Coastguard Worker // case k_ErrorType_OK:
92*f6dc9357SAndroid Build Coastguard Worker default: break;
93*f6dc9357SAndroid Build Coastguard Worker }
94*f6dc9357SAndroid Build Coastguard Worker if (flags != 0)
95*f6dc9357SAndroid Build Coastguard Worker prop = flags;
96*f6dc9357SAndroid Build Coastguard Worker break;
97*f6dc9357SAndroid Build Coastguard Worker }
98*f6dc9357SAndroid Build Coastguard Worker
99*f6dc9357SAndroid Build Coastguard Worker case kpidWarningFlags:
100*f6dc9357SAndroid Build Coastguard Worker {
101*f6dc9357SAndroid Build Coastguard Worker if (_arc._is_Warning)
102*f6dc9357SAndroid Build Coastguard Worker prop = kpv_ErrorFlags_HeadersError;
103*f6dc9357SAndroid Build Coastguard Worker break;
104*f6dc9357SAndroid Build Coastguard Worker }
105*f6dc9357SAndroid Build Coastguard Worker
106*f6dc9357SAndroid Build Coastguard Worker case kpidCodePage:
107*f6dc9357SAndroid Build Coastguard Worker {
108*f6dc9357SAndroid Build Coastguard Worker char sz[16];
109*f6dc9357SAndroid Build Coastguard Worker const char *name = NULL;
110*f6dc9357SAndroid Build Coastguard Worker switch (_openCodePage)
111*f6dc9357SAndroid Build Coastguard Worker {
112*f6dc9357SAndroid Build Coastguard Worker case CP_OEMCP: name = "OEM"; break;
113*f6dc9357SAndroid Build Coastguard Worker case CP_UTF8: name = "UTF-8"; break;
114*f6dc9357SAndroid Build Coastguard Worker default: break;
115*f6dc9357SAndroid Build Coastguard Worker }
116*f6dc9357SAndroid Build Coastguard Worker if (!name)
117*f6dc9357SAndroid Build Coastguard Worker {
118*f6dc9357SAndroid Build Coastguard Worker ConvertUInt32ToString(_openCodePage, sz);
119*f6dc9357SAndroid Build Coastguard Worker name = sz;
120*f6dc9357SAndroid Build Coastguard Worker }
121*f6dc9357SAndroid Build Coastguard Worker prop = name;
122*f6dc9357SAndroid Build Coastguard Worker break;
123*f6dc9357SAndroid Build Coastguard Worker }
124*f6dc9357SAndroid Build Coastguard Worker
125*f6dc9357SAndroid Build Coastguard Worker case kpidCharacts:
126*f6dc9357SAndroid Build Coastguard Worker {
127*f6dc9357SAndroid Build Coastguard Worker AString s;
128*f6dc9357SAndroid Build Coastguard Worker if (_arc._are_Gnu) s.Add_OptSpaced("GNU");
129*f6dc9357SAndroid Build Coastguard Worker if (_arc._are_Posix) s.Add_OptSpaced("POSIX");
130*f6dc9357SAndroid Build Coastguard Worker if (_arc._are_Pax_Items) s.Add_OptSpaced("PAX_ITEM");
131*f6dc9357SAndroid Build Coastguard Worker if (_arc._pathPrefix_WasUsed) s.Add_OptSpaced(k_Characts_Prefix);
132*f6dc9357SAndroid Build Coastguard Worker if (_arc._are_LongName) s.Add_OptSpaced("LongName");
133*f6dc9357SAndroid Build Coastguard Worker if (_arc._are_LongLink) s.Add_OptSpaced("LongLink");
134*f6dc9357SAndroid Build Coastguard Worker if (_arc._are_Pax) s.Add_OptSpaced("PAX");
135*f6dc9357SAndroid Build Coastguard Worker if (_arc._are_pax_path) s.Add_OptSpaced("path");
136*f6dc9357SAndroid Build Coastguard Worker if (_arc._are_pax_link) s.Add_OptSpaced("linkpath");
137*f6dc9357SAndroid Build Coastguard Worker if (_arc._are_mtime) s.Add_OptSpaced("mtime");
138*f6dc9357SAndroid Build Coastguard Worker if (_arc._are_atime) s.Add_OptSpaced("atime");
139*f6dc9357SAndroid Build Coastguard Worker if (_arc._are_ctime) s.Add_OptSpaced("ctime");
140*f6dc9357SAndroid Build Coastguard Worker if (_arc._are_SCHILY_fflags) s.Add_OptSpaced("SCHILY.fflags");
141*f6dc9357SAndroid Build Coastguard Worker if (_arc._is_PaxGlobal_Error) s.Add_OptSpaced("PAX_GLOBAL_ERROR");
142*f6dc9357SAndroid Build Coastguard Worker s.Add_OptSpaced(_encodingCharacts.GetCharactsString());
143*f6dc9357SAndroid Build Coastguard Worker prop = s;
144*f6dc9357SAndroid Build Coastguard Worker break;
145*f6dc9357SAndroid Build Coastguard Worker }
146*f6dc9357SAndroid Build Coastguard Worker
147*f6dc9357SAndroid Build Coastguard Worker case kpidComment:
148*f6dc9357SAndroid Build Coastguard Worker {
149*f6dc9357SAndroid Build Coastguard Worker if (_arc.PaxGlobal_Defined)
150*f6dc9357SAndroid Build Coastguard Worker {
151*f6dc9357SAndroid Build Coastguard Worker AString s;
152*f6dc9357SAndroid Build Coastguard Worker _arc.PaxGlobal.Print_To_String(s);
153*f6dc9357SAndroid Build Coastguard Worker if (!s.IsEmpty())
154*f6dc9357SAndroid Build Coastguard Worker prop = s;
155*f6dc9357SAndroid Build Coastguard Worker }
156*f6dc9357SAndroid Build Coastguard Worker break;
157*f6dc9357SAndroid Build Coastguard Worker }
158*f6dc9357SAndroid Build Coastguard Worker default: break;
159*f6dc9357SAndroid Build Coastguard Worker }
160*f6dc9357SAndroid Build Coastguard Worker prop.Detach(value);
161*f6dc9357SAndroid Build Coastguard Worker return S_OK;
162*f6dc9357SAndroid Build Coastguard Worker }
163*f6dc9357SAndroid Build Coastguard Worker
164*f6dc9357SAndroid Build Coastguard Worker
Check(const AString & s)165*f6dc9357SAndroid Build Coastguard Worker void CEncodingCharacts::Check(const AString &s)
166*f6dc9357SAndroid Build Coastguard Worker {
167*f6dc9357SAndroid Build Coastguard Worker IsAscii = s.IsAscii();
168*f6dc9357SAndroid Build Coastguard Worker if (!IsAscii)
169*f6dc9357SAndroid Build Coastguard Worker {
170*f6dc9357SAndroid Build Coastguard Worker /*
171*f6dc9357SAndroid Build Coastguard Worker {
172*f6dc9357SAndroid Build Coastguard Worker Oem_Checked = true;
173*f6dc9357SAndroid Build Coastguard Worker UString u;
174*f6dc9357SAndroid Build Coastguard Worker MultiByteToUnicodeString2(u, s, CP_OEMCP);
175*f6dc9357SAndroid Build Coastguard Worker Oem_Ok = (u.Find((wchar_t)0xfffd) <= 0);
176*f6dc9357SAndroid Build Coastguard Worker }
177*f6dc9357SAndroid Build Coastguard Worker Utf_Checked = true;
178*f6dc9357SAndroid Build Coastguard Worker */
179*f6dc9357SAndroid Build Coastguard Worker UtfCheck.Check_AString(s);
180*f6dc9357SAndroid Build Coastguard Worker }
181*f6dc9357SAndroid Build Coastguard Worker }
182*f6dc9357SAndroid Build Coastguard Worker
183*f6dc9357SAndroid Build Coastguard Worker
GetCharactsString() const184*f6dc9357SAndroid Build Coastguard Worker AString CEncodingCharacts::GetCharactsString() const
185*f6dc9357SAndroid Build Coastguard Worker {
186*f6dc9357SAndroid Build Coastguard Worker AString s;
187*f6dc9357SAndroid Build Coastguard Worker if (IsAscii)
188*f6dc9357SAndroid Build Coastguard Worker {
189*f6dc9357SAndroid Build Coastguard Worker s += "ASCII";
190*f6dc9357SAndroid Build Coastguard Worker }
191*f6dc9357SAndroid Build Coastguard Worker /*
192*f6dc9357SAndroid Build Coastguard Worker if (Oem_Checked)
193*f6dc9357SAndroid Build Coastguard Worker {
194*f6dc9357SAndroid Build Coastguard Worker s.Add_Space_if_NotEmpty();
195*f6dc9357SAndroid Build Coastguard Worker s += (Oem_Ok ? "oem-ok" : "oem-error");
196*f6dc9357SAndroid Build Coastguard Worker }
197*f6dc9357SAndroid Build Coastguard Worker if (Utf_Checked)
198*f6dc9357SAndroid Build Coastguard Worker */
199*f6dc9357SAndroid Build Coastguard Worker else
200*f6dc9357SAndroid Build Coastguard Worker {
201*f6dc9357SAndroid Build Coastguard Worker s.Add_Space_if_NotEmpty();
202*f6dc9357SAndroid Build Coastguard Worker s += (UtfCheck.IsOK() ? "UTF8" : "UTF8-ERROR"); // "UTF8-error"
203*f6dc9357SAndroid Build Coastguard Worker {
204*f6dc9357SAndroid Build Coastguard Worker AString s2;
205*f6dc9357SAndroid Build Coastguard Worker UtfCheck.PrintStatus(s2);
206*f6dc9357SAndroid Build Coastguard Worker s.Add_Space_if_NotEmpty();
207*f6dc9357SAndroid Build Coastguard Worker s += s2;
208*f6dc9357SAndroid Build Coastguard Worker }
209*f6dc9357SAndroid Build Coastguard Worker }
210*f6dc9357SAndroid Build Coastguard Worker return s;
211*f6dc9357SAndroid Build Coastguard Worker }
212*f6dc9357SAndroid Build Coastguard Worker
213*f6dc9357SAndroid Build Coastguard Worker
Open2(IInStream * stream,IArchiveOpenCallback * callback)214*f6dc9357SAndroid Build Coastguard Worker HRESULT CHandler::Open2(IInStream *stream, IArchiveOpenCallback *callback)
215*f6dc9357SAndroid Build Coastguard Worker {
216*f6dc9357SAndroid Build Coastguard Worker UInt64 endPos;
217*f6dc9357SAndroid Build Coastguard Worker {
218*f6dc9357SAndroid Build Coastguard Worker RINOK(InStream_AtBegin_GetSize(stream, endPos))
219*f6dc9357SAndroid Build Coastguard Worker }
220*f6dc9357SAndroid Build Coastguard Worker
221*f6dc9357SAndroid Build Coastguard Worker _arc._phySize_Defined = true;
222*f6dc9357SAndroid Build Coastguard Worker
223*f6dc9357SAndroid Build Coastguard Worker // bool utf8_OK = true;
224*f6dc9357SAndroid Build Coastguard Worker
225*f6dc9357SAndroid Build Coastguard Worker _arc.SeqStream = stream;
226*f6dc9357SAndroid Build Coastguard Worker _arc.InStream = stream;
227*f6dc9357SAndroid Build Coastguard Worker _arc.OpenCallback = callback;
228*f6dc9357SAndroid Build Coastguard Worker
229*f6dc9357SAndroid Build Coastguard Worker CItemEx item;
230*f6dc9357SAndroid Build Coastguard Worker for (;;)
231*f6dc9357SAndroid Build Coastguard Worker {
232*f6dc9357SAndroid Build Coastguard Worker _arc.NumFiles = _items.Size();
233*f6dc9357SAndroid Build Coastguard Worker RINOK(_arc.ReadItem(item))
234*f6dc9357SAndroid Build Coastguard Worker if (!_arc.filled)
235*f6dc9357SAndroid Build Coastguard Worker break;
236*f6dc9357SAndroid Build Coastguard Worker
237*f6dc9357SAndroid Build Coastguard Worker _isArc = true;
238*f6dc9357SAndroid Build Coastguard Worker
239*f6dc9357SAndroid Build Coastguard Worker /*
240*f6dc9357SAndroid Build Coastguard Worker if (!_forceCodePage)
241*f6dc9357SAndroid Build Coastguard Worker {
242*f6dc9357SAndroid Build Coastguard Worker if (utf8_OK) utf8_OK = CheckUTF8(item.Name, item.NameCouldBeReduced);
243*f6dc9357SAndroid Build Coastguard Worker if (utf8_OK) utf8_OK = CheckUTF8(item.LinkName, item.LinkNameCouldBeReduced);
244*f6dc9357SAndroid Build Coastguard Worker if (utf8_OK) utf8_OK = CheckUTF8(item.User);
245*f6dc9357SAndroid Build Coastguard Worker if (utf8_OK) utf8_OK = CheckUTF8(item.Group);
246*f6dc9357SAndroid Build Coastguard Worker }
247*f6dc9357SAndroid Build Coastguard Worker */
248*f6dc9357SAndroid Build Coastguard Worker
249*f6dc9357SAndroid Build Coastguard Worker item.EncodingCharacts.Check(item.Name);
250*f6dc9357SAndroid Build Coastguard Worker _encodingCharacts.Update(item.EncodingCharacts);
251*f6dc9357SAndroid Build Coastguard Worker
252*f6dc9357SAndroid Build Coastguard Worker _items.Add(item);
253*f6dc9357SAndroid Build Coastguard Worker
254*f6dc9357SAndroid Build Coastguard Worker RINOK(stream->Seek((Int64)item.Get_PackSize_Aligned(), STREAM_SEEK_CUR, &_arc._phySize))
255*f6dc9357SAndroid Build Coastguard Worker if (_arc._phySize > endPos)
256*f6dc9357SAndroid Build Coastguard Worker {
257*f6dc9357SAndroid Build Coastguard Worker _arc._error = k_ErrorType_UnexpectedEnd;
258*f6dc9357SAndroid Build Coastguard Worker break;
259*f6dc9357SAndroid Build Coastguard Worker }
260*f6dc9357SAndroid Build Coastguard Worker /*
261*f6dc9357SAndroid Build Coastguard Worker if (_phySize == endPos)
262*f6dc9357SAndroid Build Coastguard Worker {
263*f6dc9357SAndroid Build Coastguard Worker _errorMessage = "There are no trailing zero-filled records";
264*f6dc9357SAndroid Build Coastguard Worker break;
265*f6dc9357SAndroid Build Coastguard Worker }
266*f6dc9357SAndroid Build Coastguard Worker */
267*f6dc9357SAndroid Build Coastguard Worker /*
268*f6dc9357SAndroid Build Coastguard Worker if (callback)
269*f6dc9357SAndroid Build Coastguard Worker {
270*f6dc9357SAndroid Build Coastguard Worker if (_items.Size() == 1)
271*f6dc9357SAndroid Build Coastguard Worker {
272*f6dc9357SAndroid Build Coastguard Worker RINOK(callback->SetTotal(NULL, &endPos));
273*f6dc9357SAndroid Build Coastguard Worker }
274*f6dc9357SAndroid Build Coastguard Worker if ((_items.Size() & 0x3FF) == 0)
275*f6dc9357SAndroid Build Coastguard Worker {
276*f6dc9357SAndroid Build Coastguard Worker const UInt64 numFiles = _items.Size();
277*f6dc9357SAndroid Build Coastguard Worker RINOK(callback->SetCompleted(&numFiles, &_phySize));
278*f6dc9357SAndroid Build Coastguard Worker }
279*f6dc9357SAndroid Build Coastguard Worker }
280*f6dc9357SAndroid Build Coastguard Worker */
281*f6dc9357SAndroid Build Coastguard Worker }
282*f6dc9357SAndroid Build Coastguard Worker
283*f6dc9357SAndroid Build Coastguard Worker /*
284*f6dc9357SAndroid Build Coastguard Worker if (!_forceCodePage)
285*f6dc9357SAndroid Build Coastguard Worker {
286*f6dc9357SAndroid Build Coastguard Worker if (!utf8_OK)
287*f6dc9357SAndroid Build Coastguard Worker _curCodePage = k_DefaultCodePage;
288*f6dc9357SAndroid Build Coastguard Worker }
289*f6dc9357SAndroid Build Coastguard Worker */
290*f6dc9357SAndroid Build Coastguard Worker _openCodePage = _curCodePage;
291*f6dc9357SAndroid Build Coastguard Worker
292*f6dc9357SAndroid Build Coastguard Worker if (_items.Size() == 0)
293*f6dc9357SAndroid Build Coastguard Worker {
294*f6dc9357SAndroid Build Coastguard Worker if (_arc._error != k_ErrorType_OK)
295*f6dc9357SAndroid Build Coastguard Worker {
296*f6dc9357SAndroid Build Coastguard Worker _isArc = false;
297*f6dc9357SAndroid Build Coastguard Worker return S_FALSE;
298*f6dc9357SAndroid Build Coastguard Worker }
299*f6dc9357SAndroid Build Coastguard Worker if (!callback)
300*f6dc9357SAndroid Build Coastguard Worker return S_FALSE;
301*f6dc9357SAndroid Build Coastguard Worker Z7_DECL_CMyComPtr_QI_FROM(
302*f6dc9357SAndroid Build Coastguard Worker IArchiveOpenVolumeCallback,
303*f6dc9357SAndroid Build Coastguard Worker openVolumeCallback, callback)
304*f6dc9357SAndroid Build Coastguard Worker if (!openVolumeCallback)
305*f6dc9357SAndroid Build Coastguard Worker return S_FALSE;
306*f6dc9357SAndroid Build Coastguard Worker NCOM::CPropVariant prop;
307*f6dc9357SAndroid Build Coastguard Worker if (openVolumeCallback->GetProperty(kpidName, &prop) != S_OK)
308*f6dc9357SAndroid Build Coastguard Worker return S_FALSE;
309*f6dc9357SAndroid Build Coastguard Worker if (prop.vt != VT_BSTR)
310*f6dc9357SAndroid Build Coastguard Worker return S_FALSE;
311*f6dc9357SAndroid Build Coastguard Worker unsigned len = MyStringLen(prop.bstrVal);
312*f6dc9357SAndroid Build Coastguard Worker if (len < 4 || MyStringCompareNoCase(prop.bstrVal + len - 4, L".tar") != 0)
313*f6dc9357SAndroid Build Coastguard Worker return S_FALSE;
314*f6dc9357SAndroid Build Coastguard Worker }
315*f6dc9357SAndroid Build Coastguard Worker
316*f6dc9357SAndroid Build Coastguard Worker _isArc = true;
317*f6dc9357SAndroid Build Coastguard Worker return S_OK;
318*f6dc9357SAndroid Build Coastguard Worker }
319*f6dc9357SAndroid Build Coastguard Worker
Z7_COM7F_IMF(CHandler::Open (IInStream * stream,const UInt64 *,IArchiveOpenCallback * openArchiveCallback))320*f6dc9357SAndroid Build Coastguard Worker Z7_COM7F_IMF(CHandler::Open(IInStream *stream, const UInt64 *, IArchiveOpenCallback *openArchiveCallback))
321*f6dc9357SAndroid Build Coastguard Worker {
322*f6dc9357SAndroid Build Coastguard Worker COM_TRY_BEGIN
323*f6dc9357SAndroid Build Coastguard Worker // for (int i = 0; i < 10; i++) // for debug
324*f6dc9357SAndroid Build Coastguard Worker {
325*f6dc9357SAndroid Build Coastguard Worker Close();
326*f6dc9357SAndroid Build Coastguard Worker RINOK(Open2(stream, openArchiveCallback))
327*f6dc9357SAndroid Build Coastguard Worker _stream = stream;
328*f6dc9357SAndroid Build Coastguard Worker }
329*f6dc9357SAndroid Build Coastguard Worker return S_OK;
330*f6dc9357SAndroid Build Coastguard Worker COM_TRY_END
331*f6dc9357SAndroid Build Coastguard Worker }
332*f6dc9357SAndroid Build Coastguard Worker
Z7_COM7F_IMF(CHandler::OpenSeq (ISequentialInStream * stream))333*f6dc9357SAndroid Build Coastguard Worker Z7_COM7F_IMF(CHandler::OpenSeq(ISequentialInStream *stream))
334*f6dc9357SAndroid Build Coastguard Worker {
335*f6dc9357SAndroid Build Coastguard Worker Close();
336*f6dc9357SAndroid Build Coastguard Worker _seqStream = stream;
337*f6dc9357SAndroid Build Coastguard Worker _isArc = true;
338*f6dc9357SAndroid Build Coastguard Worker return S_OK;
339*f6dc9357SAndroid Build Coastguard Worker }
340*f6dc9357SAndroid Build Coastguard Worker
Z7_COM7F_IMF(CHandler::Close ())341*f6dc9357SAndroid Build Coastguard Worker Z7_COM7F_IMF(CHandler::Close())
342*f6dc9357SAndroid Build Coastguard Worker {
343*f6dc9357SAndroid Build Coastguard Worker _isArc = false;
344*f6dc9357SAndroid Build Coastguard Worker
345*f6dc9357SAndroid Build Coastguard Worker _arc.Clear();
346*f6dc9357SAndroid Build Coastguard Worker
347*f6dc9357SAndroid Build Coastguard Worker _curIndex = 0;
348*f6dc9357SAndroid Build Coastguard Worker _latestIsRead = false;
349*f6dc9357SAndroid Build Coastguard Worker _encodingCharacts.Clear();
350*f6dc9357SAndroid Build Coastguard Worker _items.Clear();
351*f6dc9357SAndroid Build Coastguard Worker _seqStream.Release();
352*f6dc9357SAndroid Build Coastguard Worker _stream.Release();
353*f6dc9357SAndroid Build Coastguard Worker return S_OK;
354*f6dc9357SAndroid Build Coastguard Worker }
355*f6dc9357SAndroid Build Coastguard Worker
Z7_COM7F_IMF(CHandler::GetNumberOfItems (UInt32 * numItems))356*f6dc9357SAndroid Build Coastguard Worker Z7_COM7F_IMF(CHandler::GetNumberOfItems(UInt32 *numItems))
357*f6dc9357SAndroid Build Coastguard Worker {
358*f6dc9357SAndroid Build Coastguard Worker *numItems = (_stream ? _items.Size() : (UInt32)(Int32)-1);
359*f6dc9357SAndroid Build Coastguard Worker return S_OK;
360*f6dc9357SAndroid Build Coastguard Worker }
361*f6dc9357SAndroid Build Coastguard Worker
CHandler()362*f6dc9357SAndroid Build Coastguard Worker CHandler::CHandler()
363*f6dc9357SAndroid Build Coastguard Worker {
364*f6dc9357SAndroid Build Coastguard Worker // copyCoder = new NCompress::CCopyCoder();
365*f6dc9357SAndroid Build Coastguard Worker // copyCoder = copyCoder;
366*f6dc9357SAndroid Build Coastguard Worker _openCodePage = CP_UTF8;
367*f6dc9357SAndroid Build Coastguard Worker Init();
368*f6dc9357SAndroid Build Coastguard Worker }
369*f6dc9357SAndroid Build Coastguard Worker
SkipTo(UInt32 index)370*f6dc9357SAndroid Build Coastguard Worker HRESULT CHandler::SkipTo(UInt32 index)
371*f6dc9357SAndroid Build Coastguard Worker {
372*f6dc9357SAndroid Build Coastguard Worker while (_curIndex < index || !_latestIsRead)
373*f6dc9357SAndroid Build Coastguard Worker {
374*f6dc9357SAndroid Build Coastguard Worker if (_latestIsRead)
375*f6dc9357SAndroid Build Coastguard Worker {
376*f6dc9357SAndroid Build Coastguard Worker const UInt64 packSize = _latestItem.Get_PackSize_Aligned();
377*f6dc9357SAndroid Build Coastguard Worker RINOK(copyCoder.Interface()->Code(_seqStream, NULL, &packSize, &packSize, NULL))
378*f6dc9357SAndroid Build Coastguard Worker _arc._phySize += copyCoder->TotalSize;
379*f6dc9357SAndroid Build Coastguard Worker if (copyCoder->TotalSize != packSize)
380*f6dc9357SAndroid Build Coastguard Worker {
381*f6dc9357SAndroid Build Coastguard Worker _arc._error = k_ErrorType_UnexpectedEnd;
382*f6dc9357SAndroid Build Coastguard Worker return S_FALSE;
383*f6dc9357SAndroid Build Coastguard Worker }
384*f6dc9357SAndroid Build Coastguard Worker _latestIsRead = false;
385*f6dc9357SAndroid Build Coastguard Worker _curIndex++;
386*f6dc9357SAndroid Build Coastguard Worker }
387*f6dc9357SAndroid Build Coastguard Worker else
388*f6dc9357SAndroid Build Coastguard Worker {
389*f6dc9357SAndroid Build Coastguard Worker _arc.SeqStream = _seqStream;
390*f6dc9357SAndroid Build Coastguard Worker _arc.InStream = NULL;
391*f6dc9357SAndroid Build Coastguard Worker RINOK(_arc.ReadItem(_latestItem))
392*f6dc9357SAndroid Build Coastguard Worker if (!_arc.filled)
393*f6dc9357SAndroid Build Coastguard Worker {
394*f6dc9357SAndroid Build Coastguard Worker _arc._phySize_Defined = true;
395*f6dc9357SAndroid Build Coastguard Worker return E_INVALIDARG;
396*f6dc9357SAndroid Build Coastguard Worker }
397*f6dc9357SAndroid Build Coastguard Worker _latestIsRead = true;
398*f6dc9357SAndroid Build Coastguard Worker }
399*f6dc9357SAndroid Build Coastguard Worker }
400*f6dc9357SAndroid Build Coastguard Worker return S_OK;
401*f6dc9357SAndroid Build Coastguard Worker }
402*f6dc9357SAndroid Build Coastguard Worker
TarStringToUnicode(const AString & s,NWindows::NCOM::CPropVariant & prop,bool toOs) const403*f6dc9357SAndroid Build Coastguard Worker void CHandler::TarStringToUnicode(const AString &s, NWindows::NCOM::CPropVariant &prop, bool toOs) const
404*f6dc9357SAndroid Build Coastguard Worker {
405*f6dc9357SAndroid Build Coastguard Worker UString dest;
406*f6dc9357SAndroid Build Coastguard Worker if (_curCodePage == CP_UTF8)
407*f6dc9357SAndroid Build Coastguard Worker ConvertUTF8ToUnicode(s, dest);
408*f6dc9357SAndroid Build Coastguard Worker else
409*f6dc9357SAndroid Build Coastguard Worker MultiByteToUnicodeString2(dest, s, _curCodePage);
410*f6dc9357SAndroid Build Coastguard Worker if (toOs)
411*f6dc9357SAndroid Build Coastguard Worker NItemName::ReplaceToOsSlashes_Remove_TailSlash(dest,
412*f6dc9357SAndroid Build Coastguard Worker true); // useBackslashReplacement
413*f6dc9357SAndroid Build Coastguard Worker prop = dest;
414*f6dc9357SAndroid Build Coastguard Worker }
415*f6dc9357SAndroid Build Coastguard Worker
416*f6dc9357SAndroid Build Coastguard Worker
417*f6dc9357SAndroid Build Coastguard Worker // CPaxTime is defined (NumDigits >= 0)
PaxTimeToProp(const CPaxTime & pt,NWindows::NCOM::CPropVariant & prop)418*f6dc9357SAndroid Build Coastguard Worker static void PaxTimeToProp(const CPaxTime &pt, NWindows::NCOM::CPropVariant &prop)
419*f6dc9357SAndroid Build Coastguard Worker {
420*f6dc9357SAndroid Build Coastguard Worker UInt64 v;
421*f6dc9357SAndroid Build Coastguard Worker if (!NTime::UnixTime64_To_FileTime64(pt.Sec, v))
422*f6dc9357SAndroid Build Coastguard Worker return;
423*f6dc9357SAndroid Build Coastguard Worker if (pt.Ns != 0)
424*f6dc9357SAndroid Build Coastguard Worker v += pt.Ns / 100;
425*f6dc9357SAndroid Build Coastguard Worker FILETIME ft;
426*f6dc9357SAndroid Build Coastguard Worker ft.dwLowDateTime = (DWORD)v;
427*f6dc9357SAndroid Build Coastguard Worker ft.dwHighDateTime = (DWORD)(v >> 32);
428*f6dc9357SAndroid Build Coastguard Worker prop.SetAsTimeFrom_FT_Prec_Ns100(ft,
429*f6dc9357SAndroid Build Coastguard Worker k_PropVar_TimePrec_Base + (unsigned)pt.NumDigits, pt.Ns % 100);
430*f6dc9357SAndroid Build Coastguard Worker }
431*f6dc9357SAndroid Build Coastguard Worker
432*f6dc9357SAndroid Build Coastguard Worker
AddSpecCharToString(const char c,AString & s)433*f6dc9357SAndroid Build Coastguard Worker static void AddSpecCharToString(const char c, AString &s)
434*f6dc9357SAndroid Build Coastguard Worker {
435*f6dc9357SAndroid Build Coastguard Worker if ((Byte)c <= 0x20 || (Byte)c > 127)
436*f6dc9357SAndroid Build Coastguard Worker {
437*f6dc9357SAndroid Build Coastguard Worker s.Add_Char('[');
438*f6dc9357SAndroid Build Coastguard Worker s.Add_Char(GET_HEX_CHAR_LOWER((Byte)c >> 4));
439*f6dc9357SAndroid Build Coastguard Worker s.Add_Char(GET_HEX_CHAR_LOWER(c & 15));
440*f6dc9357SAndroid Build Coastguard Worker s.Add_Char(']');
441*f6dc9357SAndroid Build Coastguard Worker }
442*f6dc9357SAndroid Build Coastguard Worker else
443*f6dc9357SAndroid Build Coastguard Worker s.Add_Char(c);
444*f6dc9357SAndroid Build Coastguard Worker }
445*f6dc9357SAndroid Build Coastguard Worker
AddSpecUInt64(AString & s,const char * name,UInt64 v)446*f6dc9357SAndroid Build Coastguard Worker static void AddSpecUInt64(AString &s, const char *name, UInt64 v)
447*f6dc9357SAndroid Build Coastguard Worker {
448*f6dc9357SAndroid Build Coastguard Worker if (v != 0)
449*f6dc9357SAndroid Build Coastguard Worker {
450*f6dc9357SAndroid Build Coastguard Worker s.Add_OptSpaced(name);
451*f6dc9357SAndroid Build Coastguard Worker if (v > 1)
452*f6dc9357SAndroid Build Coastguard Worker {
453*f6dc9357SAndroid Build Coastguard Worker s.Add_Colon();
454*f6dc9357SAndroid Build Coastguard Worker s.Add_UInt64(v);
455*f6dc9357SAndroid Build Coastguard Worker }
456*f6dc9357SAndroid Build Coastguard Worker }
457*f6dc9357SAndroid Build Coastguard Worker }
458*f6dc9357SAndroid Build Coastguard Worker
AddSpecBools(AString & s,const char * name,bool b1,bool b2)459*f6dc9357SAndroid Build Coastguard Worker static void AddSpecBools(AString &s, const char *name, bool b1, bool b2)
460*f6dc9357SAndroid Build Coastguard Worker {
461*f6dc9357SAndroid Build Coastguard Worker if (b1)
462*f6dc9357SAndroid Build Coastguard Worker {
463*f6dc9357SAndroid Build Coastguard Worker s.Add_OptSpaced(name);
464*f6dc9357SAndroid Build Coastguard Worker if (b2)
465*f6dc9357SAndroid Build Coastguard Worker s.Add_Char('*');
466*f6dc9357SAndroid Build Coastguard Worker }
467*f6dc9357SAndroid Build Coastguard Worker }
468*f6dc9357SAndroid Build Coastguard Worker
469*f6dc9357SAndroid Build Coastguard Worker
470*f6dc9357SAndroid Build Coastguard Worker #if 0
Parse_Attrib_from_SCHILY_fflags(const AString & s,UInt32 & attribRes)471*f6dc9357SAndroid Build Coastguard Worker static bool Parse_Attrib_from_SCHILY_fflags(const AString &s, UInt32 &attribRes)
472*f6dc9357SAndroid Build Coastguard Worker {
473*f6dc9357SAndroid Build Coastguard Worker UInt32 attrib = 0;
474*f6dc9357SAndroid Build Coastguard Worker attribRes = attrib;
475*f6dc9357SAndroid Build Coastguard Worker unsigned pos = 0;
476*f6dc9357SAndroid Build Coastguard Worker while (pos < s.Len())
477*f6dc9357SAndroid Build Coastguard Worker {
478*f6dc9357SAndroid Build Coastguard Worker int pos2 = s.Find(',', pos);
479*f6dc9357SAndroid Build Coastguard Worker if (pos2 < 0)
480*f6dc9357SAndroid Build Coastguard Worker pos2 = (int)s.Len();
481*f6dc9357SAndroid Build Coastguard Worker const AString str = s.Mid(pos, (unsigned)pos2 - pos);
482*f6dc9357SAndroid Build Coastguard Worker if (str.IsEqualTo("hidden")) attrib |= FILE_ATTRIBUTE_HIDDEN;
483*f6dc9357SAndroid Build Coastguard Worker else if (str.IsEqualTo("rdonly")) attrib |= FILE_ATTRIBUTE_READONLY;
484*f6dc9357SAndroid Build Coastguard Worker else if (str.IsEqualTo("system")) attrib |= FILE_ATTRIBUTE_SYSTEM;
485*f6dc9357SAndroid Build Coastguard Worker else
486*f6dc9357SAndroid Build Coastguard Worker return false;
487*f6dc9357SAndroid Build Coastguard Worker pos = (unsigned)pos2 + 1;
488*f6dc9357SAndroid Build Coastguard Worker }
489*f6dc9357SAndroid Build Coastguard Worker attribRes = attrib;
490*f6dc9357SAndroid Build Coastguard Worker return true;
491*f6dc9357SAndroid Build Coastguard Worker }
492*f6dc9357SAndroid Build Coastguard Worker #endif
493*f6dc9357SAndroid Build Coastguard Worker
494*f6dc9357SAndroid Build Coastguard Worker
Z7_COM7F_IMF(CHandler::GetProperty (UInt32 index,PROPID propID,PROPVARIANT * value))495*f6dc9357SAndroid Build Coastguard Worker Z7_COM7F_IMF(CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *value))
496*f6dc9357SAndroid Build Coastguard Worker {
497*f6dc9357SAndroid Build Coastguard Worker COM_TRY_BEGIN
498*f6dc9357SAndroid Build Coastguard Worker NCOM::CPropVariant prop;
499*f6dc9357SAndroid Build Coastguard Worker
500*f6dc9357SAndroid Build Coastguard Worker const CItemEx *item;
501*f6dc9357SAndroid Build Coastguard Worker if (_stream)
502*f6dc9357SAndroid Build Coastguard Worker item = &_items[index];
503*f6dc9357SAndroid Build Coastguard Worker else
504*f6dc9357SAndroid Build Coastguard Worker {
505*f6dc9357SAndroid Build Coastguard Worker if (index < _curIndex)
506*f6dc9357SAndroid Build Coastguard Worker return E_INVALIDARG;
507*f6dc9357SAndroid Build Coastguard Worker else
508*f6dc9357SAndroid Build Coastguard Worker {
509*f6dc9357SAndroid Build Coastguard Worker RINOK(SkipTo(index))
510*f6dc9357SAndroid Build Coastguard Worker item = &_latestItem;
511*f6dc9357SAndroid Build Coastguard Worker }
512*f6dc9357SAndroid Build Coastguard Worker }
513*f6dc9357SAndroid Build Coastguard Worker
514*f6dc9357SAndroid Build Coastguard Worker switch (propID)
515*f6dc9357SAndroid Build Coastguard Worker {
516*f6dc9357SAndroid Build Coastguard Worker case kpidPath: TarStringToUnicode(item->Name, prop, true); break;
517*f6dc9357SAndroid Build Coastguard Worker case kpidIsDir: prop = item->IsDir(); break;
518*f6dc9357SAndroid Build Coastguard Worker case kpidSize: prop = item->Get_UnpackSize(); break;
519*f6dc9357SAndroid Build Coastguard Worker case kpidPackSize: prop = item->Get_PackSize_Aligned(); break;
520*f6dc9357SAndroid Build Coastguard Worker case kpidMTime:
521*f6dc9357SAndroid Build Coastguard Worker {
522*f6dc9357SAndroid Build Coastguard Worker /*
523*f6dc9357SAndroid Build Coastguard Worker // for debug:
524*f6dc9357SAndroid Build Coastguard Worker PropVariant_SetFrom_UnixTime(prop, 1 << 30);
525*f6dc9357SAndroid Build Coastguard Worker prop.wReserved1 = k_PropVar_TimePrec_Base + 1;
526*f6dc9357SAndroid Build Coastguard Worker prop.wReserved2 = 12;
527*f6dc9357SAndroid Build Coastguard Worker break;
528*f6dc9357SAndroid Build Coastguard Worker */
529*f6dc9357SAndroid Build Coastguard Worker
530*f6dc9357SAndroid Build Coastguard Worker if (item->PaxTimes.MTime.IsDefined())
531*f6dc9357SAndroid Build Coastguard Worker PaxTimeToProp(item->PaxTimes.MTime, prop);
532*f6dc9357SAndroid Build Coastguard Worker else
533*f6dc9357SAndroid Build Coastguard Worker // if (item->MTime != 0)
534*f6dc9357SAndroid Build Coastguard Worker {
535*f6dc9357SAndroid Build Coastguard Worker // we allow (item->MTime == 0)
536*f6dc9357SAndroid Build Coastguard Worker FILETIME ft;
537*f6dc9357SAndroid Build Coastguard Worker if (NTime::UnixTime64_To_FileTime(item->MTime, ft))
538*f6dc9357SAndroid Build Coastguard Worker {
539*f6dc9357SAndroid Build Coastguard Worker unsigned prec = k_PropVar_TimePrec_Unix;
540*f6dc9357SAndroid Build Coastguard Worker if (item->MTime_IsBin)
541*f6dc9357SAndroid Build Coastguard Worker {
542*f6dc9357SAndroid Build Coastguard Worker /* we report here that it's Int64-UnixTime
543*f6dc9357SAndroid Build Coastguard Worker instead of basic UInt32-UnixTime range */
544*f6dc9357SAndroid Build Coastguard Worker prec = k_PropVar_TimePrec_Base;
545*f6dc9357SAndroid Build Coastguard Worker }
546*f6dc9357SAndroid Build Coastguard Worker prop.SetAsTimeFrom_FT_Prec(ft, prec);
547*f6dc9357SAndroid Build Coastguard Worker }
548*f6dc9357SAndroid Build Coastguard Worker }
549*f6dc9357SAndroid Build Coastguard Worker break;
550*f6dc9357SAndroid Build Coastguard Worker }
551*f6dc9357SAndroid Build Coastguard Worker case kpidATime:
552*f6dc9357SAndroid Build Coastguard Worker if (item->PaxTimes.ATime.IsDefined())
553*f6dc9357SAndroid Build Coastguard Worker PaxTimeToProp(item->PaxTimes.ATime, prop);
554*f6dc9357SAndroid Build Coastguard Worker break;
555*f6dc9357SAndroid Build Coastguard Worker case kpidCTime:
556*f6dc9357SAndroid Build Coastguard Worker if (item->PaxTimes.CTime.IsDefined())
557*f6dc9357SAndroid Build Coastguard Worker PaxTimeToProp(item->PaxTimes.CTime, prop);
558*f6dc9357SAndroid Build Coastguard Worker break;
559*f6dc9357SAndroid Build Coastguard Worker case kpidPosixAttrib: prop = item->Get_Combined_Mode(); break;
560*f6dc9357SAndroid Build Coastguard Worker
561*f6dc9357SAndroid Build Coastguard Worker // kpidAttrib has priority over kpidPosixAttrib in 7-Zip.
562*f6dc9357SAndroid Build Coastguard Worker // but if we want kpidPosixAttrib priority for TAR, we disable kpidAttrib.
563*f6dc9357SAndroid Build Coastguard Worker #if 0
564*f6dc9357SAndroid Build Coastguard Worker case kpidAttrib:
565*f6dc9357SAndroid Build Coastguard Worker {
566*f6dc9357SAndroid Build Coastguard Worker if (!item->SCHILY_fflags.IsEmpty())
567*f6dc9357SAndroid Build Coastguard Worker {
568*f6dc9357SAndroid Build Coastguard Worker UInt32 attrib = 0;
569*f6dc9357SAndroid Build Coastguard Worker if (Parse_Attrib_from_SCHILY_fflags(item->SCHILY_fflags, attrib))
570*f6dc9357SAndroid Build Coastguard Worker {
571*f6dc9357SAndroid Build Coastguard Worker if (attrib != 0)
572*f6dc9357SAndroid Build Coastguard Worker {
573*f6dc9357SAndroid Build Coastguard Worker if (item->IsDir())
574*f6dc9357SAndroid Build Coastguard Worker attrib |= FILE_ATTRIBUTE_DIRECTORY;
575*f6dc9357SAndroid Build Coastguard Worker attrib |= ((UInt32)item->Get_Combined_Mode() << 16) | 0x8000; // FILE_ATTRIBUTE_UNIX_EXTENSION;
576*f6dc9357SAndroid Build Coastguard Worker prop = attrib;
577*f6dc9357SAndroid Build Coastguard Worker }
578*f6dc9357SAndroid Build Coastguard Worker }
579*f6dc9357SAndroid Build Coastguard Worker }
580*f6dc9357SAndroid Build Coastguard Worker break;
581*f6dc9357SAndroid Build Coastguard Worker }
582*f6dc9357SAndroid Build Coastguard Worker #endif
583*f6dc9357SAndroid Build Coastguard Worker
584*f6dc9357SAndroid Build Coastguard Worker case kpidUser:
585*f6dc9357SAndroid Build Coastguard Worker if (!item->User.IsEmpty())
586*f6dc9357SAndroid Build Coastguard Worker TarStringToUnicode(item->User, prop);
587*f6dc9357SAndroid Build Coastguard Worker break;
588*f6dc9357SAndroid Build Coastguard Worker case kpidGroup:
589*f6dc9357SAndroid Build Coastguard Worker if (!item->Group.IsEmpty())
590*f6dc9357SAndroid Build Coastguard Worker TarStringToUnicode(item->Group, prop);
591*f6dc9357SAndroid Build Coastguard Worker break;
592*f6dc9357SAndroid Build Coastguard Worker
593*f6dc9357SAndroid Build Coastguard Worker case kpidUserId:
594*f6dc9357SAndroid Build Coastguard Worker // if (item->UID != 0)
595*f6dc9357SAndroid Build Coastguard Worker prop = (UInt32)item->UID;
596*f6dc9357SAndroid Build Coastguard Worker break;
597*f6dc9357SAndroid Build Coastguard Worker case kpidGroupId:
598*f6dc9357SAndroid Build Coastguard Worker // if (item->GID != 0)
599*f6dc9357SAndroid Build Coastguard Worker prop = (UInt32)item->GID;
600*f6dc9357SAndroid Build Coastguard Worker break;
601*f6dc9357SAndroid Build Coastguard Worker
602*f6dc9357SAndroid Build Coastguard Worker case kpidDeviceMajor:
603*f6dc9357SAndroid Build Coastguard Worker if (item->DeviceMajor_Defined)
604*f6dc9357SAndroid Build Coastguard Worker // if (item->DeviceMajor != 0)
605*f6dc9357SAndroid Build Coastguard Worker prop = (UInt32)item->DeviceMajor;
606*f6dc9357SAndroid Build Coastguard Worker break;
607*f6dc9357SAndroid Build Coastguard Worker
608*f6dc9357SAndroid Build Coastguard Worker case kpidDeviceMinor:
609*f6dc9357SAndroid Build Coastguard Worker if (item->DeviceMinor_Defined)
610*f6dc9357SAndroid Build Coastguard Worker // if (item->DeviceMinor != 0)
611*f6dc9357SAndroid Build Coastguard Worker prop = (UInt32)item->DeviceMinor;
612*f6dc9357SAndroid Build Coastguard Worker break;
613*f6dc9357SAndroid Build Coastguard Worker /*
614*f6dc9357SAndroid Build Coastguard Worker case kpidDevice:
615*f6dc9357SAndroid Build Coastguard Worker if (item->DeviceMajor_Defined)
616*f6dc9357SAndroid Build Coastguard Worker if (item->DeviceMinor_Defined)
617*f6dc9357SAndroid Build Coastguard Worker prop = (UInt64)MY_dev_makedev(item->DeviceMajor, item->DeviceMinor);
618*f6dc9357SAndroid Build Coastguard Worker break;
619*f6dc9357SAndroid Build Coastguard Worker */
620*f6dc9357SAndroid Build Coastguard Worker
621*f6dc9357SAndroid Build Coastguard Worker case kpidSymLink:
622*f6dc9357SAndroid Build Coastguard Worker if (item->Is_SymLink())
623*f6dc9357SAndroid Build Coastguard Worker if (!item->LinkName.IsEmpty())
624*f6dc9357SAndroid Build Coastguard Worker TarStringToUnicode(item->LinkName, prop);
625*f6dc9357SAndroid Build Coastguard Worker break;
626*f6dc9357SAndroid Build Coastguard Worker case kpidHardLink:
627*f6dc9357SAndroid Build Coastguard Worker if (item->Is_HardLink())
628*f6dc9357SAndroid Build Coastguard Worker if (!item->LinkName.IsEmpty())
629*f6dc9357SAndroid Build Coastguard Worker TarStringToUnicode(item->LinkName, prop);
630*f6dc9357SAndroid Build Coastguard Worker break;
631*f6dc9357SAndroid Build Coastguard Worker
632*f6dc9357SAndroid Build Coastguard Worker case kpidCharacts:
633*f6dc9357SAndroid Build Coastguard Worker {
634*f6dc9357SAndroid Build Coastguard Worker AString s;
635*f6dc9357SAndroid Build Coastguard Worker {
636*f6dc9357SAndroid Build Coastguard Worker s.Add_Space_if_NotEmpty();
637*f6dc9357SAndroid Build Coastguard Worker AddSpecCharToString(item->LinkFlag, s);
638*f6dc9357SAndroid Build Coastguard Worker }
639*f6dc9357SAndroid Build Coastguard Worker if (item->IsMagic_GNU())
640*f6dc9357SAndroid Build Coastguard Worker s.Add_OptSpaced("GNU");
641*f6dc9357SAndroid Build Coastguard Worker else if (item->IsMagic_Posix_ustar_00())
642*f6dc9357SAndroid Build Coastguard Worker s.Add_OptSpaced("POSIX");
643*f6dc9357SAndroid Build Coastguard Worker else
644*f6dc9357SAndroid Build Coastguard Worker {
645*f6dc9357SAndroid Build Coastguard Worker s.Add_Space_if_NotEmpty();
646*f6dc9357SAndroid Build Coastguard Worker for (unsigned i = 0; i < sizeof(item->Magic); i++)
647*f6dc9357SAndroid Build Coastguard Worker AddSpecCharToString(item->Magic[i], s);
648*f6dc9357SAndroid Build Coastguard Worker }
649*f6dc9357SAndroid Build Coastguard Worker
650*f6dc9357SAndroid Build Coastguard Worker if (item->IsSignedChecksum)
651*f6dc9357SAndroid Build Coastguard Worker s.Add_OptSpaced("SignedChecksum");
652*f6dc9357SAndroid Build Coastguard Worker
653*f6dc9357SAndroid Build Coastguard Worker if (item->Prefix_WasUsed)
654*f6dc9357SAndroid Build Coastguard Worker s.Add_OptSpaced(k_Characts_Prefix);
655*f6dc9357SAndroid Build Coastguard Worker
656*f6dc9357SAndroid Build Coastguard Worker s.Add_OptSpaced(item->EncodingCharacts.GetCharactsString());
657*f6dc9357SAndroid Build Coastguard Worker
658*f6dc9357SAndroid Build Coastguard Worker // AddSpecUInt64(s, "LongName", item->Num_LongName_Records);
659*f6dc9357SAndroid Build Coastguard Worker // AddSpecUInt64(s, "LongLink", item->Num_LongLink_Records);
660*f6dc9357SAndroid Build Coastguard Worker AddSpecBools(s, "LongName", item->LongName_WasUsed, item->LongName_WasUsed_2);
661*f6dc9357SAndroid Build Coastguard Worker AddSpecBools(s, "LongLink", item->LongLink_WasUsed, item->LongLink_WasUsed_2);
662*f6dc9357SAndroid Build Coastguard Worker
663*f6dc9357SAndroid Build Coastguard Worker if (item->MTime_IsBin)
664*f6dc9357SAndroid Build Coastguard Worker s.Add_OptSpaced("bin_mtime");
665*f6dc9357SAndroid Build Coastguard Worker if (item->PackSize_IsBin)
666*f6dc9357SAndroid Build Coastguard Worker s.Add_OptSpaced("bin_psize");
667*f6dc9357SAndroid Build Coastguard Worker if (item->Size_IsBin)
668*f6dc9357SAndroid Build Coastguard Worker s.Add_OptSpaced("bin_size");
669*f6dc9357SAndroid Build Coastguard Worker
670*f6dc9357SAndroid Build Coastguard Worker AddSpecUInt64(s, "PAX", item->Num_Pax_Records);
671*f6dc9357SAndroid Build Coastguard Worker
672*f6dc9357SAndroid Build Coastguard Worker if (item->PaxTimes.MTime.IsDefined()) s.Add_OptSpaced("mtime");
673*f6dc9357SAndroid Build Coastguard Worker if (item->PaxTimes.ATime.IsDefined()) s.Add_OptSpaced("atime");
674*f6dc9357SAndroid Build Coastguard Worker if (item->PaxTimes.CTime.IsDefined()) s.Add_OptSpaced("ctime");
675*f6dc9357SAndroid Build Coastguard Worker
676*f6dc9357SAndroid Build Coastguard Worker if (item->pax_path_WasUsed)
677*f6dc9357SAndroid Build Coastguard Worker s.Add_OptSpaced("pax_path");
678*f6dc9357SAndroid Build Coastguard Worker if (item->pax_link_WasUsed)
679*f6dc9357SAndroid Build Coastguard Worker s.Add_OptSpaced("pax_linkpath");
680*f6dc9357SAndroid Build Coastguard Worker if (item->pax_size_WasUsed)
681*f6dc9357SAndroid Build Coastguard Worker s.Add_OptSpaced("pax_size");
682*f6dc9357SAndroid Build Coastguard Worker if (!item->SCHILY_fflags.IsEmpty())
683*f6dc9357SAndroid Build Coastguard Worker {
684*f6dc9357SAndroid Build Coastguard Worker s.Add_OptSpaced("SCHILY.fflags=");
685*f6dc9357SAndroid Build Coastguard Worker s += item->SCHILY_fflags;
686*f6dc9357SAndroid Build Coastguard Worker }
687*f6dc9357SAndroid Build Coastguard Worker if (item->IsThereWarning())
688*f6dc9357SAndroid Build Coastguard Worker s.Add_OptSpaced("WARNING");
689*f6dc9357SAndroid Build Coastguard Worker if (item->HeaderError)
690*f6dc9357SAndroid Build Coastguard Worker s.Add_OptSpaced("ERROR");
691*f6dc9357SAndroid Build Coastguard Worker if (item->Pax_Error)
692*f6dc9357SAndroid Build Coastguard Worker s.Add_OptSpaced("PAX_error");
693*f6dc9357SAndroid Build Coastguard Worker if (!item->PaxExtra.RawLines.IsEmpty())
694*f6dc9357SAndroid Build Coastguard Worker s.Add_OptSpaced("PAX_unsupported_line");
695*f6dc9357SAndroid Build Coastguard Worker if (item->Pax_Overflow)
696*f6dc9357SAndroid Build Coastguard Worker s.Add_OptSpaced("PAX_overflow");
697*f6dc9357SAndroid Build Coastguard Worker if (!s.IsEmpty())
698*f6dc9357SAndroid Build Coastguard Worker prop = s;
699*f6dc9357SAndroid Build Coastguard Worker break;
700*f6dc9357SAndroid Build Coastguard Worker }
701*f6dc9357SAndroid Build Coastguard Worker case kpidComment:
702*f6dc9357SAndroid Build Coastguard Worker {
703*f6dc9357SAndroid Build Coastguard Worker AString s;
704*f6dc9357SAndroid Build Coastguard Worker item->PaxExtra.Print_To_String(s);
705*f6dc9357SAndroid Build Coastguard Worker if (!s.IsEmpty())
706*f6dc9357SAndroid Build Coastguard Worker prop = s;
707*f6dc9357SAndroid Build Coastguard Worker break;
708*f6dc9357SAndroid Build Coastguard Worker }
709*f6dc9357SAndroid Build Coastguard Worker // case kpidHeadersSize: prop = item->HeaderSize; break; // for debug
710*f6dc9357SAndroid Build Coastguard Worker // case kpidOffset: prop = item->HeaderPos; break; // for debug
711*f6dc9357SAndroid Build Coastguard Worker default: break;
712*f6dc9357SAndroid Build Coastguard Worker }
713*f6dc9357SAndroid Build Coastguard Worker prop.Detach(value);
714*f6dc9357SAndroid Build Coastguard Worker return S_OK;
715*f6dc9357SAndroid Build Coastguard Worker COM_TRY_END
716*f6dc9357SAndroid Build Coastguard Worker }
717*f6dc9357SAndroid Build Coastguard Worker
718*f6dc9357SAndroid Build Coastguard Worker
Z7_COM7F_IMF(CHandler::Extract (const UInt32 * indices,UInt32 numItems,Int32 testMode,IArchiveExtractCallback * extractCallback))719*f6dc9357SAndroid Build Coastguard Worker Z7_COM7F_IMF(CHandler::Extract(const UInt32 *indices, UInt32 numItems,
720*f6dc9357SAndroid Build Coastguard Worker Int32 testMode, IArchiveExtractCallback *extractCallback))
721*f6dc9357SAndroid Build Coastguard Worker {
722*f6dc9357SAndroid Build Coastguard Worker COM_TRY_BEGIN
723*f6dc9357SAndroid Build Coastguard Worker ISequentialInStream *stream = _seqStream;
724*f6dc9357SAndroid Build Coastguard Worker const bool seqMode = (_stream == NULL);
725*f6dc9357SAndroid Build Coastguard Worker if (!seqMode)
726*f6dc9357SAndroid Build Coastguard Worker stream = _stream;
727*f6dc9357SAndroid Build Coastguard Worker
728*f6dc9357SAndroid Build Coastguard Worker const bool allFilesMode = (numItems == (UInt32)(Int32)-1);
729*f6dc9357SAndroid Build Coastguard Worker if (allFilesMode)
730*f6dc9357SAndroid Build Coastguard Worker numItems = _items.Size();
731*f6dc9357SAndroid Build Coastguard Worker if (_stream && numItems == 0)
732*f6dc9357SAndroid Build Coastguard Worker return S_OK;
733*f6dc9357SAndroid Build Coastguard Worker UInt64 totalSize = 0;
734*f6dc9357SAndroid Build Coastguard Worker UInt32 i;
735*f6dc9357SAndroid Build Coastguard Worker for (i = 0; i < numItems; i++)
736*f6dc9357SAndroid Build Coastguard Worker totalSize += _items[allFilesMode ? i : indices[i]].Get_UnpackSize();
737*f6dc9357SAndroid Build Coastguard Worker RINOK(extractCallback->SetTotal(totalSize))
738*f6dc9357SAndroid Build Coastguard Worker
739*f6dc9357SAndroid Build Coastguard Worker UInt64 totalPackSize;
740*f6dc9357SAndroid Build Coastguard Worker totalSize = totalPackSize = 0;
741*f6dc9357SAndroid Build Coastguard Worker
742*f6dc9357SAndroid Build Coastguard Worker CMyComPtr2_Create<ICompressProgressInfo, CLocalProgress> lps;
743*f6dc9357SAndroid Build Coastguard Worker lps->Init(extractCallback, false);
744*f6dc9357SAndroid Build Coastguard Worker CMyComPtr2_Create<ISequentialInStream, CLimitedSequentialInStream> inStream;
745*f6dc9357SAndroid Build Coastguard Worker inStream->SetStream(stream);
746*f6dc9357SAndroid Build Coastguard Worker CMyComPtr2_Create<ISequentialOutStream, CLimitedSequentialOutStream> outStreamSpec;
747*f6dc9357SAndroid Build Coastguard Worker
748*f6dc9357SAndroid Build Coastguard Worker for (i = 0; ; i++)
749*f6dc9357SAndroid Build Coastguard Worker {
750*f6dc9357SAndroid Build Coastguard Worker lps->InSize = totalPackSize;
751*f6dc9357SAndroid Build Coastguard Worker lps->OutSize = totalSize;
752*f6dc9357SAndroid Build Coastguard Worker RINOK(lps->SetCur())
753*f6dc9357SAndroid Build Coastguard Worker if (i >= numItems && !seqMode)
754*f6dc9357SAndroid Build Coastguard Worker break;
755*f6dc9357SAndroid Build Coastguard Worker const UInt32 index = allFilesMode ? i : indices[i];
756*f6dc9357SAndroid Build Coastguard Worker const CItemEx *item;
757*f6dc9357SAndroid Build Coastguard Worker if (seqMode)
758*f6dc9357SAndroid Build Coastguard Worker {
759*f6dc9357SAndroid Build Coastguard Worker const HRESULT res = SkipTo(index);
760*f6dc9357SAndroid Build Coastguard Worker if (res == E_INVALIDARG)
761*f6dc9357SAndroid Build Coastguard Worker break;
762*f6dc9357SAndroid Build Coastguard Worker RINOK(res)
763*f6dc9357SAndroid Build Coastguard Worker item = &_latestItem;
764*f6dc9357SAndroid Build Coastguard Worker }
765*f6dc9357SAndroid Build Coastguard Worker else
766*f6dc9357SAndroid Build Coastguard Worker item = &_items[index];
767*f6dc9357SAndroid Build Coastguard Worker
768*f6dc9357SAndroid Build Coastguard Worker Int32 askMode = testMode ?
769*f6dc9357SAndroid Build Coastguard Worker NExtract::NAskMode::kTest :
770*f6dc9357SAndroid Build Coastguard Worker NExtract::NAskMode::kExtract;
771*f6dc9357SAndroid Build Coastguard Worker CMyComPtr<ISequentialOutStream> realOutStream;
772*f6dc9357SAndroid Build Coastguard Worker RINOK(extractCallback->GetStream(index, &realOutStream, askMode))
773*f6dc9357SAndroid Build Coastguard Worker const UInt64 unpackSize = item->Get_UnpackSize();
774*f6dc9357SAndroid Build Coastguard Worker totalSize += unpackSize;
775*f6dc9357SAndroid Build Coastguard Worker totalPackSize += item->Get_PackSize_Aligned();
776*f6dc9357SAndroid Build Coastguard Worker if (item->IsDir())
777*f6dc9357SAndroid Build Coastguard Worker {
778*f6dc9357SAndroid Build Coastguard Worker RINOK(extractCallback->PrepareOperation(askMode))
779*f6dc9357SAndroid Build Coastguard Worker // realOutStream.Release();
780*f6dc9357SAndroid Build Coastguard Worker RINOK(extractCallback->SetOperationResult(NExtract::NOperationResult::kOK))
781*f6dc9357SAndroid Build Coastguard Worker continue;
782*f6dc9357SAndroid Build Coastguard Worker }
783*f6dc9357SAndroid Build Coastguard Worker bool skipMode = false;
784*f6dc9357SAndroid Build Coastguard Worker if (!testMode && !realOutStream)
785*f6dc9357SAndroid Build Coastguard Worker {
786*f6dc9357SAndroid Build Coastguard Worker if (!seqMode)
787*f6dc9357SAndroid Build Coastguard Worker {
788*f6dc9357SAndroid Build Coastguard Worker /*
789*f6dc9357SAndroid Build Coastguard Worker // GetStream() creates link.
790*f6dc9357SAndroid Build Coastguard Worker // so we can show extracting info in GetStream() instead
791*f6dc9357SAndroid Build Coastguard Worker if (item->Is_HardLink() ||
792*f6dc9357SAndroid Build Coastguard Worker item->Is_SymLink())
793*f6dc9357SAndroid Build Coastguard Worker {
794*f6dc9357SAndroid Build Coastguard Worker RINOK(extractCallback->PrepareOperation(askMode))
795*f6dc9357SAndroid Build Coastguard Worker RINOK(extractCallback->SetOperationResult(NExtract::NOperationResult::kOK))
796*f6dc9357SAndroid Build Coastguard Worker }
797*f6dc9357SAndroid Build Coastguard Worker */
798*f6dc9357SAndroid Build Coastguard Worker continue;
799*f6dc9357SAndroid Build Coastguard Worker }
800*f6dc9357SAndroid Build Coastguard Worker skipMode = true;
801*f6dc9357SAndroid Build Coastguard Worker askMode = NExtract::NAskMode::kSkip;
802*f6dc9357SAndroid Build Coastguard Worker }
803*f6dc9357SAndroid Build Coastguard Worker RINOK(extractCallback->PrepareOperation(askMode))
804*f6dc9357SAndroid Build Coastguard Worker
805*f6dc9357SAndroid Build Coastguard Worker outStreamSpec->SetStream(realOutStream);
806*f6dc9357SAndroid Build Coastguard Worker realOutStream.Release();
807*f6dc9357SAndroid Build Coastguard Worker outStreamSpec->Init(skipMode ? 0 : unpackSize, true);
808*f6dc9357SAndroid Build Coastguard Worker
809*f6dc9357SAndroid Build Coastguard Worker Int32 opRes = NExtract::NOperationResult::kOK;
810*f6dc9357SAndroid Build Coastguard Worker CMyComPtr<ISequentialInStream> inStream2;
811*f6dc9357SAndroid Build Coastguard Worker if (!item->Is_Sparse())
812*f6dc9357SAndroid Build Coastguard Worker inStream2 = inStream;
813*f6dc9357SAndroid Build Coastguard Worker else
814*f6dc9357SAndroid Build Coastguard Worker {
815*f6dc9357SAndroid Build Coastguard Worker GetStream(index, &inStream2);
816*f6dc9357SAndroid Build Coastguard Worker if (!inStream2)
817*f6dc9357SAndroid Build Coastguard Worker return E_FAIL;
818*f6dc9357SAndroid Build Coastguard Worker }
819*f6dc9357SAndroid Build Coastguard Worker
820*f6dc9357SAndroid Build Coastguard Worker {
821*f6dc9357SAndroid Build Coastguard Worker if (item->Is_SymLink())
822*f6dc9357SAndroid Build Coastguard Worker {
823*f6dc9357SAndroid Build Coastguard Worker RINOK(WriteStream(outStreamSpec, (const char *)item->LinkName, item->LinkName.Len()))
824*f6dc9357SAndroid Build Coastguard Worker }
825*f6dc9357SAndroid Build Coastguard Worker else
826*f6dc9357SAndroid Build Coastguard Worker {
827*f6dc9357SAndroid Build Coastguard Worker if (!seqMode)
828*f6dc9357SAndroid Build Coastguard Worker {
829*f6dc9357SAndroid Build Coastguard Worker RINOK(InStream_SeekSet(_stream, item->Get_DataPos()))
830*f6dc9357SAndroid Build Coastguard Worker }
831*f6dc9357SAndroid Build Coastguard Worker inStream->Init(item->Get_PackSize_Aligned());
832*f6dc9357SAndroid Build Coastguard Worker RINOK(copyCoder.Interface()->Code(inStream2, outStreamSpec, NULL, NULL, lps))
833*f6dc9357SAndroid Build Coastguard Worker }
834*f6dc9357SAndroid Build Coastguard Worker if (outStreamSpec->GetRem() != 0)
835*f6dc9357SAndroid Build Coastguard Worker opRes = NExtract::NOperationResult::kDataError;
836*f6dc9357SAndroid Build Coastguard Worker }
837*f6dc9357SAndroid Build Coastguard Worker if (seqMode)
838*f6dc9357SAndroid Build Coastguard Worker {
839*f6dc9357SAndroid Build Coastguard Worker _latestIsRead = false;
840*f6dc9357SAndroid Build Coastguard Worker _curIndex++;
841*f6dc9357SAndroid Build Coastguard Worker }
842*f6dc9357SAndroid Build Coastguard Worker outStreamSpec->ReleaseStream();
843*f6dc9357SAndroid Build Coastguard Worker RINOK(extractCallback->SetOperationResult(opRes))
844*f6dc9357SAndroid Build Coastguard Worker }
845*f6dc9357SAndroid Build Coastguard Worker return S_OK;
846*f6dc9357SAndroid Build Coastguard Worker COM_TRY_END
847*f6dc9357SAndroid Build Coastguard Worker }
848*f6dc9357SAndroid Build Coastguard Worker
849*f6dc9357SAndroid Build Coastguard Worker
850*f6dc9357SAndroid Build Coastguard Worker Z7_CLASS_IMP_IInStream(
851*f6dc9357SAndroid Build Coastguard Worker CSparseStream
852*f6dc9357SAndroid Build Coastguard Worker )
853*f6dc9357SAndroid Build Coastguard Worker UInt64 _phyPos;
854*f6dc9357SAndroid Build Coastguard Worker UInt64 _virtPos;
855*f6dc9357SAndroid Build Coastguard Worker bool _needStartSeek;
856*f6dc9357SAndroid Build Coastguard Worker
857*f6dc9357SAndroid Build Coastguard Worker public:
858*f6dc9357SAndroid Build Coastguard Worker CHandler *Handler;
859*f6dc9357SAndroid Build Coastguard Worker CMyComPtr<IUnknown> HandlerRef;
860*f6dc9357SAndroid Build Coastguard Worker unsigned ItemIndex;
861*f6dc9357SAndroid Build Coastguard Worker CRecordVector<UInt64> PhyOffsets;
862*f6dc9357SAndroid Build Coastguard Worker
863*f6dc9357SAndroid Build Coastguard Worker void Init()
864*f6dc9357SAndroid Build Coastguard Worker {
865*f6dc9357SAndroid Build Coastguard Worker _virtPos = 0;
866*f6dc9357SAndroid Build Coastguard Worker _phyPos = 0;
867*f6dc9357SAndroid Build Coastguard Worker _needStartSeek = true;
868*f6dc9357SAndroid Build Coastguard Worker }
869*f6dc9357SAndroid Build Coastguard Worker };
870*f6dc9357SAndroid Build Coastguard Worker
871*f6dc9357SAndroid Build Coastguard Worker
872*f6dc9357SAndroid Build Coastguard Worker Z7_COM7F_IMF(CSparseStream::Read(void *data, UInt32 size, UInt32 *processedSize))
873*f6dc9357SAndroid Build Coastguard Worker {
874*f6dc9357SAndroid Build Coastguard Worker if (processedSize)
875*f6dc9357SAndroid Build Coastguard Worker *processedSize = 0;
876*f6dc9357SAndroid Build Coastguard Worker if (size == 0)
877*f6dc9357SAndroid Build Coastguard Worker return S_OK;
878*f6dc9357SAndroid Build Coastguard Worker const CItemEx &item = Handler->_items[ItemIndex];
879*f6dc9357SAndroid Build Coastguard Worker if (_virtPos >= item.Size)
880*f6dc9357SAndroid Build Coastguard Worker return S_OK;
881*f6dc9357SAndroid Build Coastguard Worker {
882*f6dc9357SAndroid Build Coastguard Worker UInt64 rem = item.Size - _virtPos;
883*f6dc9357SAndroid Build Coastguard Worker if (size > rem)
884*f6dc9357SAndroid Build Coastguard Worker size = (UInt32)rem;
885*f6dc9357SAndroid Build Coastguard Worker }
886*f6dc9357SAndroid Build Coastguard Worker
887*f6dc9357SAndroid Build Coastguard Worker HRESULT res = S_OK;
888*f6dc9357SAndroid Build Coastguard Worker
889*f6dc9357SAndroid Build Coastguard Worker if (item.SparseBlocks.IsEmpty())
890*f6dc9357SAndroid Build Coastguard Worker memset(data, 0, size);
891*f6dc9357SAndroid Build Coastguard Worker else
892*f6dc9357SAndroid Build Coastguard Worker {
893*f6dc9357SAndroid Build Coastguard Worker unsigned left = 0, right = item.SparseBlocks.Size();
894*f6dc9357SAndroid Build Coastguard Worker for (;;)
895*f6dc9357SAndroid Build Coastguard Worker {
896*f6dc9357SAndroid Build Coastguard Worker const unsigned mid = (unsigned)(((size_t)left + (size_t)right) / 2);
897*f6dc9357SAndroid Build Coastguard Worker if (mid == left)
898*f6dc9357SAndroid Build Coastguard Worker break;
899*f6dc9357SAndroid Build Coastguard Worker if (_virtPos < item.SparseBlocks[mid].Offset)
900*f6dc9357SAndroid Build Coastguard Worker right = mid;
901*f6dc9357SAndroid Build Coastguard Worker else
902*f6dc9357SAndroid Build Coastguard Worker left = mid;
903*f6dc9357SAndroid Build Coastguard Worker }
904*f6dc9357SAndroid Build Coastguard Worker
905*f6dc9357SAndroid Build Coastguard Worker const CSparseBlock &sb = item.SparseBlocks[left];
906*f6dc9357SAndroid Build Coastguard Worker UInt64 relat = _virtPos - sb.Offset;
907*f6dc9357SAndroid Build Coastguard Worker
908*f6dc9357SAndroid Build Coastguard Worker if (_virtPos >= sb.Offset && relat < sb.Size)
909*f6dc9357SAndroid Build Coastguard Worker {
910*f6dc9357SAndroid Build Coastguard Worker UInt64 rem = sb.Size - relat;
911*f6dc9357SAndroid Build Coastguard Worker if (size > rem)
912*f6dc9357SAndroid Build Coastguard Worker size = (UInt32)rem;
913*f6dc9357SAndroid Build Coastguard Worker UInt64 phyPos = PhyOffsets[left] + relat;
914*f6dc9357SAndroid Build Coastguard Worker if (_needStartSeek || _phyPos != phyPos)
915*f6dc9357SAndroid Build Coastguard Worker {
916*f6dc9357SAndroid Build Coastguard Worker RINOK(InStream_SeekSet(Handler->_stream, (item.Get_DataPos() + phyPos)))
917*f6dc9357SAndroid Build Coastguard Worker _needStartSeek = false;
918*f6dc9357SAndroid Build Coastguard Worker _phyPos = phyPos;
919*f6dc9357SAndroid Build Coastguard Worker }
920*f6dc9357SAndroid Build Coastguard Worker res = Handler->_stream->Read(data, size, &size);
921*f6dc9357SAndroid Build Coastguard Worker _phyPos += size;
922*f6dc9357SAndroid Build Coastguard Worker }
923*f6dc9357SAndroid Build Coastguard Worker else
924*f6dc9357SAndroid Build Coastguard Worker {
925*f6dc9357SAndroid Build Coastguard Worker UInt64 next = item.Size;
926*f6dc9357SAndroid Build Coastguard Worker if (_virtPos < sb.Offset)
927*f6dc9357SAndroid Build Coastguard Worker next = sb.Offset;
928*f6dc9357SAndroid Build Coastguard Worker else if (left + 1 < item.SparseBlocks.Size())
929*f6dc9357SAndroid Build Coastguard Worker next = item.SparseBlocks[left + 1].Offset;
930*f6dc9357SAndroid Build Coastguard Worker UInt64 rem = next - _virtPos;
931*f6dc9357SAndroid Build Coastguard Worker if (size > rem)
932*f6dc9357SAndroid Build Coastguard Worker size = (UInt32)rem;
933*f6dc9357SAndroid Build Coastguard Worker memset(data, 0, size);
934*f6dc9357SAndroid Build Coastguard Worker }
935*f6dc9357SAndroid Build Coastguard Worker }
936*f6dc9357SAndroid Build Coastguard Worker
937*f6dc9357SAndroid Build Coastguard Worker _virtPos += size;
938*f6dc9357SAndroid Build Coastguard Worker if (processedSize)
939*f6dc9357SAndroid Build Coastguard Worker *processedSize = size;
940*f6dc9357SAndroid Build Coastguard Worker return res;
941*f6dc9357SAndroid Build Coastguard Worker }
942*f6dc9357SAndroid Build Coastguard Worker
943*f6dc9357SAndroid Build Coastguard Worker Z7_COM7F_IMF(CSparseStream::Seek(Int64 offset, UInt32 seekOrigin, UInt64 *newPosition))
944*f6dc9357SAndroid Build Coastguard Worker {
945*f6dc9357SAndroid Build Coastguard Worker switch (seekOrigin)
946*f6dc9357SAndroid Build Coastguard Worker {
947*f6dc9357SAndroid Build Coastguard Worker case STREAM_SEEK_SET: break;
948*f6dc9357SAndroid Build Coastguard Worker case STREAM_SEEK_CUR: offset += _virtPos; break;
949*f6dc9357SAndroid Build Coastguard Worker case STREAM_SEEK_END: offset += Handler->_items[ItemIndex].Size; break;
950*f6dc9357SAndroid Build Coastguard Worker default: return STG_E_INVALIDFUNCTION;
951*f6dc9357SAndroid Build Coastguard Worker }
952*f6dc9357SAndroid Build Coastguard Worker if (offset < 0)
953*f6dc9357SAndroid Build Coastguard Worker return HRESULT_WIN32_ERROR_NEGATIVE_SEEK;
954*f6dc9357SAndroid Build Coastguard Worker _virtPos = (UInt64)offset;
955*f6dc9357SAndroid Build Coastguard Worker if (newPosition)
956*f6dc9357SAndroid Build Coastguard Worker *newPosition = _virtPos;
957*f6dc9357SAndroid Build Coastguard Worker return S_OK;
958*f6dc9357SAndroid Build Coastguard Worker }
959*f6dc9357SAndroid Build Coastguard Worker
960*f6dc9357SAndroid Build Coastguard Worker Z7_COM7F_IMF(CHandler::GetStream(UInt32 index, ISequentialInStream **stream))
961*f6dc9357SAndroid Build Coastguard Worker {
962*f6dc9357SAndroid Build Coastguard Worker COM_TRY_BEGIN
963*f6dc9357SAndroid Build Coastguard Worker
964*f6dc9357SAndroid Build Coastguard Worker const CItemEx &item = _items[index];
965*f6dc9357SAndroid Build Coastguard Worker
966*f6dc9357SAndroid Build Coastguard Worker if (item.Is_Sparse())
967*f6dc9357SAndroid Build Coastguard Worker {
968*f6dc9357SAndroid Build Coastguard Worker CSparseStream *streamSpec = new CSparseStream;
969*f6dc9357SAndroid Build Coastguard Worker CMyComPtr<IInStream> streamTemp = streamSpec;
970*f6dc9357SAndroid Build Coastguard Worker streamSpec->Init();
971*f6dc9357SAndroid Build Coastguard Worker streamSpec->Handler = this;
972*f6dc9357SAndroid Build Coastguard Worker streamSpec->HandlerRef = (IInArchive *)this;
973*f6dc9357SAndroid Build Coastguard Worker streamSpec->ItemIndex = index;
974*f6dc9357SAndroid Build Coastguard Worker streamSpec->PhyOffsets.Reserve(item.SparseBlocks.Size());
975*f6dc9357SAndroid Build Coastguard Worker UInt64 offs = 0;
976*f6dc9357SAndroid Build Coastguard Worker FOR_VECTOR(i, item.SparseBlocks)
977*f6dc9357SAndroid Build Coastguard Worker {
978*f6dc9357SAndroid Build Coastguard Worker const CSparseBlock &sb = item.SparseBlocks[i];
979*f6dc9357SAndroid Build Coastguard Worker streamSpec->PhyOffsets.AddInReserved(offs);
980*f6dc9357SAndroid Build Coastguard Worker offs += sb.Size;
981*f6dc9357SAndroid Build Coastguard Worker }
982*f6dc9357SAndroid Build Coastguard Worker *stream = streamTemp.Detach();
983*f6dc9357SAndroid Build Coastguard Worker return S_OK;
984*f6dc9357SAndroid Build Coastguard Worker }
985*f6dc9357SAndroid Build Coastguard Worker
986*f6dc9357SAndroid Build Coastguard Worker if (item.Is_SymLink())
987*f6dc9357SAndroid Build Coastguard Worker {
988*f6dc9357SAndroid Build Coastguard Worker Create_BufInStream_WithReference((const Byte *)(const char *)item.LinkName, item.LinkName.Len(), (IInArchive *)this, stream);
989*f6dc9357SAndroid Build Coastguard Worker return S_OK;
990*f6dc9357SAndroid Build Coastguard Worker }
991*f6dc9357SAndroid Build Coastguard Worker
992*f6dc9357SAndroid Build Coastguard Worker return CreateLimitedInStream(_stream, item.Get_DataPos(), item.PackSize, stream);
993*f6dc9357SAndroid Build Coastguard Worker
994*f6dc9357SAndroid Build Coastguard Worker COM_TRY_END
995*f6dc9357SAndroid Build Coastguard Worker }
996*f6dc9357SAndroid Build Coastguard Worker
997*f6dc9357SAndroid Build Coastguard Worker
998*f6dc9357SAndroid Build Coastguard Worker void CHandler::Init()
999*f6dc9357SAndroid Build Coastguard Worker {
1000*f6dc9357SAndroid Build Coastguard Worker _forceCodePage = false;
1001*f6dc9357SAndroid Build Coastguard Worker _curCodePage = _specifiedCodePage = CP_UTF8; // CP_OEMCP;
1002*f6dc9357SAndroid Build Coastguard Worker _posixMode = false;
1003*f6dc9357SAndroid Build Coastguard Worker _posixMode_WasForced = false;
1004*f6dc9357SAndroid Build Coastguard Worker // TimeOptions.Clear();
1005*f6dc9357SAndroid Build Coastguard Worker _handlerTimeOptions.Init();
1006*f6dc9357SAndroid Build Coastguard Worker // _handlerTimeOptions.Write_MTime.Val = true; // it's default already
1007*f6dc9357SAndroid Build Coastguard Worker }
1008*f6dc9357SAndroid Build Coastguard Worker
1009*f6dc9357SAndroid Build Coastguard Worker
1010*f6dc9357SAndroid Build Coastguard Worker Z7_COM7F_IMF(CHandler::SetProperties(const wchar_t * const *names, const PROPVARIANT *values, UInt32 numProps))
1011*f6dc9357SAndroid Build Coastguard Worker {
1012*f6dc9357SAndroid Build Coastguard Worker Init();
1013*f6dc9357SAndroid Build Coastguard Worker
1014*f6dc9357SAndroid Build Coastguard Worker for (UInt32 i = 0; i < numProps; i++)
1015*f6dc9357SAndroid Build Coastguard Worker {
1016*f6dc9357SAndroid Build Coastguard Worker UString name = names[i];
1017*f6dc9357SAndroid Build Coastguard Worker name.MakeLower_Ascii();
1018*f6dc9357SAndroid Build Coastguard Worker if (name.IsEmpty())
1019*f6dc9357SAndroid Build Coastguard Worker return E_INVALIDARG;
1020*f6dc9357SAndroid Build Coastguard Worker
1021*f6dc9357SAndroid Build Coastguard Worker const PROPVARIANT &prop = values[i];
1022*f6dc9357SAndroid Build Coastguard Worker
1023*f6dc9357SAndroid Build Coastguard Worker if (name[0] == L'x')
1024*f6dc9357SAndroid Build Coastguard Worker {
1025*f6dc9357SAndroid Build Coastguard Worker // some clients write 'x' property. So we support it
1026*f6dc9357SAndroid Build Coastguard Worker UInt32 level = 0;
1027*f6dc9357SAndroid Build Coastguard Worker RINOK(ParsePropToUInt32(name.Ptr(1), prop, level))
1028*f6dc9357SAndroid Build Coastguard Worker }
1029*f6dc9357SAndroid Build Coastguard Worker else if (name.IsEqualTo("cp"))
1030*f6dc9357SAndroid Build Coastguard Worker {
1031*f6dc9357SAndroid Build Coastguard Worker UInt32 cp = CP_OEMCP;
1032*f6dc9357SAndroid Build Coastguard Worker RINOK(ParsePropToUInt32(L"", prop, cp))
1033*f6dc9357SAndroid Build Coastguard Worker _forceCodePage = true;
1034*f6dc9357SAndroid Build Coastguard Worker _curCodePage = _specifiedCodePage = cp;
1035*f6dc9357SAndroid Build Coastguard Worker }
1036*f6dc9357SAndroid Build Coastguard Worker else if (name.IsPrefixedBy_Ascii_NoCase("mt"))
1037*f6dc9357SAndroid Build Coastguard Worker {
1038*f6dc9357SAndroid Build Coastguard Worker }
1039*f6dc9357SAndroid Build Coastguard Worker else if (name.IsPrefixedBy_Ascii_NoCase("memuse"))
1040*f6dc9357SAndroid Build Coastguard Worker {
1041*f6dc9357SAndroid Build Coastguard Worker }
1042*f6dc9357SAndroid Build Coastguard Worker else if (name.IsEqualTo("m"))
1043*f6dc9357SAndroid Build Coastguard Worker {
1044*f6dc9357SAndroid Build Coastguard Worker if (prop.vt != VT_BSTR)
1045*f6dc9357SAndroid Build Coastguard Worker return E_INVALIDARG;
1046*f6dc9357SAndroid Build Coastguard Worker const UString s = prop.bstrVal;
1047*f6dc9357SAndroid Build Coastguard Worker if (s.IsEqualTo_Ascii_NoCase("pax") ||
1048*f6dc9357SAndroid Build Coastguard Worker s.IsEqualTo_Ascii_NoCase("posix"))
1049*f6dc9357SAndroid Build Coastguard Worker _posixMode = true;
1050*f6dc9357SAndroid Build Coastguard Worker else if (s.IsEqualTo_Ascii_NoCase("gnu"))
1051*f6dc9357SAndroid Build Coastguard Worker _posixMode = false;
1052*f6dc9357SAndroid Build Coastguard Worker else
1053*f6dc9357SAndroid Build Coastguard Worker return E_INVALIDARG;
1054*f6dc9357SAndroid Build Coastguard Worker _posixMode_WasForced = true;
1055*f6dc9357SAndroid Build Coastguard Worker }
1056*f6dc9357SAndroid Build Coastguard Worker else
1057*f6dc9357SAndroid Build Coastguard Worker {
1058*f6dc9357SAndroid Build Coastguard Worker /*
1059*f6dc9357SAndroid Build Coastguard Worker if (name.IsPrefixedBy_Ascii_NoCase("td"))
1060*f6dc9357SAndroid Build Coastguard Worker {
1061*f6dc9357SAndroid Build Coastguard Worker name.Delete(0, 3);
1062*f6dc9357SAndroid Build Coastguard Worker if (prop.vt == VT_EMPTY)
1063*f6dc9357SAndroid Build Coastguard Worker {
1064*f6dc9357SAndroid Build Coastguard Worker if (name.IsEqualTo_Ascii_NoCase("n"))
1065*f6dc9357SAndroid Build Coastguard Worker {
1066*f6dc9357SAndroid Build Coastguard Worker // TimeOptions.UseNativeDigits = true;
1067*f6dc9357SAndroid Build Coastguard Worker }
1068*f6dc9357SAndroid Build Coastguard Worker else if (name.IsEqualTo_Ascii_NoCase("r"))
1069*f6dc9357SAndroid Build Coastguard Worker {
1070*f6dc9357SAndroid Build Coastguard Worker // TimeOptions.RemoveZeroDigits = true;
1071*f6dc9357SAndroid Build Coastguard Worker }
1072*f6dc9357SAndroid Build Coastguard Worker else
1073*f6dc9357SAndroid Build Coastguard Worker return E_INVALIDARG;
1074*f6dc9357SAndroid Build Coastguard Worker }
1075*f6dc9357SAndroid Build Coastguard Worker else
1076*f6dc9357SAndroid Build Coastguard Worker {
1077*f6dc9357SAndroid Build Coastguard Worker UInt32 numTimeDigits = 0;
1078*f6dc9357SAndroid Build Coastguard Worker RINOK(ParsePropToUInt32(name, prop, numTimeDigits));
1079*f6dc9357SAndroid Build Coastguard Worker TimeOptions.NumDigits_WasForced = true;
1080*f6dc9357SAndroid Build Coastguard Worker TimeOptions.NumDigits = numTimeDigits;
1081*f6dc9357SAndroid Build Coastguard Worker }
1082*f6dc9357SAndroid Build Coastguard Worker }
1083*f6dc9357SAndroid Build Coastguard Worker */
1084*f6dc9357SAndroid Build Coastguard Worker bool processed = false;
1085*f6dc9357SAndroid Build Coastguard Worker RINOK(_handlerTimeOptions.Parse(name, prop, processed))
1086*f6dc9357SAndroid Build Coastguard Worker if (processed)
1087*f6dc9357SAndroid Build Coastguard Worker continue;
1088*f6dc9357SAndroid Build Coastguard Worker return E_INVALIDARG;
1089*f6dc9357SAndroid Build Coastguard Worker }
1090*f6dc9357SAndroid Build Coastguard Worker }
1091*f6dc9357SAndroid Build Coastguard Worker return S_OK;
1092*f6dc9357SAndroid Build Coastguard Worker }
1093*f6dc9357SAndroid Build Coastguard Worker
1094*f6dc9357SAndroid Build Coastguard Worker }}
1095