xref: /aosp_15_r20/external/lzma/CPP/7zip/Archive/Bz2Handler.cpp (revision f6dc9357d832569d4d1f5d24eacdb3935a1ae8e6)
1 // Bz2Handler.cpp
2 
3 #include "StdAfx.h"
4 
5 #include "../../Common/ComTry.h"
6 
7 #include "../Common/ProgressUtils.h"
8 #include "../Common/RegisterArc.h"
9 #include "../Common/StreamUtils.h"
10 
11 #include "../Compress/BZip2Decoder.h"
12 #include "../Compress/BZip2Encoder.h"
13 #include "../Compress/CopyCoder.h"
14 
15 #include "Common/DummyOutStream.h"
16 #include "Common/HandlerOut.h"
17 
18 using namespace NWindows;
19 
20 namespace NArchive {
21 namespace NBz2 {
22 
23 Z7_CLASS_IMP_CHandler_IInArchive_3(
24   IArchiveOpenSeq,
25   IOutArchive,
26   ISetProperties
27 )
28   CMyComPtr<IInStream> _stream;
29   CMyComPtr<ISequentialInStream> _seqStream;
30 
31   bool _isArc;
32   bool _needSeekToStart;
33   bool _dataAfterEnd;
34   bool _needMoreInput;
35 
36   bool _packSize_Defined;
37   bool _unpackSize_Defined;
38   bool _numStreams_Defined;
39   bool _numBlocks_Defined;
40 
41   UInt64 _packSize;
42   UInt64 _unpackSize;
43   UInt64 _numStreams;
44   UInt64 _numBlocks;
45 
46   CSingleMethodProps _props;
47 };
48 
49 static const Byte kProps[] =
50 {
51   kpidSize,
52   kpidPackSize
53 };
54 
55 static const Byte kArcProps[] =
56 {
57   kpidNumStreams,
58   kpidNumBlocks
59 };
60 
61 IMP_IInArchive_Props
62 IMP_IInArchive_ArcProps
63 
Z7_COM7F_IMF(CHandler::GetArchiveProperty (PROPID propID,PROPVARIANT * value))64 Z7_COM7F_IMF(CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value))
65 {
66   NCOM::CPropVariant prop;
67   switch (propID)
68   {
69     case kpidPhySize: if (_packSize_Defined) prop = _packSize; break;
70     case kpidUnpackSize: if (_unpackSize_Defined) prop = _unpackSize; break;
71     case kpidNumStreams: if (_numStreams_Defined) prop = _numStreams; break;
72     case kpidNumBlocks: if (_numBlocks_Defined) prop = _numBlocks; break;
73     case kpidErrorFlags:
74     {
75       UInt32 v = 0;
76       if (!_isArc) v |= kpv_ErrorFlags_IsNotArc;
77       if (_needMoreInput) v |= kpv_ErrorFlags_UnexpectedEnd;
78       if (_dataAfterEnd) v |= kpv_ErrorFlags_DataAfterEnd;
79       prop = v;
80       break;
81     }
82     default: break;
83   }
84   prop.Detach(value);
85   return S_OK;
86 }
87 
Z7_COM7F_IMF(CHandler::GetNumberOfItems (UInt32 * numItems))88 Z7_COM7F_IMF(CHandler::GetNumberOfItems(UInt32 *numItems))
89 {
90   *numItems = 1;
91   return S_OK;
92 }
93 
Z7_COM7F_IMF(CHandler::GetProperty (UInt32,PROPID propID,PROPVARIANT * value))94 Z7_COM7F_IMF(CHandler::GetProperty(UInt32 /* index */, PROPID propID, PROPVARIANT *value))
95 {
96   NCOM::CPropVariant prop;
97   switch (propID)
98   {
99     case kpidPackSize: if (_packSize_Defined) prop = _packSize; break;
100     case kpidSize: if (_unpackSize_Defined) prop = _unpackSize; break;
101     default: break;
102   }
103   prop.Detach(value);
104   return S_OK;
105 }
106 
107 static const unsigned kSignatureCheckSize = 10;
108 
IsArc_BZip2(const Byte * p,size_t size)109 API_FUNC_static_IsArc IsArc_BZip2(const Byte *p, size_t size)
110 {
111   if (size < kSignatureCheckSize)
112     return k_IsArc_Res_NEED_MORE;
113   if (p[0] != 'B' || p[1] != 'Z' || p[2] != 'h' || p[3] < '1' || p[3] > '9')
114     return k_IsArc_Res_NO;
115   p += 4;
116   if (NCompress::NBZip2::IsBlockSig(p))
117     return k_IsArc_Res_YES;
118   if (NCompress::NBZip2::IsEndSig(p))
119     return k_IsArc_Res_YES;
120   return k_IsArc_Res_NO;
121 }
122 }
123 
Z7_COM7F_IMF(CHandler::Open (IInStream * stream,const UInt64 *,IArchiveOpenCallback *))124 Z7_COM7F_IMF(CHandler::Open(IInStream *stream, const UInt64 *, IArchiveOpenCallback *))
125 {
126   COM_TRY_BEGIN
127   Close();
128   {
129     Byte buf[kSignatureCheckSize];
130     RINOK(ReadStream_FALSE(stream, buf, kSignatureCheckSize))
131     if (IsArc_BZip2(buf, kSignatureCheckSize) == k_IsArc_Res_NO)
132       return S_FALSE;
133     _isArc = true;
134     _stream = stream;
135     _seqStream = stream;
136     _needSeekToStart = true;
137   }
138   return S_OK;
139   COM_TRY_END
140 }
141 
142 
Z7_COM7F_IMF(CHandler::OpenSeq (ISequentialInStream * stream))143 Z7_COM7F_IMF(CHandler::OpenSeq(ISequentialInStream *stream))
144 {
145   Close();
146   _isArc = true;
147   _seqStream = stream;
148   return S_OK;
149 }
150 
Z7_COM7F_IMF(CHandler::Close ())151 Z7_COM7F_IMF(CHandler::Close())
152 {
153   _isArc = false;
154   _needSeekToStart = false;
155   _dataAfterEnd = false;
156   _needMoreInput = false;
157 
158   _packSize_Defined = false;
159   _unpackSize_Defined = false;
160   _numStreams_Defined = false;
161   _numBlocks_Defined = false;
162 
163   _packSize = 0;
164 
165   _seqStream.Release();
166   _stream.Release();
167   return S_OK;
168 }
169 
170 
Z7_COM7F_IMF(CHandler::Extract (const UInt32 * indices,UInt32 numItems,Int32 testMode,IArchiveExtractCallback * extractCallback))171 Z7_COM7F_IMF(CHandler::Extract(const UInt32 *indices, UInt32 numItems,
172     Int32 testMode, IArchiveExtractCallback *extractCallback))
173 {
174   COM_TRY_BEGIN
175   if (numItems == 0)
176     return S_OK;
177   if (numItems != (UInt32)(Int32)-1 && (numItems != 1 || indices[0] != 0))
178     return E_INVALIDARG;
179 
180   if (_packSize_Defined)
181   {
182     RINOK(extractCallback->SetTotal(_packSize))
183   }
184 
185   Int32 opRes;
186  {
187   CMyComPtr<ISequentialOutStream> realOutStream;
188   const Int32 askMode = testMode ?
189       NExtract::NAskMode::kTest :
190       NExtract::NAskMode::kExtract;
191   RINOK(extractCallback->GetStream(0, &realOutStream, askMode))
192   if (!testMode && !realOutStream)
193     return S_OK;
194 
195   RINOK(extractCallback->PrepareOperation(askMode))
196 
197   if (_needSeekToStart)
198   {
199     if (!_stream)
200       return E_FAIL;
201     RINOK(InStream_SeekToBegin(_stream))
202   }
203   else
204     _needSeekToStart = true;
205 
206   // try {
207 
208   CMyComPtr2_Create<ICompressCoder, NCompress::NBZip2::CDecoder> decoder;
209 
210   #ifndef Z7_ST
211   RINOK(decoder->SetNumberOfThreads(_props._numThreads))
212   #endif
213 
214   CMyComPtr2_Create<ISequentialOutStream, CDummyOutStream> outStream;
215   outStream->SetStream(realOutStream);
216   outStream->Init();
217   // realOutStream.Release();
218 
219   CMyComPtr2_Create<ICompressProgressInfo, CLocalProgress> lps;
220   lps->Init(extractCallback, true);
221 
222   decoder->FinishMode = true;
223   decoder->Base.DecodeAllStreams = true;
224 
225   _dataAfterEnd = false;
226   _needMoreInput = false;
227 
228   HRESULT result = decoder.Interface()->Code(_seqStream, outStream, NULL, NULL, lps);
229 
230   if (result != S_FALSE && result != S_OK)
231     return result;
232 
233   if (decoder->Base.NumStreams == 0)
234   {
235     _isArc = false;
236     result = S_FALSE;
237   }
238   else
239   {
240     const UInt64 inProcessedSize = decoder->GetInputProcessedSize();
241     UInt64 packSize = inProcessedSize;
242 
243     if (decoder->Base.NeedMoreInput)
244       _needMoreInput = true;
245 
246     if (!decoder->Base.IsBz)
247     {
248       packSize = decoder->Base.FinishedPackSize;
249       if (packSize != inProcessedSize)
250         _dataAfterEnd = true;
251     }
252 
253     _packSize = packSize;
254     _unpackSize = decoder->GetOutProcessedSize();
255     _numStreams = decoder->Base.NumStreams;
256     _numBlocks = decoder->GetNumBlocks();
257 
258     _packSize_Defined = true;
259     _unpackSize_Defined = true;
260     _numStreams_Defined = true;
261     _numBlocks_Defined = true;
262 
263     // RINOK(
264     lps.Interface()->SetRatioInfo(&packSize, &_unpackSize);
265   }
266 
267   // outStream.Release();
268 
269   if (!_isArc)
270     opRes = NExtract::NOperationResult::kIsNotArc;
271   else if (_needMoreInput)
272     opRes = NExtract::NOperationResult::kUnexpectedEnd;
273   else if (decoder->GetCrcError())
274     opRes = NExtract::NOperationResult::kCRCError;
275   else if (_dataAfterEnd)
276     opRes = NExtract::NOperationResult::kDataAfterEnd;
277   else if (result == S_FALSE)
278     opRes = NExtract::NOperationResult::kDataError;
279   else if (decoder->Base.MinorError)
280     opRes = NExtract::NOperationResult::kDataError;
281   else if (result == S_OK)
282     opRes = NExtract::NOperationResult::kOK;
283   else
284     return result;
285 
286  }
287   return extractCallback->SetOperationResult(opRes);
288 
289   // } catch(...)  { return E_FAIL; }
290 
291   COM_TRY_END
292 }
293 
294 
295 /*
296 static HRESULT ReportItemProp(IArchiveUpdateCallbackArcProp *reportArcProp, PROPID propID, const PROPVARIANT *value)
297 {
298   return reportArcProp->ReportProp(NEventIndexType::kOutArcIndex, 0, propID, value);
299 }
300 
301 static HRESULT ReportArcProp(IArchiveUpdateCallbackArcProp *reportArcProp, PROPID propID, const PROPVARIANT *value)
302 {
303   return reportArcProp->ReportProp(NEventIndexType::kArcProp, 0, propID, value);
304 }
305 
306 static HRESULT ReportArcProps(IArchiveUpdateCallbackArcProp *reportArcProp,
307     const UInt64 *unpackSize,
308     const UInt64 *numBlocks)
309 {
310   NCOM::CPropVariant sizeProp;
311   if (unpackSize)
312   {
313     sizeProp = *unpackSize;
314     RINOK(ReportItemProp(reportArcProp, kpidSize, &sizeProp));
315     RINOK(reportArcProp->ReportFinished(NEventIndexType::kOutArcIndex, 0, NArchive::NUpdate::NOperationResult::kOK));
316   }
317 
318   if (unpackSize)
319   {
320     RINOK(ReportArcProp(reportArcProp, kpidSize, &sizeProp));
321   }
322   if (numBlocks)
323   {
324     NCOM::CPropVariant prop;
325     prop = *numBlocks;
326     RINOK(ReportArcProp(reportArcProp, kpidNumBlocks, &prop));
327   }
328   return S_OK;
329 }
330 */
331 
UpdateArchive(UInt64 unpackSize,ISequentialOutStream * outStream,const CProps & props,IArchiveUpdateCallback * updateCallback)332 static HRESULT UpdateArchive(
333     UInt64 unpackSize,
334     ISequentialOutStream *outStream,
335     const CProps &props,
336     IArchiveUpdateCallback *updateCallback
337     // , ArchiveUpdateCallbackArcProp *reportArcProp
338     )
339 {
340   {
341     CMyComPtr<ISequentialInStream> fileInStream;
342     RINOK(updateCallback->GetStream(0, &fileInStream))
343     if (!fileInStream)
344       return S_FALSE;
345     {
346       Z7_DECL_CMyComPtr_QI_FROM(
347           IStreamGetSize,
348           streamGetSize, fileInStream)
349       if (streamGetSize)
350       {
351         UInt64 size;
352         if (streamGetSize->GetSize(&size) == S_OK)
353           unpackSize = size;
354       }
355     }
356     RINOK(updateCallback->SetTotal(unpackSize))
357 
358     CMyComPtr2_Create<ICompressProgressInfo, CLocalProgress> lps;
359     lps->Init(updateCallback, true);
360     {
361       CMyComPtr2_Create<ICompressCoder, NCompress::NBZip2::CEncoder> encoder;
362       RINOK(props.SetCoderProps(encoder.ClsPtr(), NULL))
363       RINOK(encoder.Interface()->Code(fileInStream, outStream, NULL, NULL, lps))
364       /*
365       if (reportArcProp)
366       {
367         unpackSize = encoderSpec->GetInProcessedSize();
368         RINOK(ReportArcProps(reportArcProp, &unpackSize, &encoderSpec->NumBlocks));
369       }
370       */
371     }
372   }
373   return updateCallback->SetOperationResult(NArchive::NUpdate::NOperationResult::kOK);
374 }
375 
Z7_COM7F_IMF(CHandler::GetFileTimeType (UInt32 * timeType))376 Z7_COM7F_IMF(CHandler::GetFileTimeType(UInt32 *timeType))
377 {
378   *timeType = GET_FileTimeType_NotDefined_for_GetFileTimeType;
379   // *timeType = NFileTimeType::kUnix;
380   return S_OK;
381 }
382 
Z7_COM7F_IMF(CHandler::UpdateItems (ISequentialOutStream * outStream,UInt32 numItems,IArchiveUpdateCallback * updateCallback))383 Z7_COM7F_IMF(CHandler::UpdateItems(ISequentialOutStream *outStream, UInt32 numItems,
384     IArchiveUpdateCallback *updateCallback))
385 {
386   COM_TRY_BEGIN
387 
388   if (numItems != 1)
389     return E_INVALIDARG;
390 
391   {
392     Z7_DECL_CMyComPtr_QI_FROM(
393         IStreamSetRestriction,
394         setRestriction, outStream)
395     if (setRestriction)
396       RINOK(setRestriction->SetRestriction(0, 0))
397   }
398 
399   Int32 newData, newProps;
400   UInt32 indexInArchive;
401   if (!updateCallback)
402     return E_FAIL;
403   RINOK(updateCallback->GetUpdateItemInfo(0, &newData, &newProps, &indexInArchive))
404 
405   // Z7_DECL_CMyComPtr_QI_FROM(IArchiveUpdateCallbackArcProp, reportArcProp, updateCallback)
406 
407   if (IntToBool(newProps))
408   {
409     {
410       NCOM::CPropVariant prop;
411       RINOK(updateCallback->GetProperty(0, kpidIsDir, &prop))
412       if (prop.vt != VT_EMPTY)
413         if (prop.vt != VT_BOOL || prop.boolVal != VARIANT_FALSE)
414           return E_INVALIDARG;
415     }
416   }
417 
418   if (IntToBool(newData))
419   {
420     UInt64 size;
421     {
422       NCOM::CPropVariant prop;
423       RINOK(updateCallback->GetProperty(0, kpidSize, &prop))
424       if (prop.vt != VT_UI8)
425         return E_INVALIDARG;
426       size = prop.uhVal.QuadPart;
427     }
428 
429     CMethodProps props2 = _props;
430     #ifndef Z7_ST
431     props2.AddProp_NumThreads(_props._numThreads);
432     #endif
433 
434     return UpdateArchive(size, outStream, props2, updateCallback);
435   }
436 
437   if (indexInArchive != 0)
438     return E_INVALIDARG;
439 
440   CMyComPtr2_Create<ICompressProgressInfo, CLocalProgress> lps;
441   lps->Init(updateCallback, true);
442 
443   Z7_DECL_CMyComPtr_QI_FROM(
444       IArchiveUpdateCallbackFile,
445       opCallback, updateCallback)
446   if (opCallback)
447   {
448     RINOK(opCallback->ReportOperation(
449         NEventIndexType::kInArcIndex, 0,
450         NUpdateNotifyOp::kReplicate))
451   }
452 
453   if (_stream)
454     RINOK(InStream_SeekToBegin(_stream))
455 
456   return NCompress::CopyStream(_stream, outStream, lps);
457 
458   // return ReportArcProps(reportArcProp, NULL, NULL);
459 
460   COM_TRY_END
461 }
462 
Z7_COM7F_IMF(CHandler::SetProperties (const wchar_t * const * names,const PROPVARIANT * values,UInt32 numProps))463 Z7_COM7F_IMF(CHandler::SetProperties(const wchar_t * const *names, const PROPVARIANT *values, UInt32 numProps))
464 {
465   return _props.SetProperties(names, values, numProps);
466 }
467 
468 static const Byte k_Signature[] = { 'B', 'Z', 'h' };
469 
470 REGISTER_ARC_IO(
471   "bzip2", "bz2 bzip2 tbz2 tbz", "* * .tar .tar", 2,
472   k_Signature,
473   0,
474   NArcInfoFlags::kKeepName
475   , 0
476   , IsArc_BZip2)
477 
478 }}
479