1*f6dc9357SAndroid Build Coastguard Worker // XzHandler.cpp 2*f6dc9357SAndroid Build Coastguard Worker 3*f6dc9357SAndroid Build Coastguard Worker #include "StdAfx.h" 4*f6dc9357SAndroid Build Coastguard Worker 5*f6dc9357SAndroid Build Coastguard Worker #include "../../../C/Alloc.h" 6*f6dc9357SAndroid Build Coastguard Worker 7*f6dc9357SAndroid Build Coastguard Worker #include "../../Common/ComTry.h" 8*f6dc9357SAndroid Build Coastguard Worker #include "../../Common/Defs.h" 9*f6dc9357SAndroid Build Coastguard Worker #include "../../Common/IntToString.h" 10*f6dc9357SAndroid Build Coastguard Worker #include "../../Common/MyBuffer.h" 11*f6dc9357SAndroid Build Coastguard Worker #include "../../Common/StringToInt.h" 12*f6dc9357SAndroid Build Coastguard Worker 13*f6dc9357SAndroid Build Coastguard Worker #include "../../Windows/PropVariant.h" 14*f6dc9357SAndroid Build Coastguard Worker #include "../../Windows/System.h" 15*f6dc9357SAndroid Build Coastguard Worker 16*f6dc9357SAndroid Build Coastguard Worker #include "../Common/CWrappers.h" 17*f6dc9357SAndroid Build Coastguard Worker #include "../Common/ProgressUtils.h" 18*f6dc9357SAndroid Build Coastguard Worker #include "../Common/RegisterArc.h" 19*f6dc9357SAndroid Build Coastguard Worker #include "../Common/StreamUtils.h" 20*f6dc9357SAndroid Build Coastguard Worker 21*f6dc9357SAndroid Build Coastguard Worker #include "../Compress/CopyCoder.h" 22*f6dc9357SAndroid Build Coastguard Worker #include "../Compress/XzDecoder.h" 23*f6dc9357SAndroid Build Coastguard Worker #include "../Compress/XzEncoder.h" 24*f6dc9357SAndroid Build Coastguard Worker 25*f6dc9357SAndroid Build Coastguard Worker #include "IArchive.h" 26*f6dc9357SAndroid Build Coastguard Worker 27*f6dc9357SAndroid Build Coastguard Worker #include "Common/HandlerOut.h" 28*f6dc9357SAndroid Build Coastguard Worker 29*f6dc9357SAndroid Build Coastguard Worker using namespace NWindows; 30*f6dc9357SAndroid Build Coastguard Worker 31*f6dc9357SAndroid Build Coastguard Worker namespace NArchive { 32*f6dc9357SAndroid Build Coastguard Worker namespace NXz { 33*f6dc9357SAndroid Build Coastguard Worker 34*f6dc9357SAndroid Build Coastguard Worker #define k_LZMA2_Name "LZMA2" 35*f6dc9357SAndroid Build Coastguard Worker 36*f6dc9357SAndroid Build Coastguard Worker 37*f6dc9357SAndroid Build Coastguard Worker struct CBlockInfo 38*f6dc9357SAndroid Build Coastguard Worker { 39*f6dc9357SAndroid Build Coastguard Worker unsigned StreamFlags; 40*f6dc9357SAndroid Build Coastguard Worker UInt64 PackPos; 41*f6dc9357SAndroid Build Coastguard Worker UInt64 PackSize; // pure value from Index record, it doesn't include pad zeros 42*f6dc9357SAndroid Build Coastguard Worker UInt64 UnpackPos; 43*f6dc9357SAndroid Build Coastguard Worker }; 44*f6dc9357SAndroid Build Coastguard Worker 45*f6dc9357SAndroid Build Coastguard Worker 46*f6dc9357SAndroid Build Coastguard Worker Z7_class_CHandler_final: 47*f6dc9357SAndroid Build Coastguard Worker public IInArchive, 48*f6dc9357SAndroid Build Coastguard Worker public IArchiveOpenSeq, 49*f6dc9357SAndroid Build Coastguard Worker public IInArchiveGetStream, 50*f6dc9357SAndroid Build Coastguard Worker public ISetProperties, 51*f6dc9357SAndroid Build Coastguard Worker #ifndef Z7_EXTRACT_ONLY 52*f6dc9357SAndroid Build Coastguard Worker public IOutArchive, 53*f6dc9357SAndroid Build Coastguard Worker #endif 54*f6dc9357SAndroid Build Coastguard Worker public CMyUnknownImp, 55*f6dc9357SAndroid Build Coastguard Worker #ifndef Z7_EXTRACT_ONLY 56*f6dc9357SAndroid Build Coastguard Worker public CMultiMethodProps 57*f6dc9357SAndroid Build Coastguard Worker #else 58*f6dc9357SAndroid Build Coastguard Worker public CCommonMethodProps 59*f6dc9357SAndroid Build Coastguard Worker #endif 60*f6dc9357SAndroid Build Coastguard Worker { 61*f6dc9357SAndroid Build Coastguard Worker Z7_COM_QI_BEGIN2(IInArchive) 62*f6dc9357SAndroid Build Coastguard Worker Z7_COM_QI_ENTRY(IArchiveOpenSeq) 63*f6dc9357SAndroid Build Coastguard Worker Z7_COM_QI_ENTRY(IInArchiveGetStream) 64*f6dc9357SAndroid Build Coastguard Worker Z7_COM_QI_ENTRY(ISetProperties) 65*f6dc9357SAndroid Build Coastguard Worker #ifndef Z7_EXTRACT_ONLY 66*f6dc9357SAndroid Build Coastguard Worker Z7_COM_QI_ENTRY(IOutArchive) 67*f6dc9357SAndroid Build Coastguard Worker #endif 68*f6dc9357SAndroid Build Coastguard Worker Z7_COM_QI_END 69*f6dc9357SAndroid Build Coastguard Worker Z7_COM_ADDREF_RELEASE 70*f6dc9357SAndroid Build Coastguard Worker 71*f6dc9357SAndroid Build Coastguard Worker Z7_IFACE_COM7_IMP(IInArchive) 72*f6dc9357SAndroid Build Coastguard Worker Z7_IFACE_COM7_IMP(IArchiveOpenSeq) 73*f6dc9357SAndroid Build Coastguard Worker Z7_IFACE_COM7_IMP(IInArchiveGetStream) 74*f6dc9357SAndroid Build Coastguard Worker Z7_IFACE_COM7_IMP(ISetProperties) 75*f6dc9357SAndroid Build Coastguard Worker #ifndef Z7_EXTRACT_ONLY 76*f6dc9357SAndroid Build Coastguard Worker Z7_IFACE_COM7_IMP(IOutArchive) 77*f6dc9357SAndroid Build Coastguard Worker #endif 78*f6dc9357SAndroid Build Coastguard Worker 79*f6dc9357SAndroid Build Coastguard Worker bool _stat_defined; 80*f6dc9357SAndroid Build Coastguard Worker bool _stat2_defined; 81*f6dc9357SAndroid Build Coastguard Worker bool _isArc; 82*f6dc9357SAndroid Build Coastguard Worker bool _needSeekToStart; 83*f6dc9357SAndroid Build Coastguard Worker bool _firstBlockWasRead; 84*f6dc9357SAndroid Build Coastguard Worker SRes _stat2_decode_SRes; 85*f6dc9357SAndroid Build Coastguard Worker 86*f6dc9357SAndroid Build Coastguard Worker CXzStatInfo _stat; // it's stat from backward parsing 87*f6dc9357SAndroid Build Coastguard Worker CXzStatInfo _stat2; // it's data from forward parsing, if the decoder was called 88*f6dc9357SAndroid Build Coastguard Worker 89*f6dc9357SAndroid Build Coastguard Worker const CXzStatInfo *GetStat() const 90*f6dc9357SAndroid Build Coastguard Worker { 91*f6dc9357SAndroid Build Coastguard Worker if (_stat_defined) return &_stat; 92*f6dc9357SAndroid Build Coastguard Worker if (_stat2_defined) return &_stat2; 93*f6dc9357SAndroid Build Coastguard Worker return NULL; 94*f6dc9357SAndroid Build Coastguard Worker } 95*f6dc9357SAndroid Build Coastguard Worker 96*f6dc9357SAndroid Build Coastguard Worker AString _methodsString; 97*f6dc9357SAndroid Build Coastguard Worker 98*f6dc9357SAndroid Build Coastguard Worker 99*f6dc9357SAndroid Build Coastguard Worker #ifndef Z7_EXTRACT_ONLY 100*f6dc9357SAndroid Build Coastguard Worker 101*f6dc9357SAndroid Build Coastguard Worker UInt32 _filterId; 102*f6dc9357SAndroid Build Coastguard Worker UInt64 _numSolidBytes; 103*f6dc9357SAndroid Build Coastguard Worker 104*f6dc9357SAndroid Build Coastguard Worker void InitXz() 105*f6dc9357SAndroid Build Coastguard Worker { 106*f6dc9357SAndroid Build Coastguard Worker _filterId = 0; 107*f6dc9357SAndroid Build Coastguard Worker _numSolidBytes = XZ_PROPS_BLOCK_SIZE_AUTO; 108*f6dc9357SAndroid Build Coastguard Worker } 109*f6dc9357SAndroid Build Coastguard Worker 110*f6dc9357SAndroid Build Coastguard Worker #endif 111*f6dc9357SAndroid Build Coastguard Worker 112*f6dc9357SAndroid Build Coastguard Worker 113*f6dc9357SAndroid Build Coastguard Worker void Init() 114*f6dc9357SAndroid Build Coastguard Worker { 115*f6dc9357SAndroid Build Coastguard Worker #ifndef Z7_EXTRACT_ONLY 116*f6dc9357SAndroid Build Coastguard Worker InitXz(); 117*f6dc9357SAndroid Build Coastguard Worker CMultiMethodProps::Init(); 118*f6dc9357SAndroid Build Coastguard Worker #else 119*f6dc9357SAndroid Build Coastguard Worker CCommonMethodProps::InitCommon(); 120*f6dc9357SAndroid Build Coastguard Worker #endif 121*f6dc9357SAndroid Build Coastguard Worker } 122*f6dc9357SAndroid Build Coastguard Worker 123*f6dc9357SAndroid Build Coastguard Worker HRESULT SetProperty(const wchar_t *name, const PROPVARIANT &value); 124*f6dc9357SAndroid Build Coastguard Worker 125*f6dc9357SAndroid Build Coastguard Worker HRESULT Open2(IInStream *inStream, /* UInt32 flags, */ IArchiveOpenCallback *callback); 126*f6dc9357SAndroid Build Coastguard Worker 127*f6dc9357SAndroid Build Coastguard Worker HRESULT Decode(NCompress::NXz::CDecoder &decoder, 128*f6dc9357SAndroid Build Coastguard Worker ISequentialInStream *seqInStream, 129*f6dc9357SAndroid Build Coastguard Worker ISequentialOutStream *outStream, 130*f6dc9357SAndroid Build Coastguard Worker ICompressProgressInfo *progress) 131*f6dc9357SAndroid Build Coastguard Worker { 132*f6dc9357SAndroid Build Coastguard Worker #ifndef Z7_ST 133*f6dc9357SAndroid Build Coastguard Worker decoder._numThreads = _numThreads; 134*f6dc9357SAndroid Build Coastguard Worker #endif 135*f6dc9357SAndroid Build Coastguard Worker decoder._memUsage = _memUsage_Decompress; 136*f6dc9357SAndroid Build Coastguard Worker 137*f6dc9357SAndroid Build Coastguard Worker const HRESULT hres = decoder.Decode(seqInStream, outStream, 138*f6dc9357SAndroid Build Coastguard Worker NULL, // *outSizeLimit 139*f6dc9357SAndroid Build Coastguard Worker true, // finishStream 140*f6dc9357SAndroid Build Coastguard Worker progress); 141*f6dc9357SAndroid Build Coastguard Worker 142*f6dc9357SAndroid Build Coastguard Worker if (decoder.MainDecodeSRes_wasUsed 143*f6dc9357SAndroid Build Coastguard Worker && decoder.MainDecodeSRes != SZ_ERROR_MEM 144*f6dc9357SAndroid Build Coastguard Worker && decoder.MainDecodeSRes != SZ_ERROR_UNSUPPORTED) 145*f6dc9357SAndroid Build Coastguard Worker { 146*f6dc9357SAndroid Build Coastguard Worker // if (!_stat2_defined) 147*f6dc9357SAndroid Build Coastguard Worker { 148*f6dc9357SAndroid Build Coastguard Worker _stat2_decode_SRes = decoder.MainDecodeSRes; 149*f6dc9357SAndroid Build Coastguard Worker _stat2 = decoder.Stat; 150*f6dc9357SAndroid Build Coastguard Worker _stat2_defined = true; 151*f6dc9357SAndroid Build Coastguard Worker } 152*f6dc9357SAndroid Build Coastguard Worker } 153*f6dc9357SAndroid Build Coastguard Worker 154*f6dc9357SAndroid Build Coastguard Worker if (hres == S_OK && progress) 155*f6dc9357SAndroid Build Coastguard Worker { 156*f6dc9357SAndroid Build Coastguard Worker // RINOK( 157*f6dc9357SAndroid Build Coastguard Worker progress->SetRatioInfo(&decoder.Stat.InSize, &decoder.Stat.OutSize); 158*f6dc9357SAndroid Build Coastguard Worker } 159*f6dc9357SAndroid Build Coastguard Worker return hres; 160*f6dc9357SAndroid Build Coastguard Worker } 161*f6dc9357SAndroid Build Coastguard Worker 162*f6dc9357SAndroid Build Coastguard Worker public: 163*f6dc9357SAndroid Build Coastguard Worker CBlockInfo *_blocks; 164*f6dc9357SAndroid Build Coastguard Worker size_t _blocksArraySize; 165*f6dc9357SAndroid Build Coastguard Worker UInt64 _maxBlocksSize; 166*f6dc9357SAndroid Build Coastguard Worker CMyComPtr<IInStream> _stream; 167*f6dc9357SAndroid Build Coastguard Worker CMyComPtr<ISequentialInStream> _seqStream; 168*f6dc9357SAndroid Build Coastguard Worker 169*f6dc9357SAndroid Build Coastguard Worker CXzBlock _firstBlock; 170*f6dc9357SAndroid Build Coastguard Worker 171*f6dc9357SAndroid Build Coastguard Worker CHandler(); 172*f6dc9357SAndroid Build Coastguard Worker ~CHandler(); 173*f6dc9357SAndroid Build Coastguard Worker 174*f6dc9357SAndroid Build Coastguard Worker HRESULT SeekToPackPos(UInt64 pos) 175*f6dc9357SAndroid Build Coastguard Worker { 176*f6dc9357SAndroid Build Coastguard Worker return InStream_SeekSet(_stream, pos); 177*f6dc9357SAndroid Build Coastguard Worker } 178*f6dc9357SAndroid Build Coastguard Worker }; 179*f6dc9357SAndroid Build Coastguard Worker 180*f6dc9357SAndroid Build Coastguard Worker 181*f6dc9357SAndroid Build Coastguard Worker CHandler::CHandler(): 182*f6dc9357SAndroid Build Coastguard Worker _blocks(NULL), 183*f6dc9357SAndroid Build Coastguard Worker _blocksArraySize(0) 184*f6dc9357SAndroid Build Coastguard Worker { 185*f6dc9357SAndroid Build Coastguard Worker #ifndef Z7_EXTRACT_ONLY 186*f6dc9357SAndroid Build Coastguard Worker InitXz(); 187*f6dc9357SAndroid Build Coastguard Worker #endif 188*f6dc9357SAndroid Build Coastguard Worker } 189*f6dc9357SAndroid Build Coastguard Worker 190*f6dc9357SAndroid Build Coastguard Worker CHandler::~CHandler() 191*f6dc9357SAndroid Build Coastguard Worker { 192*f6dc9357SAndroid Build Coastguard Worker MyFree(_blocks); 193*f6dc9357SAndroid Build Coastguard Worker } 194*f6dc9357SAndroid Build Coastguard Worker 195*f6dc9357SAndroid Build Coastguard Worker 196*f6dc9357SAndroid Build Coastguard Worker static const Byte kProps[] = 197*f6dc9357SAndroid Build Coastguard Worker { 198*f6dc9357SAndroid Build Coastguard Worker kpidSize, 199*f6dc9357SAndroid Build Coastguard Worker kpidPackSize, 200*f6dc9357SAndroid Build Coastguard Worker kpidMethod 201*f6dc9357SAndroid Build Coastguard Worker }; 202*f6dc9357SAndroid Build Coastguard Worker 203*f6dc9357SAndroid Build Coastguard Worker static const Byte kArcProps[] = 204*f6dc9357SAndroid Build Coastguard Worker { 205*f6dc9357SAndroid Build Coastguard Worker kpidMethod, 206*f6dc9357SAndroid Build Coastguard Worker kpidNumStreams, 207*f6dc9357SAndroid Build Coastguard Worker kpidNumBlocks, 208*f6dc9357SAndroid Build Coastguard Worker kpidClusterSize, 209*f6dc9357SAndroid Build Coastguard Worker kpidCharacts 210*f6dc9357SAndroid Build Coastguard Worker }; 211*f6dc9357SAndroid Build Coastguard Worker 212*f6dc9357SAndroid Build Coastguard Worker IMP_IInArchive_Props 213*f6dc9357SAndroid Build Coastguard Worker IMP_IInArchive_ArcProps 214*f6dc9357SAndroid Build Coastguard Worker 215*f6dc9357SAndroid Build Coastguard Worker static void Lzma2PropToString(AString &s, unsigned prop) 216*f6dc9357SAndroid Build Coastguard Worker { 217*f6dc9357SAndroid Build Coastguard Worker char c = 0; 218*f6dc9357SAndroid Build Coastguard Worker UInt32 size; 219*f6dc9357SAndroid Build Coastguard Worker if ((prop & 1) == 0) 220*f6dc9357SAndroid Build Coastguard Worker size = prop / 2 + 12; 221*f6dc9357SAndroid Build Coastguard Worker else 222*f6dc9357SAndroid Build Coastguard Worker { 223*f6dc9357SAndroid Build Coastguard Worker c = 'k'; 224*f6dc9357SAndroid Build Coastguard Worker size = (UInt32)(2 | (prop & 1)) << (prop / 2 + 1); 225*f6dc9357SAndroid Build Coastguard Worker if (prop > 17) 226*f6dc9357SAndroid Build Coastguard Worker { 227*f6dc9357SAndroid Build Coastguard Worker size >>= 10; 228*f6dc9357SAndroid Build Coastguard Worker c = 'm'; 229*f6dc9357SAndroid Build Coastguard Worker } 230*f6dc9357SAndroid Build Coastguard Worker } 231*f6dc9357SAndroid Build Coastguard Worker s.Add_UInt32(size); 232*f6dc9357SAndroid Build Coastguard Worker if (c != 0) 233*f6dc9357SAndroid Build Coastguard Worker s.Add_Char(c); 234*f6dc9357SAndroid Build Coastguard Worker } 235*f6dc9357SAndroid Build Coastguard Worker 236*f6dc9357SAndroid Build Coastguard Worker struct CMethodNamePair 237*f6dc9357SAndroid Build Coastguard Worker { 238*f6dc9357SAndroid Build Coastguard Worker UInt32 Id; 239*f6dc9357SAndroid Build Coastguard Worker const char *Name; 240*f6dc9357SAndroid Build Coastguard Worker }; 241*f6dc9357SAndroid Build Coastguard Worker 242*f6dc9357SAndroid Build Coastguard Worker static const CMethodNamePair g_NamePairs[] = 243*f6dc9357SAndroid Build Coastguard Worker { 244*f6dc9357SAndroid Build Coastguard Worker { XZ_ID_Subblock, "SB" }, 245*f6dc9357SAndroid Build Coastguard Worker { XZ_ID_Delta, "Delta" }, 246*f6dc9357SAndroid Build Coastguard Worker { XZ_ID_X86, "BCJ" }, 247*f6dc9357SAndroid Build Coastguard Worker { XZ_ID_PPC, "PPC" }, 248*f6dc9357SAndroid Build Coastguard Worker { XZ_ID_IA64, "IA64" }, 249*f6dc9357SAndroid Build Coastguard Worker { XZ_ID_ARM, "ARM" }, 250*f6dc9357SAndroid Build Coastguard Worker { XZ_ID_ARMT, "ARMT" }, 251*f6dc9357SAndroid Build Coastguard Worker { XZ_ID_SPARC, "SPARC" }, 252*f6dc9357SAndroid Build Coastguard Worker { XZ_ID_ARM64, "ARM64" }, 253*f6dc9357SAndroid Build Coastguard Worker { XZ_ID_RISCV, "RISCV" }, 254*f6dc9357SAndroid Build Coastguard Worker { XZ_ID_LZMA2, "LZMA2" } 255*f6dc9357SAndroid Build Coastguard Worker }; 256*f6dc9357SAndroid Build Coastguard Worker 257*f6dc9357SAndroid Build Coastguard Worker static void AddMethodString(AString &s, const CXzFilter &f) 258*f6dc9357SAndroid Build Coastguard Worker { 259*f6dc9357SAndroid Build Coastguard Worker const char *p = NULL; 260*f6dc9357SAndroid Build Coastguard Worker for (unsigned i = 0; i < Z7_ARRAY_SIZE(g_NamePairs); i++) 261*f6dc9357SAndroid Build Coastguard Worker if (g_NamePairs[i].Id == f.id) 262*f6dc9357SAndroid Build Coastguard Worker { 263*f6dc9357SAndroid Build Coastguard Worker p = g_NamePairs[i].Name; 264*f6dc9357SAndroid Build Coastguard Worker break; 265*f6dc9357SAndroid Build Coastguard Worker } 266*f6dc9357SAndroid Build Coastguard Worker char temp[32]; 267*f6dc9357SAndroid Build Coastguard Worker if (!p) 268*f6dc9357SAndroid Build Coastguard Worker { 269*f6dc9357SAndroid Build Coastguard Worker ::ConvertUInt64ToString(f.id, temp); 270*f6dc9357SAndroid Build Coastguard Worker p = temp; 271*f6dc9357SAndroid Build Coastguard Worker } 272*f6dc9357SAndroid Build Coastguard Worker 273*f6dc9357SAndroid Build Coastguard Worker s += p; 274*f6dc9357SAndroid Build Coastguard Worker 275*f6dc9357SAndroid Build Coastguard Worker if (f.propsSize > 0) 276*f6dc9357SAndroid Build Coastguard Worker { 277*f6dc9357SAndroid Build Coastguard Worker s.Add_Colon(); 278*f6dc9357SAndroid Build Coastguard Worker if (f.id == XZ_ID_LZMA2 && f.propsSize == 1) 279*f6dc9357SAndroid Build Coastguard Worker Lzma2PropToString(s, f.props[0]); 280*f6dc9357SAndroid Build Coastguard Worker else if (f.id == XZ_ID_Delta && f.propsSize == 1) 281*f6dc9357SAndroid Build Coastguard Worker s.Add_UInt32((UInt32)f.props[0] + 1); 282*f6dc9357SAndroid Build Coastguard Worker else if (f.id == XZ_ID_ARM64 && f.propsSize == 1) 283*f6dc9357SAndroid Build Coastguard Worker s.Add_UInt32((UInt32)f.props[0] + 16 + 2); 284*f6dc9357SAndroid Build Coastguard Worker else 285*f6dc9357SAndroid Build Coastguard Worker { 286*f6dc9357SAndroid Build Coastguard Worker s.Add_Char('['); 287*f6dc9357SAndroid Build Coastguard Worker for (UInt32 bi = 0; bi < f.propsSize; bi++) 288*f6dc9357SAndroid Build Coastguard Worker { 289*f6dc9357SAndroid Build Coastguard Worker const unsigned v = f.props[bi]; 290*f6dc9357SAndroid Build Coastguard Worker s.Add_Char(GET_HEX_CHAR_UPPER(v >> 4)); 291*f6dc9357SAndroid Build Coastguard Worker s.Add_Char(GET_HEX_CHAR_UPPER(v & 15)); 292*f6dc9357SAndroid Build Coastguard Worker } 293*f6dc9357SAndroid Build Coastguard Worker s.Add_Char(']'); 294*f6dc9357SAndroid Build Coastguard Worker } 295*f6dc9357SAndroid Build Coastguard Worker } 296*f6dc9357SAndroid Build Coastguard Worker } 297*f6dc9357SAndroid Build Coastguard Worker 298*f6dc9357SAndroid Build Coastguard Worker static const char * const kChecks[] = 299*f6dc9357SAndroid Build Coastguard Worker { 300*f6dc9357SAndroid Build Coastguard Worker "NoCheck" 301*f6dc9357SAndroid Build Coastguard Worker , "CRC32" 302*f6dc9357SAndroid Build Coastguard Worker , NULL 303*f6dc9357SAndroid Build Coastguard Worker , NULL 304*f6dc9357SAndroid Build Coastguard Worker , "CRC64" 305*f6dc9357SAndroid Build Coastguard Worker , NULL 306*f6dc9357SAndroid Build Coastguard Worker , NULL 307*f6dc9357SAndroid Build Coastguard Worker , NULL 308*f6dc9357SAndroid Build Coastguard Worker , NULL 309*f6dc9357SAndroid Build Coastguard Worker , NULL 310*f6dc9357SAndroid Build Coastguard Worker , "SHA256" 311*f6dc9357SAndroid Build Coastguard Worker , NULL 312*f6dc9357SAndroid Build Coastguard Worker , NULL 313*f6dc9357SAndroid Build Coastguard Worker , NULL 314*f6dc9357SAndroid Build Coastguard Worker , NULL 315*f6dc9357SAndroid Build Coastguard Worker , NULL 316*f6dc9357SAndroid Build Coastguard Worker }; 317*f6dc9357SAndroid Build Coastguard Worker 318*f6dc9357SAndroid Build Coastguard Worker static void AddCheckString(AString &s, const CXzs &xzs) 319*f6dc9357SAndroid Build Coastguard Worker { 320*f6dc9357SAndroid Build Coastguard Worker size_t i; 321*f6dc9357SAndroid Build Coastguard Worker UInt32 mask = 0; 322*f6dc9357SAndroid Build Coastguard Worker for (i = 0; i < xzs.num; i++) 323*f6dc9357SAndroid Build Coastguard Worker mask |= ((UInt32)1 << XzFlags_GetCheckType(xzs.streams[i].flags)); 324*f6dc9357SAndroid Build Coastguard Worker for (i = 0; i <= XZ_CHECK_MASK; i++) 325*f6dc9357SAndroid Build Coastguard Worker if (((mask >> i) & 1) != 0) 326*f6dc9357SAndroid Build Coastguard Worker { 327*f6dc9357SAndroid Build Coastguard Worker s.Add_Space_if_NotEmpty(); 328*f6dc9357SAndroid Build Coastguard Worker if (kChecks[i]) 329*f6dc9357SAndroid Build Coastguard Worker s += kChecks[i]; 330*f6dc9357SAndroid Build Coastguard Worker else 331*f6dc9357SAndroid Build Coastguard Worker { 332*f6dc9357SAndroid Build Coastguard Worker s += "Check-"; 333*f6dc9357SAndroid Build Coastguard Worker s.Add_UInt32((UInt32)i); 334*f6dc9357SAndroid Build Coastguard Worker } 335*f6dc9357SAndroid Build Coastguard Worker } 336*f6dc9357SAndroid Build Coastguard Worker } 337*f6dc9357SAndroid Build Coastguard Worker 338*f6dc9357SAndroid Build Coastguard Worker Z7_COM7F_IMF(CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value)) 339*f6dc9357SAndroid Build Coastguard Worker { 340*f6dc9357SAndroid Build Coastguard Worker COM_TRY_BEGIN 341*f6dc9357SAndroid Build Coastguard Worker NCOM::CPropVariant prop; 342*f6dc9357SAndroid Build Coastguard Worker 343*f6dc9357SAndroid Build Coastguard Worker const CXzStatInfo *stat = GetStat(); 344*f6dc9357SAndroid Build Coastguard Worker 345*f6dc9357SAndroid Build Coastguard Worker switch (propID) 346*f6dc9357SAndroid Build Coastguard Worker { 347*f6dc9357SAndroid Build Coastguard Worker case kpidPhySize: if (stat) prop = stat->InSize; break; 348*f6dc9357SAndroid Build Coastguard Worker case kpidNumStreams: if (stat && stat->NumStreams_Defined) prop = stat->NumStreams; break; 349*f6dc9357SAndroid Build Coastguard Worker case kpidNumBlocks: if (stat && stat->NumBlocks_Defined) prop = stat->NumBlocks; break; 350*f6dc9357SAndroid Build Coastguard Worker case kpidUnpackSize: if (stat && stat->UnpackSize_Defined) prop = stat->OutSize; break; 351*f6dc9357SAndroid Build Coastguard Worker case kpidClusterSize: if (_stat_defined && _stat.NumBlocks_Defined && stat->NumBlocks > 1) prop = _maxBlocksSize; break; 352*f6dc9357SAndroid Build Coastguard Worker case kpidCharacts: 353*f6dc9357SAndroid Build Coastguard Worker if (_firstBlockWasRead) 354*f6dc9357SAndroid Build Coastguard Worker { 355*f6dc9357SAndroid Build Coastguard Worker AString s; 356*f6dc9357SAndroid Build Coastguard Worker if (XzBlock_HasPackSize(&_firstBlock)) 357*f6dc9357SAndroid Build Coastguard Worker s.Add_OptSpaced("BlockPackSize"); 358*f6dc9357SAndroid Build Coastguard Worker if (XzBlock_HasUnpackSize(&_firstBlock)) 359*f6dc9357SAndroid Build Coastguard Worker s.Add_OptSpaced("BlockUnpackSize"); 360*f6dc9357SAndroid Build Coastguard Worker if (!s.IsEmpty()) 361*f6dc9357SAndroid Build Coastguard Worker prop = s; 362*f6dc9357SAndroid Build Coastguard Worker } 363*f6dc9357SAndroid Build Coastguard Worker break; 364*f6dc9357SAndroid Build Coastguard Worker 365*f6dc9357SAndroid Build Coastguard Worker 366*f6dc9357SAndroid Build Coastguard Worker case kpidMethod: if (!_methodsString.IsEmpty()) prop = _methodsString; break; 367*f6dc9357SAndroid Build Coastguard Worker case kpidErrorFlags: 368*f6dc9357SAndroid Build Coastguard Worker { 369*f6dc9357SAndroid Build Coastguard Worker UInt32 v = 0; 370*f6dc9357SAndroid Build Coastguard Worker SRes sres = _stat2_decode_SRes; 371*f6dc9357SAndroid Build Coastguard Worker if (!_isArc) v |= kpv_ErrorFlags_IsNotArc; 372*f6dc9357SAndroid Build Coastguard Worker if (sres == SZ_ERROR_INPUT_EOF) v |= kpv_ErrorFlags_UnexpectedEnd; 373*f6dc9357SAndroid Build Coastguard Worker if (_stat2_defined && _stat2.DataAfterEnd) v |= kpv_ErrorFlags_DataAfterEnd; 374*f6dc9357SAndroid Build Coastguard Worker if (sres == SZ_ERROR_ARCHIVE) v |= kpv_ErrorFlags_HeadersError; 375*f6dc9357SAndroid Build Coastguard Worker if (sres == SZ_ERROR_UNSUPPORTED) v |= kpv_ErrorFlags_UnsupportedMethod; 376*f6dc9357SAndroid Build Coastguard Worker if (sres == SZ_ERROR_DATA) v |= kpv_ErrorFlags_DataError; 377*f6dc9357SAndroid Build Coastguard Worker if (sres == SZ_ERROR_CRC) v |= kpv_ErrorFlags_CrcError; 378*f6dc9357SAndroid Build Coastguard Worker if (v != 0) 379*f6dc9357SAndroid Build Coastguard Worker prop = v; 380*f6dc9357SAndroid Build Coastguard Worker break; 381*f6dc9357SAndroid Build Coastguard Worker } 382*f6dc9357SAndroid Build Coastguard Worker 383*f6dc9357SAndroid Build Coastguard Worker case kpidMainSubfile: 384*f6dc9357SAndroid Build Coastguard Worker { 385*f6dc9357SAndroid Build Coastguard Worker // debug only, comment it: 386*f6dc9357SAndroid Build Coastguard Worker // if (_blocks) prop = (UInt32)0; 387*f6dc9357SAndroid Build Coastguard Worker break; 388*f6dc9357SAndroid Build Coastguard Worker } 389*f6dc9357SAndroid Build Coastguard Worker default: break; 390*f6dc9357SAndroid Build Coastguard Worker } 391*f6dc9357SAndroid Build Coastguard Worker prop.Detach(value); 392*f6dc9357SAndroid Build Coastguard Worker return S_OK; 393*f6dc9357SAndroid Build Coastguard Worker COM_TRY_END 394*f6dc9357SAndroid Build Coastguard Worker } 395*f6dc9357SAndroid Build Coastguard Worker 396*f6dc9357SAndroid Build Coastguard Worker Z7_COM7F_IMF(CHandler::GetNumberOfItems(UInt32 *numItems)) 397*f6dc9357SAndroid Build Coastguard Worker { 398*f6dc9357SAndroid Build Coastguard Worker *numItems = 1; 399*f6dc9357SAndroid Build Coastguard Worker return S_OK; 400*f6dc9357SAndroid Build Coastguard Worker } 401*f6dc9357SAndroid Build Coastguard Worker 402*f6dc9357SAndroid Build Coastguard Worker Z7_COM7F_IMF(CHandler::GetProperty(UInt32, PROPID propID, PROPVARIANT *value)) 403*f6dc9357SAndroid Build Coastguard Worker { 404*f6dc9357SAndroid Build Coastguard Worker COM_TRY_BEGIN 405*f6dc9357SAndroid Build Coastguard Worker const CXzStatInfo *stat = GetStat(); 406*f6dc9357SAndroid Build Coastguard Worker NCOM::CPropVariant prop; 407*f6dc9357SAndroid Build Coastguard Worker switch (propID) 408*f6dc9357SAndroid Build Coastguard Worker { 409*f6dc9357SAndroid Build Coastguard Worker case kpidSize: if (stat && stat->UnpackSize_Defined) prop = stat->OutSize; break; 410*f6dc9357SAndroid Build Coastguard Worker case kpidPackSize: if (stat) prop = stat->InSize; break; 411*f6dc9357SAndroid Build Coastguard Worker case kpidMethod: if (!_methodsString.IsEmpty()) prop = _methodsString; break; 412*f6dc9357SAndroid Build Coastguard Worker default: break; 413*f6dc9357SAndroid Build Coastguard Worker } 414*f6dc9357SAndroid Build Coastguard Worker prop.Detach(value); 415*f6dc9357SAndroid Build Coastguard Worker return S_OK; 416*f6dc9357SAndroid Build Coastguard Worker COM_TRY_END 417*f6dc9357SAndroid Build Coastguard Worker } 418*f6dc9357SAndroid Build Coastguard Worker 419*f6dc9357SAndroid Build Coastguard Worker 420*f6dc9357SAndroid Build Coastguard Worker struct COpenCallbackWrap 421*f6dc9357SAndroid Build Coastguard Worker { 422*f6dc9357SAndroid Build Coastguard Worker ICompressProgress vt; 423*f6dc9357SAndroid Build Coastguard Worker IArchiveOpenCallback *OpenCallback; 424*f6dc9357SAndroid Build Coastguard Worker HRESULT Res; 425*f6dc9357SAndroid Build Coastguard Worker 426*f6dc9357SAndroid Build Coastguard Worker // new clang shows "non-POD" warning for offsetof(), if we use constructor instead of Init() 427*f6dc9357SAndroid Build Coastguard Worker void Init(IArchiveOpenCallback *progress); 428*f6dc9357SAndroid Build Coastguard Worker }; 429*f6dc9357SAndroid Build Coastguard Worker 430*f6dc9357SAndroid Build Coastguard Worker static SRes OpenCallbackProgress(ICompressProgressPtr pp, UInt64 inSize, UInt64 /* outSize */) 431*f6dc9357SAndroid Build Coastguard Worker { 432*f6dc9357SAndroid Build Coastguard Worker Z7_CONTAINER_FROM_VTBL_TO_DECL_VAR_pp_vt_p(COpenCallbackWrap) 433*f6dc9357SAndroid Build Coastguard Worker if (p->OpenCallback) 434*f6dc9357SAndroid Build Coastguard Worker p->Res = p->OpenCallback->SetCompleted(NULL, &inSize); 435*f6dc9357SAndroid Build Coastguard Worker return HRESULT_To_SRes(p->Res, SZ_ERROR_PROGRESS); 436*f6dc9357SAndroid Build Coastguard Worker } 437*f6dc9357SAndroid Build Coastguard Worker 438*f6dc9357SAndroid Build Coastguard Worker void COpenCallbackWrap::Init(IArchiveOpenCallback *callback) 439*f6dc9357SAndroid Build Coastguard Worker { 440*f6dc9357SAndroid Build Coastguard Worker vt.Progress = OpenCallbackProgress; 441*f6dc9357SAndroid Build Coastguard Worker OpenCallback = callback; 442*f6dc9357SAndroid Build Coastguard Worker Res = SZ_OK; 443*f6dc9357SAndroid Build Coastguard Worker } 444*f6dc9357SAndroid Build Coastguard Worker 445*f6dc9357SAndroid Build Coastguard Worker 446*f6dc9357SAndroid Build Coastguard Worker struct CXzsCPP 447*f6dc9357SAndroid Build Coastguard Worker { 448*f6dc9357SAndroid Build Coastguard Worker CXzs p; 449*f6dc9357SAndroid Build Coastguard Worker CXzsCPP() { Xzs_Construct(&p); } 450*f6dc9357SAndroid Build Coastguard Worker ~CXzsCPP() { Xzs_Free(&p, &g_Alloc); } 451*f6dc9357SAndroid Build Coastguard Worker }; 452*f6dc9357SAndroid Build Coastguard Worker 453*f6dc9357SAndroid Build Coastguard Worker #define kInputBufSize ((size_t)1 << 10) 454*f6dc9357SAndroid Build Coastguard Worker 455*f6dc9357SAndroid Build Coastguard Worker struct CLookToRead2_CPP: public CLookToRead2 456*f6dc9357SAndroid Build Coastguard Worker { 457*f6dc9357SAndroid Build Coastguard Worker CLookToRead2_CPP() 458*f6dc9357SAndroid Build Coastguard Worker { 459*f6dc9357SAndroid Build Coastguard Worker buf = NULL; 460*f6dc9357SAndroid Build Coastguard Worker LookToRead2_CreateVTable(this, 461*f6dc9357SAndroid Build Coastguard Worker True // Lookahead ? 462*f6dc9357SAndroid Build Coastguard Worker ); 463*f6dc9357SAndroid Build Coastguard Worker } 464*f6dc9357SAndroid Build Coastguard Worker void Alloc(size_t allocSize) 465*f6dc9357SAndroid Build Coastguard Worker { 466*f6dc9357SAndroid Build Coastguard Worker buf = (Byte *)MyAlloc(allocSize); 467*f6dc9357SAndroid Build Coastguard Worker if (buf) 468*f6dc9357SAndroid Build Coastguard Worker this->bufSize = allocSize; 469*f6dc9357SAndroid Build Coastguard Worker } 470*f6dc9357SAndroid Build Coastguard Worker ~CLookToRead2_CPP() 471*f6dc9357SAndroid Build Coastguard Worker { 472*f6dc9357SAndroid Build Coastguard Worker MyFree(buf); 473*f6dc9357SAndroid Build Coastguard Worker } 474*f6dc9357SAndroid Build Coastguard Worker }; 475*f6dc9357SAndroid Build Coastguard Worker 476*f6dc9357SAndroid Build Coastguard Worker 477*f6dc9357SAndroid Build Coastguard Worker static HRESULT SRes_to_Open_HRESULT(SRes res) 478*f6dc9357SAndroid Build Coastguard Worker { 479*f6dc9357SAndroid Build Coastguard Worker switch (res) 480*f6dc9357SAndroid Build Coastguard Worker { 481*f6dc9357SAndroid Build Coastguard Worker case SZ_OK: return S_OK; 482*f6dc9357SAndroid Build Coastguard Worker case SZ_ERROR_MEM: return E_OUTOFMEMORY; 483*f6dc9357SAndroid Build Coastguard Worker case SZ_ERROR_PROGRESS: return E_ABORT; 484*f6dc9357SAndroid Build Coastguard Worker /* 485*f6dc9357SAndroid Build Coastguard Worker case SZ_ERROR_UNSUPPORTED: 486*f6dc9357SAndroid Build Coastguard Worker case SZ_ERROR_CRC: 487*f6dc9357SAndroid Build Coastguard Worker case SZ_ERROR_DATA: 488*f6dc9357SAndroid Build Coastguard Worker case SZ_ERROR_ARCHIVE: 489*f6dc9357SAndroid Build Coastguard Worker case SZ_ERROR_NO_ARCHIVE: 490*f6dc9357SAndroid Build Coastguard Worker return S_FALSE; 491*f6dc9357SAndroid Build Coastguard Worker */ 492*f6dc9357SAndroid Build Coastguard Worker default: break; 493*f6dc9357SAndroid Build Coastguard Worker } 494*f6dc9357SAndroid Build Coastguard Worker return S_FALSE; 495*f6dc9357SAndroid Build Coastguard Worker } 496*f6dc9357SAndroid Build Coastguard Worker 497*f6dc9357SAndroid Build Coastguard Worker 498*f6dc9357SAndroid Build Coastguard Worker 499*f6dc9357SAndroid Build Coastguard Worker HRESULT CHandler::Open2(IInStream *inStream, /* UInt32 flags, */ IArchiveOpenCallback *callback) 500*f6dc9357SAndroid Build Coastguard Worker { 501*f6dc9357SAndroid Build Coastguard Worker _needSeekToStart = true; 502*f6dc9357SAndroid Build Coastguard Worker 503*f6dc9357SAndroid Build Coastguard Worker { 504*f6dc9357SAndroid Build Coastguard Worker CXzStreamFlags st; 505*f6dc9357SAndroid Build Coastguard Worker CSeqInStreamWrap inStreamWrap; 506*f6dc9357SAndroid Build Coastguard Worker 507*f6dc9357SAndroid Build Coastguard Worker inStreamWrap.Init(inStream); 508*f6dc9357SAndroid Build Coastguard Worker 509*f6dc9357SAndroid Build Coastguard Worker SRes res = Xz_ReadHeader(&st, &inStreamWrap.vt); 510*f6dc9357SAndroid Build Coastguard Worker 511*f6dc9357SAndroid Build Coastguard Worker if (inStreamWrap.Res != S_OK) 512*f6dc9357SAndroid Build Coastguard Worker return inStreamWrap.Res; 513*f6dc9357SAndroid Build Coastguard Worker if (res != SZ_OK) 514*f6dc9357SAndroid Build Coastguard Worker return SRes_to_Open_HRESULT(res); 515*f6dc9357SAndroid Build Coastguard Worker 516*f6dc9357SAndroid Build Coastguard Worker { 517*f6dc9357SAndroid Build Coastguard Worker CXzBlock block; 518*f6dc9357SAndroid Build Coastguard Worker BoolInt isIndex; 519*f6dc9357SAndroid Build Coastguard Worker UInt32 headerSizeRes; 520*f6dc9357SAndroid Build Coastguard Worker 521*f6dc9357SAndroid Build Coastguard Worker SRes res2 = XzBlock_ReadHeader(&block, &inStreamWrap.vt, &isIndex, &headerSizeRes); 522*f6dc9357SAndroid Build Coastguard Worker 523*f6dc9357SAndroid Build Coastguard Worker if (inStreamWrap.Res != S_OK) 524*f6dc9357SAndroid Build Coastguard Worker return inStreamWrap.Res; 525*f6dc9357SAndroid Build Coastguard Worker 526*f6dc9357SAndroid Build Coastguard Worker if (res2 != SZ_OK) 527*f6dc9357SAndroid Build Coastguard Worker { 528*f6dc9357SAndroid Build Coastguard Worker if (res2 == SZ_ERROR_INPUT_EOF) 529*f6dc9357SAndroid Build Coastguard Worker { 530*f6dc9357SAndroid Build Coastguard Worker _stat2_decode_SRes = res2; 531*f6dc9357SAndroid Build Coastguard Worker _stream = inStream; 532*f6dc9357SAndroid Build Coastguard Worker _seqStream = inStream; 533*f6dc9357SAndroid Build Coastguard Worker _isArc = true; 534*f6dc9357SAndroid Build Coastguard Worker return S_OK; 535*f6dc9357SAndroid Build Coastguard Worker } 536*f6dc9357SAndroid Build Coastguard Worker 537*f6dc9357SAndroid Build Coastguard Worker if (res2 == SZ_ERROR_ARCHIVE) 538*f6dc9357SAndroid Build Coastguard Worker return S_FALSE; 539*f6dc9357SAndroid Build Coastguard Worker } 540*f6dc9357SAndroid Build Coastguard Worker else if (!isIndex) 541*f6dc9357SAndroid Build Coastguard Worker { 542*f6dc9357SAndroid Build Coastguard Worker _firstBlockWasRead = true; 543*f6dc9357SAndroid Build Coastguard Worker _firstBlock = block; 544*f6dc9357SAndroid Build Coastguard Worker 545*f6dc9357SAndroid Build Coastguard Worker unsigned numFilters = XzBlock_GetNumFilters(&block); 546*f6dc9357SAndroid Build Coastguard Worker for (unsigned i = 0; i < numFilters; i++) 547*f6dc9357SAndroid Build Coastguard Worker { 548*f6dc9357SAndroid Build Coastguard Worker _methodsString.Add_Space_if_NotEmpty(); 549*f6dc9357SAndroid Build Coastguard Worker AddMethodString(_methodsString, block.filters[i]); 550*f6dc9357SAndroid Build Coastguard Worker } 551*f6dc9357SAndroid Build Coastguard Worker } 552*f6dc9357SAndroid Build Coastguard Worker } 553*f6dc9357SAndroid Build Coastguard Worker } 554*f6dc9357SAndroid Build Coastguard Worker 555*f6dc9357SAndroid Build Coastguard Worker RINOK(InStream_GetSize_SeekToEnd(inStream, _stat.InSize)) 556*f6dc9357SAndroid Build Coastguard Worker if (callback) 557*f6dc9357SAndroid Build Coastguard Worker { 558*f6dc9357SAndroid Build Coastguard Worker RINOK(callback->SetTotal(NULL, &_stat.InSize)) 559*f6dc9357SAndroid Build Coastguard Worker } 560*f6dc9357SAndroid Build Coastguard Worker 561*f6dc9357SAndroid Build Coastguard Worker CSeekInStreamWrap inStreamImp; 562*f6dc9357SAndroid Build Coastguard Worker 563*f6dc9357SAndroid Build Coastguard Worker inStreamImp.Init(inStream); 564*f6dc9357SAndroid Build Coastguard Worker 565*f6dc9357SAndroid Build Coastguard Worker CLookToRead2_CPP lookStream; 566*f6dc9357SAndroid Build Coastguard Worker 567*f6dc9357SAndroid Build Coastguard Worker lookStream.Alloc(kInputBufSize); 568*f6dc9357SAndroid Build Coastguard Worker 569*f6dc9357SAndroid Build Coastguard Worker if (!lookStream.buf) 570*f6dc9357SAndroid Build Coastguard Worker return E_OUTOFMEMORY; 571*f6dc9357SAndroid Build Coastguard Worker 572*f6dc9357SAndroid Build Coastguard Worker lookStream.realStream = &inStreamImp.vt; 573*f6dc9357SAndroid Build Coastguard Worker LookToRead2_INIT(&lookStream) 574*f6dc9357SAndroid Build Coastguard Worker 575*f6dc9357SAndroid Build Coastguard Worker COpenCallbackWrap openWrap; 576*f6dc9357SAndroid Build Coastguard Worker openWrap.Init(callback); 577*f6dc9357SAndroid Build Coastguard Worker 578*f6dc9357SAndroid Build Coastguard Worker CXzsCPP xzs; 579*f6dc9357SAndroid Build Coastguard Worker Int64 startPosition; 580*f6dc9357SAndroid Build Coastguard Worker SRes res = Xzs_ReadBackward(&xzs.p, &lookStream.vt, &startPosition, &openWrap.vt, &g_Alloc); 581*f6dc9357SAndroid Build Coastguard Worker if (res == SZ_ERROR_PROGRESS) 582*f6dc9357SAndroid Build Coastguard Worker return (openWrap.Res == S_OK) ? E_FAIL : openWrap.Res; 583*f6dc9357SAndroid Build Coastguard Worker /* 584*f6dc9357SAndroid Build Coastguard Worker if (res == SZ_ERROR_NO_ARCHIVE && xzs.p.num > 0) 585*f6dc9357SAndroid Build Coastguard Worker res = SZ_OK; 586*f6dc9357SAndroid Build Coastguard Worker */ 587*f6dc9357SAndroid Build Coastguard Worker if (res == SZ_OK && startPosition == 0) 588*f6dc9357SAndroid Build Coastguard Worker { 589*f6dc9357SAndroid Build Coastguard Worker _stat_defined = true; 590*f6dc9357SAndroid Build Coastguard Worker 591*f6dc9357SAndroid Build Coastguard Worker _stat.OutSize = Xzs_GetUnpackSize(&xzs.p); 592*f6dc9357SAndroid Build Coastguard Worker _stat.UnpackSize_Defined = true; 593*f6dc9357SAndroid Build Coastguard Worker 594*f6dc9357SAndroid Build Coastguard Worker _stat.NumStreams = xzs.p.num; 595*f6dc9357SAndroid Build Coastguard Worker _stat.NumStreams_Defined = true; 596*f6dc9357SAndroid Build Coastguard Worker 597*f6dc9357SAndroid Build Coastguard Worker _stat.NumBlocks = Xzs_GetNumBlocks(&xzs.p); 598*f6dc9357SAndroid Build Coastguard Worker _stat.NumBlocks_Defined = true; 599*f6dc9357SAndroid Build Coastguard Worker 600*f6dc9357SAndroid Build Coastguard Worker AddCheckString(_methodsString, xzs.p); 601*f6dc9357SAndroid Build Coastguard Worker 602*f6dc9357SAndroid Build Coastguard Worker const size_t numBlocks = (size_t)_stat.NumBlocks + 1; 603*f6dc9357SAndroid Build Coastguard Worker const size_t bytesAlloc = numBlocks * sizeof(CBlockInfo); 604*f6dc9357SAndroid Build Coastguard Worker 605*f6dc9357SAndroid Build Coastguard Worker if (bytesAlloc / sizeof(CBlockInfo) == _stat.NumBlocks + 1) 606*f6dc9357SAndroid Build Coastguard Worker { 607*f6dc9357SAndroid Build Coastguard Worker _blocks = (CBlockInfo *)MyAlloc(bytesAlloc); 608*f6dc9357SAndroid Build Coastguard Worker if (_blocks) 609*f6dc9357SAndroid Build Coastguard Worker { 610*f6dc9357SAndroid Build Coastguard Worker unsigned blockIndex = 0; 611*f6dc9357SAndroid Build Coastguard Worker UInt64 unpackPos = 0; 612*f6dc9357SAndroid Build Coastguard Worker 613*f6dc9357SAndroid Build Coastguard Worker for (size_t si = xzs.p.num; si != 0;) 614*f6dc9357SAndroid Build Coastguard Worker { 615*f6dc9357SAndroid Build Coastguard Worker si--; 616*f6dc9357SAndroid Build Coastguard Worker const CXzStream &str = xzs.p.streams[si]; 617*f6dc9357SAndroid Build Coastguard Worker UInt64 packPos = str.startOffset + XZ_STREAM_HEADER_SIZE; 618*f6dc9357SAndroid Build Coastguard Worker 619*f6dc9357SAndroid Build Coastguard Worker for (size_t bi = 0; bi < str.numBlocks; bi++) 620*f6dc9357SAndroid Build Coastguard Worker { 621*f6dc9357SAndroid Build Coastguard Worker const CXzBlockSizes &bs = str.blocks[bi]; 622*f6dc9357SAndroid Build Coastguard Worker const UInt64 packSizeAligned = bs.totalSize + ((0 - (unsigned)bs.totalSize) & 3); 623*f6dc9357SAndroid Build Coastguard Worker 624*f6dc9357SAndroid Build Coastguard Worker if (bs.unpackSize != 0) 625*f6dc9357SAndroid Build Coastguard Worker { 626*f6dc9357SAndroid Build Coastguard Worker if (blockIndex >= _stat.NumBlocks) 627*f6dc9357SAndroid Build Coastguard Worker return E_FAIL; 628*f6dc9357SAndroid Build Coastguard Worker 629*f6dc9357SAndroid Build Coastguard Worker CBlockInfo &block = _blocks[blockIndex++]; 630*f6dc9357SAndroid Build Coastguard Worker block.StreamFlags = str.flags; 631*f6dc9357SAndroid Build Coastguard Worker block.PackSize = bs.totalSize; // packSizeAligned; 632*f6dc9357SAndroid Build Coastguard Worker block.PackPos = packPos; 633*f6dc9357SAndroid Build Coastguard Worker block.UnpackPos = unpackPos; 634*f6dc9357SAndroid Build Coastguard Worker } 635*f6dc9357SAndroid Build Coastguard Worker packPos += packSizeAligned; 636*f6dc9357SAndroid Build Coastguard Worker unpackPos += bs.unpackSize; 637*f6dc9357SAndroid Build Coastguard Worker if (_maxBlocksSize < bs.unpackSize) 638*f6dc9357SAndroid Build Coastguard Worker _maxBlocksSize = bs.unpackSize; 639*f6dc9357SAndroid Build Coastguard Worker } 640*f6dc9357SAndroid Build Coastguard Worker } 641*f6dc9357SAndroid Build Coastguard Worker 642*f6dc9357SAndroid Build Coastguard Worker /* 643*f6dc9357SAndroid Build Coastguard Worker if (blockIndex != _stat.NumBlocks) 644*f6dc9357SAndroid Build Coastguard Worker { 645*f6dc9357SAndroid Build Coastguard Worker // there are Empty blocks; 646*f6dc9357SAndroid Build Coastguard Worker } 647*f6dc9357SAndroid Build Coastguard Worker */ 648*f6dc9357SAndroid Build Coastguard Worker if (_stat.OutSize != unpackPos) 649*f6dc9357SAndroid Build Coastguard Worker return E_FAIL; 650*f6dc9357SAndroid Build Coastguard Worker CBlockInfo &block = _blocks[blockIndex++]; 651*f6dc9357SAndroid Build Coastguard Worker block.StreamFlags = 0; 652*f6dc9357SAndroid Build Coastguard Worker block.PackSize = 0; 653*f6dc9357SAndroid Build Coastguard Worker block.PackPos = 0; 654*f6dc9357SAndroid Build Coastguard Worker block.UnpackPos = unpackPos; 655*f6dc9357SAndroid Build Coastguard Worker _blocksArraySize = blockIndex; 656*f6dc9357SAndroid Build Coastguard Worker } 657*f6dc9357SAndroid Build Coastguard Worker } 658*f6dc9357SAndroid Build Coastguard Worker } 659*f6dc9357SAndroid Build Coastguard Worker else 660*f6dc9357SAndroid Build Coastguard Worker { 661*f6dc9357SAndroid Build Coastguard Worker res = SZ_OK; 662*f6dc9357SAndroid Build Coastguard Worker } 663*f6dc9357SAndroid Build Coastguard Worker 664*f6dc9357SAndroid Build Coastguard Worker RINOK(SRes_to_Open_HRESULT(res)) 665*f6dc9357SAndroid Build Coastguard Worker 666*f6dc9357SAndroid Build Coastguard Worker _stream = inStream; 667*f6dc9357SAndroid Build Coastguard Worker _seqStream = inStream; 668*f6dc9357SAndroid Build Coastguard Worker _isArc = true; 669*f6dc9357SAndroid Build Coastguard Worker return S_OK; 670*f6dc9357SAndroid Build Coastguard Worker } 671*f6dc9357SAndroid Build Coastguard Worker 672*f6dc9357SAndroid Build Coastguard Worker 673*f6dc9357SAndroid Build Coastguard Worker 674*f6dc9357SAndroid Build Coastguard Worker Z7_COM7F_IMF(CHandler::Open(IInStream *inStream, const UInt64 *, IArchiveOpenCallback *callback)) 675*f6dc9357SAndroid Build Coastguard Worker { 676*f6dc9357SAndroid Build Coastguard Worker COM_TRY_BEGIN 677*f6dc9357SAndroid Build Coastguard Worker { 678*f6dc9357SAndroid Build Coastguard Worker Close(); 679*f6dc9357SAndroid Build Coastguard Worker return Open2(inStream, callback); 680*f6dc9357SAndroid Build Coastguard Worker } 681*f6dc9357SAndroid Build Coastguard Worker COM_TRY_END 682*f6dc9357SAndroid Build Coastguard Worker } 683*f6dc9357SAndroid Build Coastguard Worker 684*f6dc9357SAndroid Build Coastguard Worker Z7_COM7F_IMF(CHandler::OpenSeq(ISequentialInStream *stream)) 685*f6dc9357SAndroid Build Coastguard Worker { 686*f6dc9357SAndroid Build Coastguard Worker Close(); 687*f6dc9357SAndroid Build Coastguard Worker _seqStream = stream; 688*f6dc9357SAndroid Build Coastguard Worker _isArc = true; 689*f6dc9357SAndroid Build Coastguard Worker _needSeekToStart = false; 690*f6dc9357SAndroid Build Coastguard Worker return S_OK; 691*f6dc9357SAndroid Build Coastguard Worker } 692*f6dc9357SAndroid Build Coastguard Worker 693*f6dc9357SAndroid Build Coastguard Worker Z7_COM7F_IMF(CHandler::Close()) 694*f6dc9357SAndroid Build Coastguard Worker { 695*f6dc9357SAndroid Build Coastguard Worker XzStatInfo_Clear(&_stat); 696*f6dc9357SAndroid Build Coastguard Worker XzStatInfo_Clear(&_stat2); 697*f6dc9357SAndroid Build Coastguard Worker _stat_defined = false; 698*f6dc9357SAndroid Build Coastguard Worker _stat2_defined = false; 699*f6dc9357SAndroid Build Coastguard Worker _stat2_decode_SRes = SZ_OK; 700*f6dc9357SAndroid Build Coastguard Worker 701*f6dc9357SAndroid Build Coastguard Worker _isArc = false; 702*f6dc9357SAndroid Build Coastguard Worker _needSeekToStart = false; 703*f6dc9357SAndroid Build Coastguard Worker _firstBlockWasRead = false; 704*f6dc9357SAndroid Build Coastguard Worker 705*f6dc9357SAndroid Build Coastguard Worker _methodsString.Empty(); 706*f6dc9357SAndroid Build Coastguard Worker _stream.Release(); 707*f6dc9357SAndroid Build Coastguard Worker _seqStream.Release(); 708*f6dc9357SAndroid Build Coastguard Worker 709*f6dc9357SAndroid Build Coastguard Worker MyFree(_blocks); 710*f6dc9357SAndroid Build Coastguard Worker _blocks = NULL; 711*f6dc9357SAndroid Build Coastguard Worker _blocksArraySize = 0; 712*f6dc9357SAndroid Build Coastguard Worker _maxBlocksSize = 0; 713*f6dc9357SAndroid Build Coastguard Worker 714*f6dc9357SAndroid Build Coastguard Worker return S_OK; 715*f6dc9357SAndroid Build Coastguard Worker } 716*f6dc9357SAndroid Build Coastguard Worker 717*f6dc9357SAndroid Build Coastguard Worker 718*f6dc9357SAndroid Build Coastguard Worker struct CXzUnpackerCPP2 719*f6dc9357SAndroid Build Coastguard Worker { 720*f6dc9357SAndroid Build Coastguard Worker Byte *InBuf; 721*f6dc9357SAndroid Build Coastguard Worker // Byte *OutBuf; 722*f6dc9357SAndroid Build Coastguard Worker CXzUnpacker p; 723*f6dc9357SAndroid Build Coastguard Worker 724*f6dc9357SAndroid Build Coastguard Worker CXzUnpackerCPP2(); 725*f6dc9357SAndroid Build Coastguard Worker ~CXzUnpackerCPP2(); 726*f6dc9357SAndroid Build Coastguard Worker }; 727*f6dc9357SAndroid Build Coastguard Worker 728*f6dc9357SAndroid Build Coastguard Worker CXzUnpackerCPP2::CXzUnpackerCPP2(): InBuf(NULL) 729*f6dc9357SAndroid Build Coastguard Worker // , OutBuf(NULL) 730*f6dc9357SAndroid Build Coastguard Worker { 731*f6dc9357SAndroid Build Coastguard Worker XzUnpacker_Construct(&p, &g_Alloc); 732*f6dc9357SAndroid Build Coastguard Worker } 733*f6dc9357SAndroid Build Coastguard Worker 734*f6dc9357SAndroid Build Coastguard Worker CXzUnpackerCPP2::~CXzUnpackerCPP2() 735*f6dc9357SAndroid Build Coastguard Worker { 736*f6dc9357SAndroid Build Coastguard Worker XzUnpacker_Free(&p); 737*f6dc9357SAndroid Build Coastguard Worker MidFree(InBuf); 738*f6dc9357SAndroid Build Coastguard Worker // MidFree(OutBuf); 739*f6dc9357SAndroid Build Coastguard Worker } 740*f6dc9357SAndroid Build Coastguard Worker 741*f6dc9357SAndroid Build Coastguard Worker 742*f6dc9357SAndroid Build Coastguard Worker Z7_CLASS_IMP_IInStream( 743*f6dc9357SAndroid Build Coastguard Worker CInStream 744*f6dc9357SAndroid Build Coastguard Worker ) 745*f6dc9357SAndroid Build Coastguard Worker 746*f6dc9357SAndroid Build Coastguard Worker UInt64 _virtPos; 747*f6dc9357SAndroid Build Coastguard Worker public: 748*f6dc9357SAndroid Build Coastguard Worker UInt64 Size; 749*f6dc9357SAndroid Build Coastguard Worker UInt64 _cacheStartPos; 750*f6dc9357SAndroid Build Coastguard Worker size_t _cacheSize; 751*f6dc9357SAndroid Build Coastguard Worker CByteBuffer _cache; 752*f6dc9357SAndroid Build Coastguard Worker // UInt64 _startPos; 753*f6dc9357SAndroid Build Coastguard Worker CXzUnpackerCPP2 xz; 754*f6dc9357SAndroid Build Coastguard Worker 755*f6dc9357SAndroid Build Coastguard Worker void InitAndSeek() 756*f6dc9357SAndroid Build Coastguard Worker { 757*f6dc9357SAndroid Build Coastguard Worker _virtPos = 0; 758*f6dc9357SAndroid Build Coastguard Worker _cacheStartPos = 0; 759*f6dc9357SAndroid Build Coastguard Worker _cacheSize = 0; 760*f6dc9357SAndroid Build Coastguard Worker // _startPos = startPos; 761*f6dc9357SAndroid Build Coastguard Worker } 762*f6dc9357SAndroid Build Coastguard Worker 763*f6dc9357SAndroid Build Coastguard Worker CMyComPtr2<IInArchive, CHandler> _handlerSpec; 764*f6dc9357SAndroid Build Coastguard Worker // ~CInStream(); 765*f6dc9357SAndroid Build Coastguard Worker }; 766*f6dc9357SAndroid Build Coastguard Worker 767*f6dc9357SAndroid Build Coastguard Worker /* 768*f6dc9357SAndroid Build Coastguard Worker CInStream::~CInStream() 769*f6dc9357SAndroid Build Coastguard Worker { 770*f6dc9357SAndroid Build Coastguard Worker // _cache.Free(); 771*f6dc9357SAndroid Build Coastguard Worker } 772*f6dc9357SAndroid Build Coastguard Worker */ 773*f6dc9357SAndroid Build Coastguard Worker 774*f6dc9357SAndroid Build Coastguard Worker static size_t FindBlock(const CBlockInfo *blocks, size_t numBlocks, UInt64 pos) 775*f6dc9357SAndroid Build Coastguard Worker { 776*f6dc9357SAndroid Build Coastguard Worker size_t left = 0, right = numBlocks; 777*f6dc9357SAndroid Build Coastguard Worker for (;;) 778*f6dc9357SAndroid Build Coastguard Worker { 779*f6dc9357SAndroid Build Coastguard Worker size_t mid = (left + right) / 2; 780*f6dc9357SAndroid Build Coastguard Worker if (mid == left) 781*f6dc9357SAndroid Build Coastguard Worker return left; 782*f6dc9357SAndroid Build Coastguard Worker if (pos < blocks[mid].UnpackPos) 783*f6dc9357SAndroid Build Coastguard Worker right = mid; 784*f6dc9357SAndroid Build Coastguard Worker else 785*f6dc9357SAndroid Build Coastguard Worker left = mid; 786*f6dc9357SAndroid Build Coastguard Worker } 787*f6dc9357SAndroid Build Coastguard Worker } 788*f6dc9357SAndroid Build Coastguard Worker 789*f6dc9357SAndroid Build Coastguard Worker 790*f6dc9357SAndroid Build Coastguard Worker 791*f6dc9357SAndroid Build Coastguard Worker static HRESULT DecodeBlock(CXzUnpackerCPP2 &xzu, 792*f6dc9357SAndroid Build Coastguard Worker ISequentialInStream *seqInStream, 793*f6dc9357SAndroid Build Coastguard Worker unsigned streamFlags, 794*f6dc9357SAndroid Build Coastguard Worker UInt64 packSize, // pure size from Index record, it doesn't include pad zeros 795*f6dc9357SAndroid Build Coastguard Worker size_t unpackSize, Byte *dest 796*f6dc9357SAndroid Build Coastguard Worker // , ICompressProgressInfo *progress 797*f6dc9357SAndroid Build Coastguard Worker ) 798*f6dc9357SAndroid Build Coastguard Worker { 799*f6dc9357SAndroid Build Coastguard Worker const size_t kInBufSize = (size_t)1 << 16; 800*f6dc9357SAndroid Build Coastguard Worker 801*f6dc9357SAndroid Build Coastguard Worker XzUnpacker_Init(&xzu.p); 802*f6dc9357SAndroid Build Coastguard Worker 803*f6dc9357SAndroid Build Coastguard Worker if (!xzu.InBuf) 804*f6dc9357SAndroid Build Coastguard Worker { 805*f6dc9357SAndroid Build Coastguard Worker xzu.InBuf = (Byte *)MidAlloc(kInBufSize); 806*f6dc9357SAndroid Build Coastguard Worker if (!xzu.InBuf) 807*f6dc9357SAndroid Build Coastguard Worker return E_OUTOFMEMORY; 808*f6dc9357SAndroid Build Coastguard Worker } 809*f6dc9357SAndroid Build Coastguard Worker 810*f6dc9357SAndroid Build Coastguard Worker xzu.p.streamFlags = (UInt16)streamFlags; 811*f6dc9357SAndroid Build Coastguard Worker XzUnpacker_PrepareToRandomBlockDecoding(&xzu.p); 812*f6dc9357SAndroid Build Coastguard Worker 813*f6dc9357SAndroid Build Coastguard Worker XzUnpacker_SetOutBuf(&xzu.p, dest, unpackSize); 814*f6dc9357SAndroid Build Coastguard Worker 815*f6dc9357SAndroid Build Coastguard Worker const UInt64 packSizeAligned = packSize + ((0 - (unsigned)packSize) & 3); 816*f6dc9357SAndroid Build Coastguard Worker UInt64 packRem = packSizeAligned; 817*f6dc9357SAndroid Build Coastguard Worker 818*f6dc9357SAndroid Build Coastguard Worker UInt32 inSize = 0; 819*f6dc9357SAndroid Build Coastguard Worker SizeT inPos = 0; 820*f6dc9357SAndroid Build Coastguard Worker SizeT outPos = 0; 821*f6dc9357SAndroid Build Coastguard Worker 822*f6dc9357SAndroid Build Coastguard Worker HRESULT readRes = S_OK; 823*f6dc9357SAndroid Build Coastguard Worker 824*f6dc9357SAndroid Build Coastguard Worker for (;;) 825*f6dc9357SAndroid Build Coastguard Worker { 826*f6dc9357SAndroid Build Coastguard Worker if (inPos == inSize && readRes == S_OK) 827*f6dc9357SAndroid Build Coastguard Worker { 828*f6dc9357SAndroid Build Coastguard Worker inPos = 0; 829*f6dc9357SAndroid Build Coastguard Worker inSize = 0; 830*f6dc9357SAndroid Build Coastguard Worker UInt32 rem = kInBufSize; 831*f6dc9357SAndroid Build Coastguard Worker if (rem > packRem) 832*f6dc9357SAndroid Build Coastguard Worker rem = (UInt32)packRem; 833*f6dc9357SAndroid Build Coastguard Worker if (rem != 0) 834*f6dc9357SAndroid Build Coastguard Worker readRes = seqInStream->Read(xzu.InBuf, rem, &inSize); 835*f6dc9357SAndroid Build Coastguard Worker } 836*f6dc9357SAndroid Build Coastguard Worker 837*f6dc9357SAndroid Build Coastguard Worker SizeT inLen = inSize - inPos; 838*f6dc9357SAndroid Build Coastguard Worker SizeT outLen = unpackSize - outPos; 839*f6dc9357SAndroid Build Coastguard Worker 840*f6dc9357SAndroid Build Coastguard Worker ECoderStatus status; 841*f6dc9357SAndroid Build Coastguard Worker 842*f6dc9357SAndroid Build Coastguard Worker const SRes res = XzUnpacker_Code(&xzu.p, 843*f6dc9357SAndroid Build Coastguard Worker // dest + outPos, 844*f6dc9357SAndroid Build Coastguard Worker NULL, 845*f6dc9357SAndroid Build Coastguard Worker &outLen, 846*f6dc9357SAndroid Build Coastguard Worker xzu.InBuf + inPos, &inLen, 847*f6dc9357SAndroid Build Coastguard Worker (inLen == 0), // srcFinished 848*f6dc9357SAndroid Build Coastguard Worker CODER_FINISH_END, &status); 849*f6dc9357SAndroid Build Coastguard Worker 850*f6dc9357SAndroid Build Coastguard Worker // return E_OUTOFMEMORY; 851*f6dc9357SAndroid Build Coastguard Worker // res = SZ_ERROR_CRC; 852*f6dc9357SAndroid Build Coastguard Worker 853*f6dc9357SAndroid Build Coastguard Worker if (res != SZ_OK) 854*f6dc9357SAndroid Build Coastguard Worker { 855*f6dc9357SAndroid Build Coastguard Worker if (res == SZ_ERROR_CRC) 856*f6dc9357SAndroid Build Coastguard Worker return S_FALSE; 857*f6dc9357SAndroid Build Coastguard Worker return SResToHRESULT(res); 858*f6dc9357SAndroid Build Coastguard Worker } 859*f6dc9357SAndroid Build Coastguard Worker 860*f6dc9357SAndroid Build Coastguard Worker inPos += inLen; 861*f6dc9357SAndroid Build Coastguard Worker outPos += outLen; 862*f6dc9357SAndroid Build Coastguard Worker 863*f6dc9357SAndroid Build Coastguard Worker packRem -= inLen; 864*f6dc9357SAndroid Build Coastguard Worker 865*f6dc9357SAndroid Build Coastguard Worker const BoolInt blockFinished = XzUnpacker_IsBlockFinished(&xzu.p); 866*f6dc9357SAndroid Build Coastguard Worker 867*f6dc9357SAndroid Build Coastguard Worker if ((inLen == 0 && outLen == 0) || blockFinished) 868*f6dc9357SAndroid Build Coastguard Worker { 869*f6dc9357SAndroid Build Coastguard Worker if (packRem != 0 || !blockFinished || unpackSize != outPos) 870*f6dc9357SAndroid Build Coastguard Worker return S_FALSE; 871*f6dc9357SAndroid Build Coastguard Worker if (XzUnpacker_GetPackSizeForIndex(&xzu.p) != packSize) 872*f6dc9357SAndroid Build Coastguard Worker return S_FALSE; 873*f6dc9357SAndroid Build Coastguard Worker return S_OK; 874*f6dc9357SAndroid Build Coastguard Worker } 875*f6dc9357SAndroid Build Coastguard Worker } 876*f6dc9357SAndroid Build Coastguard Worker } 877*f6dc9357SAndroid Build Coastguard Worker 878*f6dc9357SAndroid Build Coastguard Worker 879*f6dc9357SAndroid Build Coastguard Worker Z7_COM7F_IMF(CInStream::Read(void *data, UInt32 size, UInt32 *processedSize)) 880*f6dc9357SAndroid Build Coastguard Worker { 881*f6dc9357SAndroid Build Coastguard Worker COM_TRY_BEGIN 882*f6dc9357SAndroid Build Coastguard Worker 883*f6dc9357SAndroid Build Coastguard Worker if (processedSize) 884*f6dc9357SAndroid Build Coastguard Worker *processedSize = 0; 885*f6dc9357SAndroid Build Coastguard Worker if (size == 0) 886*f6dc9357SAndroid Build Coastguard Worker return S_OK; 887*f6dc9357SAndroid Build Coastguard Worker 888*f6dc9357SAndroid Build Coastguard Worker { 889*f6dc9357SAndroid Build Coastguard Worker if (_virtPos >= Size) 890*f6dc9357SAndroid Build Coastguard Worker return S_OK; // (Size == _virtPos) ? S_OK: E_FAIL; 891*f6dc9357SAndroid Build Coastguard Worker { 892*f6dc9357SAndroid Build Coastguard Worker UInt64 rem = Size - _virtPos; 893*f6dc9357SAndroid Build Coastguard Worker if (size > rem) 894*f6dc9357SAndroid Build Coastguard Worker size = (UInt32)rem; 895*f6dc9357SAndroid Build Coastguard Worker } 896*f6dc9357SAndroid Build Coastguard Worker } 897*f6dc9357SAndroid Build Coastguard Worker 898*f6dc9357SAndroid Build Coastguard Worker if (size == 0) 899*f6dc9357SAndroid Build Coastguard Worker return S_OK; 900*f6dc9357SAndroid Build Coastguard Worker 901*f6dc9357SAndroid Build Coastguard Worker if (_virtPos < _cacheStartPos || _virtPos >= _cacheStartPos + _cacheSize) 902*f6dc9357SAndroid Build Coastguard Worker { 903*f6dc9357SAndroid Build Coastguard Worker const size_t bi = FindBlock(_handlerSpec->_blocks, _handlerSpec->_blocksArraySize, _virtPos); 904*f6dc9357SAndroid Build Coastguard Worker const CBlockInfo &block = _handlerSpec->_blocks[bi]; 905*f6dc9357SAndroid Build Coastguard Worker const UInt64 unpackSize = _handlerSpec->_blocks[bi + 1].UnpackPos - block.UnpackPos; 906*f6dc9357SAndroid Build Coastguard Worker if (_cache.Size() < unpackSize) 907*f6dc9357SAndroid Build Coastguard Worker return E_FAIL; 908*f6dc9357SAndroid Build Coastguard Worker 909*f6dc9357SAndroid Build Coastguard Worker _cacheSize = 0; 910*f6dc9357SAndroid Build Coastguard Worker 911*f6dc9357SAndroid Build Coastguard Worker RINOK(_handlerSpec->SeekToPackPos(block.PackPos)) 912*f6dc9357SAndroid Build Coastguard Worker RINOK(DecodeBlock(xz, _handlerSpec->_seqStream, block.StreamFlags, block.PackSize, 913*f6dc9357SAndroid Build Coastguard Worker (size_t)unpackSize, _cache)) 914*f6dc9357SAndroid Build Coastguard Worker _cacheStartPos = block.UnpackPos; 915*f6dc9357SAndroid Build Coastguard Worker _cacheSize = (size_t)unpackSize; 916*f6dc9357SAndroid Build Coastguard Worker } 917*f6dc9357SAndroid Build Coastguard Worker 918*f6dc9357SAndroid Build Coastguard Worker { 919*f6dc9357SAndroid Build Coastguard Worker const size_t offset = (size_t)(_virtPos - _cacheStartPos); 920*f6dc9357SAndroid Build Coastguard Worker const size_t rem = _cacheSize - offset; 921*f6dc9357SAndroid Build Coastguard Worker if (size > rem) 922*f6dc9357SAndroid Build Coastguard Worker size = (UInt32)rem; 923*f6dc9357SAndroid Build Coastguard Worker memcpy(data, _cache.ConstData() + offset, size); 924*f6dc9357SAndroid Build Coastguard Worker _virtPos += size; 925*f6dc9357SAndroid Build Coastguard Worker if (processedSize) 926*f6dc9357SAndroid Build Coastguard Worker *processedSize = size; 927*f6dc9357SAndroid Build Coastguard Worker return S_OK; 928*f6dc9357SAndroid Build Coastguard Worker } 929*f6dc9357SAndroid Build Coastguard Worker 930*f6dc9357SAndroid Build Coastguard Worker COM_TRY_END 931*f6dc9357SAndroid Build Coastguard Worker } 932*f6dc9357SAndroid Build Coastguard Worker 933*f6dc9357SAndroid Build Coastguard Worker 934*f6dc9357SAndroid Build Coastguard Worker Z7_COM7F_IMF(CInStream::Seek(Int64 offset, UInt32 seekOrigin, UInt64 *newPosition)) 935*f6dc9357SAndroid Build Coastguard Worker { 936*f6dc9357SAndroid Build Coastguard Worker switch (seekOrigin) 937*f6dc9357SAndroid Build Coastguard Worker { 938*f6dc9357SAndroid Build Coastguard Worker case STREAM_SEEK_SET: break; 939*f6dc9357SAndroid Build Coastguard Worker case STREAM_SEEK_CUR: offset += _virtPos; break; 940*f6dc9357SAndroid Build Coastguard Worker case STREAM_SEEK_END: offset += Size; break; 941*f6dc9357SAndroid Build Coastguard Worker default: return STG_E_INVALIDFUNCTION; 942*f6dc9357SAndroid Build Coastguard Worker } 943*f6dc9357SAndroid Build Coastguard Worker if (offset < 0) 944*f6dc9357SAndroid Build Coastguard Worker return HRESULT_WIN32_ERROR_NEGATIVE_SEEK; 945*f6dc9357SAndroid Build Coastguard Worker _virtPos = (UInt64)offset; 946*f6dc9357SAndroid Build Coastguard Worker if (newPosition) 947*f6dc9357SAndroid Build Coastguard Worker *newPosition = (UInt64)offset; 948*f6dc9357SAndroid Build Coastguard Worker return S_OK; 949*f6dc9357SAndroid Build Coastguard Worker } 950*f6dc9357SAndroid Build Coastguard Worker 951*f6dc9357SAndroid Build Coastguard Worker 952*f6dc9357SAndroid Build Coastguard Worker 953*f6dc9357SAndroid Build Coastguard Worker static const UInt64 kMaxBlockSize_for_GetStream = (UInt64)1 << 40; 954*f6dc9357SAndroid Build Coastguard Worker 955*f6dc9357SAndroid Build Coastguard Worker Z7_COM7F_IMF(CHandler::GetStream(UInt32 index, ISequentialInStream **stream)) 956*f6dc9357SAndroid Build Coastguard Worker { 957*f6dc9357SAndroid Build Coastguard Worker COM_TRY_BEGIN 958*f6dc9357SAndroid Build Coastguard Worker 959*f6dc9357SAndroid Build Coastguard Worker *stream = NULL; 960*f6dc9357SAndroid Build Coastguard Worker 961*f6dc9357SAndroid Build Coastguard Worker if (index != 0) 962*f6dc9357SAndroid Build Coastguard Worker return E_INVALIDARG; 963*f6dc9357SAndroid Build Coastguard Worker 964*f6dc9357SAndroid Build Coastguard Worker if (!_stat.UnpackSize_Defined 965*f6dc9357SAndroid Build Coastguard Worker || _maxBlocksSize == 0 // 18.02 966*f6dc9357SAndroid Build Coastguard Worker || _maxBlocksSize > kMaxBlockSize_for_GetStream 967*f6dc9357SAndroid Build Coastguard Worker || _maxBlocksSize != (size_t)_maxBlocksSize) 968*f6dc9357SAndroid Build Coastguard Worker return S_FALSE; 969*f6dc9357SAndroid Build Coastguard Worker 970*f6dc9357SAndroid Build Coastguard Worker size_t memSize; 971*f6dc9357SAndroid Build Coastguard Worker if (!NSystem::GetRamSize(memSize)) 972*f6dc9357SAndroid Build Coastguard Worker memSize = (size_t)sizeof(size_t) << 28; 973*f6dc9357SAndroid Build Coastguard Worker { 974*f6dc9357SAndroid Build Coastguard Worker if (_maxBlocksSize > memSize / 4) 975*f6dc9357SAndroid Build Coastguard Worker return S_FALSE; 976*f6dc9357SAndroid Build Coastguard Worker } 977*f6dc9357SAndroid Build Coastguard Worker 978*f6dc9357SAndroid Build Coastguard Worker CMyComPtr2<ISequentialInStream, CInStream> spec; 979*f6dc9357SAndroid Build Coastguard Worker spec.Create_if_Empty(); 980*f6dc9357SAndroid Build Coastguard Worker spec->_cache.Alloc((size_t)_maxBlocksSize); 981*f6dc9357SAndroid Build Coastguard Worker spec->_handlerSpec.SetFromCls(this); 982*f6dc9357SAndroid Build Coastguard Worker // spec->_handler = (IInArchive *)this; 983*f6dc9357SAndroid Build Coastguard Worker spec->Size = _stat.OutSize; 984*f6dc9357SAndroid Build Coastguard Worker spec->InitAndSeek(); 985*f6dc9357SAndroid Build Coastguard Worker 986*f6dc9357SAndroid Build Coastguard Worker *stream = spec.Detach(); 987*f6dc9357SAndroid Build Coastguard Worker return S_OK; 988*f6dc9357SAndroid Build Coastguard Worker 989*f6dc9357SAndroid Build Coastguard Worker COM_TRY_END 990*f6dc9357SAndroid Build Coastguard Worker } 991*f6dc9357SAndroid Build Coastguard Worker 992*f6dc9357SAndroid Build Coastguard Worker 993*f6dc9357SAndroid Build Coastguard Worker static Int32 Get_Extract_OperationResult(const NCompress::NXz::CDecoder &decoder) 994*f6dc9357SAndroid Build Coastguard Worker { 995*f6dc9357SAndroid Build Coastguard Worker Int32 opRes; 996*f6dc9357SAndroid Build Coastguard Worker SRes sres = decoder.MainDecodeSRes; 997*f6dc9357SAndroid Build Coastguard Worker if (sres == SZ_ERROR_NO_ARCHIVE) // (!IsArc) 998*f6dc9357SAndroid Build Coastguard Worker opRes = NExtract::NOperationResult::kIsNotArc; 999*f6dc9357SAndroid Build Coastguard Worker else if (sres == SZ_ERROR_INPUT_EOF) // (UnexpectedEnd) 1000*f6dc9357SAndroid Build Coastguard Worker opRes = NExtract::NOperationResult::kUnexpectedEnd; 1001*f6dc9357SAndroid Build Coastguard Worker else if (decoder.Stat.DataAfterEnd) 1002*f6dc9357SAndroid Build Coastguard Worker opRes = NExtract::NOperationResult::kDataAfterEnd; 1003*f6dc9357SAndroid Build Coastguard Worker else if (sres == SZ_ERROR_CRC) // (CrcError) 1004*f6dc9357SAndroid Build Coastguard Worker opRes = NExtract::NOperationResult::kCRCError; 1005*f6dc9357SAndroid Build Coastguard Worker else if (sres == SZ_ERROR_UNSUPPORTED) // (Unsupported) 1006*f6dc9357SAndroid Build Coastguard Worker opRes = NExtract::NOperationResult::kUnsupportedMethod; 1007*f6dc9357SAndroid Build Coastguard Worker else if (sres == SZ_ERROR_ARCHIVE) // (HeadersError) 1008*f6dc9357SAndroid Build Coastguard Worker opRes = NExtract::NOperationResult::kDataError; 1009*f6dc9357SAndroid Build Coastguard Worker else if (sres == SZ_ERROR_DATA) // (DataError) 1010*f6dc9357SAndroid Build Coastguard Worker opRes = NExtract::NOperationResult::kDataError; 1011*f6dc9357SAndroid Build Coastguard Worker else if (sres != SZ_OK) 1012*f6dc9357SAndroid Build Coastguard Worker opRes = NExtract::NOperationResult::kDataError; 1013*f6dc9357SAndroid Build Coastguard Worker else 1014*f6dc9357SAndroid Build Coastguard Worker opRes = NExtract::NOperationResult::kOK; 1015*f6dc9357SAndroid Build Coastguard Worker return opRes; 1016*f6dc9357SAndroid Build Coastguard Worker } 1017*f6dc9357SAndroid Build Coastguard Worker 1018*f6dc9357SAndroid Build Coastguard Worker 1019*f6dc9357SAndroid Build Coastguard Worker 1020*f6dc9357SAndroid Build Coastguard Worker 1021*f6dc9357SAndroid Build Coastguard Worker Z7_COM7F_IMF(CHandler::Extract(const UInt32 *indices, UInt32 numItems, 1022*f6dc9357SAndroid Build Coastguard Worker Int32 testMode, IArchiveExtractCallback *extractCallback)) 1023*f6dc9357SAndroid Build Coastguard Worker { 1024*f6dc9357SAndroid Build Coastguard Worker COM_TRY_BEGIN 1025*f6dc9357SAndroid Build Coastguard Worker if (numItems == 0) 1026*f6dc9357SAndroid Build Coastguard Worker return S_OK; 1027*f6dc9357SAndroid Build Coastguard Worker if (numItems != (UInt32)(Int32)-1 && (numItems != 1 || indices[0] != 0)) 1028*f6dc9357SAndroid Build Coastguard Worker return E_INVALIDARG; 1029*f6dc9357SAndroid Build Coastguard Worker 1030*f6dc9357SAndroid Build Coastguard Worker const CXzStatInfo *stat = GetStat(); 1031*f6dc9357SAndroid Build Coastguard Worker 1032*f6dc9357SAndroid Build Coastguard Worker if (stat) 1033*f6dc9357SAndroid Build Coastguard Worker RINOK(extractCallback->SetTotal(stat->InSize)) 1034*f6dc9357SAndroid Build Coastguard Worker 1035*f6dc9357SAndroid Build Coastguard Worker UInt64 currentTotalPacked = 0; 1036*f6dc9357SAndroid Build Coastguard Worker RINOK(extractCallback->SetCompleted(¤tTotalPacked)) 1037*f6dc9357SAndroid Build Coastguard Worker Int32 opRes; 1038*f6dc9357SAndroid Build Coastguard Worker { 1039*f6dc9357SAndroid Build Coastguard Worker CMyComPtr<ISequentialOutStream> realOutStream; 1040*f6dc9357SAndroid Build Coastguard Worker const Int32 askMode = testMode ? 1041*f6dc9357SAndroid Build Coastguard Worker NExtract::NAskMode::kTest : 1042*f6dc9357SAndroid Build Coastguard Worker NExtract::NAskMode::kExtract; 1043*f6dc9357SAndroid Build Coastguard Worker 1044*f6dc9357SAndroid Build Coastguard Worker RINOK(extractCallback->GetStream(0, &realOutStream, askMode)) 1045*f6dc9357SAndroid Build Coastguard Worker 1046*f6dc9357SAndroid Build Coastguard Worker if (!testMode && !realOutStream) 1047*f6dc9357SAndroid Build Coastguard Worker return S_OK; 1048*f6dc9357SAndroid Build Coastguard Worker 1049*f6dc9357SAndroid Build Coastguard Worker RINOK(extractCallback->PrepareOperation(askMode)) 1050*f6dc9357SAndroid Build Coastguard Worker 1051*f6dc9357SAndroid Build Coastguard Worker CMyComPtr2_Create<ICompressProgressInfo, CLocalProgress> lps; 1052*f6dc9357SAndroid Build Coastguard Worker lps->Init(extractCallback, true); 1053*f6dc9357SAndroid Build Coastguard Worker 1054*f6dc9357SAndroid Build Coastguard Worker if (_needSeekToStart) 1055*f6dc9357SAndroid Build Coastguard Worker { 1056*f6dc9357SAndroid Build Coastguard Worker if (!_stream) 1057*f6dc9357SAndroid Build Coastguard Worker return E_FAIL; 1058*f6dc9357SAndroid Build Coastguard Worker RINOK(InStream_SeekToBegin(_stream)) 1059*f6dc9357SAndroid Build Coastguard Worker } 1060*f6dc9357SAndroid Build Coastguard Worker else 1061*f6dc9357SAndroid Build Coastguard Worker _needSeekToStart = true; 1062*f6dc9357SAndroid Build Coastguard Worker 1063*f6dc9357SAndroid Build Coastguard Worker 1064*f6dc9357SAndroid Build Coastguard Worker NCompress::NXz::CDecoder decoder; 1065*f6dc9357SAndroid Build Coastguard Worker 1066*f6dc9357SAndroid Build Coastguard Worker const HRESULT hres = Decode(decoder, _seqStream, realOutStream, lps); 1067*f6dc9357SAndroid Build Coastguard Worker 1068*f6dc9357SAndroid Build Coastguard Worker if (!decoder.MainDecodeSRes_wasUsed) 1069*f6dc9357SAndroid Build Coastguard Worker return hres == S_OK ? E_FAIL : hres; 1070*f6dc9357SAndroid Build Coastguard Worker 1071*f6dc9357SAndroid Build Coastguard Worker opRes = Get_Extract_OperationResult(decoder); 1072*f6dc9357SAndroid Build Coastguard Worker if (opRes == NExtract::NOperationResult::kOK 1073*f6dc9357SAndroid Build Coastguard Worker && hres != S_OK) 1074*f6dc9357SAndroid Build Coastguard Worker opRes = NExtract::NOperationResult::kDataError; 1075*f6dc9357SAndroid Build Coastguard Worker 1076*f6dc9357SAndroid Build Coastguard Worker // realOutStream.Release(); 1077*f6dc9357SAndroid Build Coastguard Worker } 1078*f6dc9357SAndroid Build Coastguard Worker return extractCallback->SetOperationResult(opRes); 1079*f6dc9357SAndroid Build Coastguard Worker COM_TRY_END 1080*f6dc9357SAndroid Build Coastguard Worker } 1081*f6dc9357SAndroid Build Coastguard Worker 1082*f6dc9357SAndroid Build Coastguard Worker 1083*f6dc9357SAndroid Build Coastguard Worker 1084*f6dc9357SAndroid Build Coastguard Worker #ifndef Z7_EXTRACT_ONLY 1085*f6dc9357SAndroid Build Coastguard Worker 1086*f6dc9357SAndroid Build Coastguard Worker Z7_COM7F_IMF(CHandler::GetFileTimeType(UInt32 *timeType)) 1087*f6dc9357SAndroid Build Coastguard Worker { 1088*f6dc9357SAndroid Build Coastguard Worker *timeType = GET_FileTimeType_NotDefined_for_GetFileTimeType; 1089*f6dc9357SAndroid Build Coastguard Worker // *timeType = NFileTimeType::kUnix; 1090*f6dc9357SAndroid Build Coastguard Worker return S_OK; 1091*f6dc9357SAndroid Build Coastguard Worker } 1092*f6dc9357SAndroid Build Coastguard Worker 1093*f6dc9357SAndroid Build Coastguard Worker 1094*f6dc9357SAndroid Build Coastguard Worker Z7_COM7F_IMF(CHandler::UpdateItems(ISequentialOutStream *outStream, UInt32 numItems, 1095*f6dc9357SAndroid Build Coastguard Worker IArchiveUpdateCallback *updateCallback)) 1096*f6dc9357SAndroid Build Coastguard Worker { 1097*f6dc9357SAndroid Build Coastguard Worker COM_TRY_BEGIN 1098*f6dc9357SAndroid Build Coastguard Worker 1099*f6dc9357SAndroid Build Coastguard Worker if (numItems == 0) 1100*f6dc9357SAndroid Build Coastguard Worker { 1101*f6dc9357SAndroid Build Coastguard Worker CSeqOutStreamWrap seqOutStream; 1102*f6dc9357SAndroid Build Coastguard Worker seqOutStream.Init(outStream); 1103*f6dc9357SAndroid Build Coastguard Worker SRes res = Xz_EncodeEmpty(&seqOutStream.vt); 1104*f6dc9357SAndroid Build Coastguard Worker return SResToHRESULT(res); 1105*f6dc9357SAndroid Build Coastguard Worker } 1106*f6dc9357SAndroid Build Coastguard Worker 1107*f6dc9357SAndroid Build Coastguard Worker if (numItems != 1) 1108*f6dc9357SAndroid Build Coastguard Worker return E_INVALIDARG; 1109*f6dc9357SAndroid Build Coastguard Worker 1110*f6dc9357SAndroid Build Coastguard Worker { 1111*f6dc9357SAndroid Build Coastguard Worker Z7_DECL_CMyComPtr_QI_FROM( 1112*f6dc9357SAndroid Build Coastguard Worker IStreamSetRestriction, 1113*f6dc9357SAndroid Build Coastguard Worker setRestriction, outStream) 1114*f6dc9357SAndroid Build Coastguard Worker if (setRestriction) 1115*f6dc9357SAndroid Build Coastguard Worker RINOK(setRestriction->SetRestriction(0, 0)) 1116*f6dc9357SAndroid Build Coastguard Worker } 1117*f6dc9357SAndroid Build Coastguard Worker 1118*f6dc9357SAndroid Build Coastguard Worker Int32 newData, newProps; 1119*f6dc9357SAndroid Build Coastguard Worker UInt32 indexInArchive; 1120*f6dc9357SAndroid Build Coastguard Worker if (!updateCallback) 1121*f6dc9357SAndroid Build Coastguard Worker return E_FAIL; 1122*f6dc9357SAndroid Build Coastguard Worker RINOK(updateCallback->GetUpdateItemInfo(0, &newData, &newProps, &indexInArchive)) 1123*f6dc9357SAndroid Build Coastguard Worker 1124*f6dc9357SAndroid Build Coastguard Worker if (IntToBool(newProps)) 1125*f6dc9357SAndroid Build Coastguard Worker { 1126*f6dc9357SAndroid Build Coastguard Worker { 1127*f6dc9357SAndroid Build Coastguard Worker NCOM::CPropVariant prop; 1128*f6dc9357SAndroid Build Coastguard Worker RINOK(updateCallback->GetProperty(0, kpidIsDir, &prop)) 1129*f6dc9357SAndroid Build Coastguard Worker if (prop.vt != VT_EMPTY) 1130*f6dc9357SAndroid Build Coastguard Worker if (prop.vt != VT_BOOL || prop.boolVal != VARIANT_FALSE) 1131*f6dc9357SAndroid Build Coastguard Worker return E_INVALIDARG; 1132*f6dc9357SAndroid Build Coastguard Worker } 1133*f6dc9357SAndroid Build Coastguard Worker } 1134*f6dc9357SAndroid Build Coastguard Worker 1135*f6dc9357SAndroid Build Coastguard Worker if (IntToBool(newData)) 1136*f6dc9357SAndroid Build Coastguard Worker { 1137*f6dc9357SAndroid Build Coastguard Worker UInt64 dataSize; 1138*f6dc9357SAndroid Build Coastguard Worker { 1139*f6dc9357SAndroid Build Coastguard Worker NCOM::CPropVariant prop; 1140*f6dc9357SAndroid Build Coastguard Worker RINOK(updateCallback->GetProperty(0, kpidSize, &prop)) 1141*f6dc9357SAndroid Build Coastguard Worker if (prop.vt != VT_UI8) 1142*f6dc9357SAndroid Build Coastguard Worker return E_INVALIDARG; 1143*f6dc9357SAndroid Build Coastguard Worker dataSize = prop.uhVal.QuadPart; 1144*f6dc9357SAndroid Build Coastguard Worker } 1145*f6dc9357SAndroid Build Coastguard Worker 1146*f6dc9357SAndroid Build Coastguard Worker CMyComPtr2_Create<ICompressCoder, NCompress::NXz::CEncoder> encoder; 1147*f6dc9357SAndroid Build Coastguard Worker 1148*f6dc9357SAndroid Build Coastguard Worker CXzProps &xzProps = encoder->xzProps; 1149*f6dc9357SAndroid Build Coastguard Worker CLzma2EncProps &lzma2Props = xzProps.lzma2Props; 1150*f6dc9357SAndroid Build Coastguard Worker 1151*f6dc9357SAndroid Build Coastguard Worker lzma2Props.lzmaProps.level = GetLevel(); 1152*f6dc9357SAndroid Build Coastguard Worker 1153*f6dc9357SAndroid Build Coastguard Worker xzProps.reduceSize = dataSize; 1154*f6dc9357SAndroid Build Coastguard Worker /* 1155*f6dc9357SAndroid Build Coastguard Worker { 1156*f6dc9357SAndroid Build Coastguard Worker NCOM::CPropVariant prop = (UInt64)dataSize; 1157*f6dc9357SAndroid Build Coastguard Worker RINOK(encoder->SetCoderProp(NCoderPropID::kReduceSize, prop)) 1158*f6dc9357SAndroid Build Coastguard Worker } 1159*f6dc9357SAndroid Build Coastguard Worker */ 1160*f6dc9357SAndroid Build Coastguard Worker 1161*f6dc9357SAndroid Build Coastguard Worker #ifndef Z7_ST 1162*f6dc9357SAndroid Build Coastguard Worker 1163*f6dc9357SAndroid Build Coastguard Worker UInt32 numThreads = _numThreads; 1164*f6dc9357SAndroid Build Coastguard Worker 1165*f6dc9357SAndroid Build Coastguard Worker const UInt32 kNumThreads_Max = 1024; 1166*f6dc9357SAndroid Build Coastguard Worker if (numThreads > kNumThreads_Max) 1167*f6dc9357SAndroid Build Coastguard Worker numThreads = kNumThreads_Max; 1168*f6dc9357SAndroid Build Coastguard Worker 1169*f6dc9357SAndroid Build Coastguard Worker if (!_numThreads_WasForced 1170*f6dc9357SAndroid Build Coastguard Worker && _numThreads >= 1 1171*f6dc9357SAndroid Build Coastguard Worker && _memUsage_WasSet) 1172*f6dc9357SAndroid Build Coastguard Worker { 1173*f6dc9357SAndroid Build Coastguard Worker COneMethodInfo oneMethodInfo; 1174*f6dc9357SAndroid Build Coastguard Worker if (!_methods.IsEmpty()) 1175*f6dc9357SAndroid Build Coastguard Worker oneMethodInfo = _methods[0]; 1176*f6dc9357SAndroid Build Coastguard Worker 1177*f6dc9357SAndroid Build Coastguard Worker SetGlobalLevelTo(oneMethodInfo); 1178*f6dc9357SAndroid Build Coastguard Worker 1179*f6dc9357SAndroid Build Coastguard Worker const bool numThreads_WasSpecifiedInMethod = (oneMethodInfo.Get_NumThreads() >= 0); 1180*f6dc9357SAndroid Build Coastguard Worker if (!numThreads_WasSpecifiedInMethod) 1181*f6dc9357SAndroid Build Coastguard Worker { 1182*f6dc9357SAndroid Build Coastguard Worker // here we set the (NCoderPropID::kNumThreads) property in each method, only if there is no such property already 1183*f6dc9357SAndroid Build Coastguard Worker CMultiMethodProps::SetMethodThreadsTo_IfNotFinded(oneMethodInfo, numThreads); 1184*f6dc9357SAndroid Build Coastguard Worker } 1185*f6dc9357SAndroid Build Coastguard Worker 1186*f6dc9357SAndroid Build Coastguard Worker UInt64 cs = _numSolidBytes; 1187*f6dc9357SAndroid Build Coastguard Worker if (cs != XZ_PROPS_BLOCK_SIZE_AUTO) 1188*f6dc9357SAndroid Build Coastguard Worker oneMethodInfo.AddProp_BlockSize2(cs); 1189*f6dc9357SAndroid Build Coastguard Worker cs = oneMethodInfo.Get_Xz_BlockSize(); 1190*f6dc9357SAndroid Build Coastguard Worker 1191*f6dc9357SAndroid Build Coastguard Worker if (cs != XZ_PROPS_BLOCK_SIZE_AUTO && 1192*f6dc9357SAndroid Build Coastguard Worker cs != XZ_PROPS_BLOCK_SIZE_SOLID) 1193*f6dc9357SAndroid Build Coastguard Worker { 1194*f6dc9357SAndroid Build Coastguard Worker const UInt32 lzmaThreads = oneMethodInfo.Get_Lzma_NumThreads(); 1195*f6dc9357SAndroid Build Coastguard Worker const UInt32 numBlockThreads_Original = numThreads / lzmaThreads; 1196*f6dc9357SAndroid Build Coastguard Worker 1197*f6dc9357SAndroid Build Coastguard Worker if (numBlockThreads_Original > 1) 1198*f6dc9357SAndroid Build Coastguard Worker { 1199*f6dc9357SAndroid Build Coastguard Worker UInt32 numBlockThreads = numBlockThreads_Original; 1200*f6dc9357SAndroid Build Coastguard Worker { 1201*f6dc9357SAndroid Build Coastguard Worker const UInt64 lzmaMemUsage = oneMethodInfo.Get_Lzma_MemUsage(false); 1202*f6dc9357SAndroid Build Coastguard Worker for (; numBlockThreads > 1; numBlockThreads--) 1203*f6dc9357SAndroid Build Coastguard Worker { 1204*f6dc9357SAndroid Build Coastguard Worker UInt64 size = numBlockThreads * (lzmaMemUsage + cs); 1205*f6dc9357SAndroid Build Coastguard Worker UInt32 numPackChunks = numBlockThreads + (numBlockThreads / 8) + 1; 1206*f6dc9357SAndroid Build Coastguard Worker if (cs < ((UInt32)1 << 26)) numPackChunks++; 1207*f6dc9357SAndroid Build Coastguard Worker if (cs < ((UInt32)1 << 24)) numPackChunks++; 1208*f6dc9357SAndroid Build Coastguard Worker if (cs < ((UInt32)1 << 22)) numPackChunks++; 1209*f6dc9357SAndroid Build Coastguard Worker size += numPackChunks * cs; 1210*f6dc9357SAndroid Build Coastguard Worker // printf("\nnumBlockThreads = %d, size = %d\n", (unsigned)(numBlockThreads), (unsigned)(size >> 20)); 1211*f6dc9357SAndroid Build Coastguard Worker if (size <= _memUsage_Compress) 1212*f6dc9357SAndroid Build Coastguard Worker break; 1213*f6dc9357SAndroid Build Coastguard Worker } 1214*f6dc9357SAndroid Build Coastguard Worker } 1215*f6dc9357SAndroid Build Coastguard Worker if (numBlockThreads == 0) 1216*f6dc9357SAndroid Build Coastguard Worker numBlockThreads = 1; 1217*f6dc9357SAndroid Build Coastguard Worker if (numBlockThreads != numBlockThreads_Original) 1218*f6dc9357SAndroid Build Coastguard Worker numThreads = numBlockThreads * lzmaThreads; 1219*f6dc9357SAndroid Build Coastguard Worker } 1220*f6dc9357SAndroid Build Coastguard Worker } 1221*f6dc9357SAndroid Build Coastguard Worker } 1222*f6dc9357SAndroid Build Coastguard Worker xzProps.numTotalThreads = (int)numThreads; 1223*f6dc9357SAndroid Build Coastguard Worker 1224*f6dc9357SAndroid Build Coastguard Worker #endif // Z7_ST 1225*f6dc9357SAndroid Build Coastguard Worker 1226*f6dc9357SAndroid Build Coastguard Worker 1227*f6dc9357SAndroid Build Coastguard Worker xzProps.blockSize = _numSolidBytes; 1228*f6dc9357SAndroid Build Coastguard Worker if (_numSolidBytes == XZ_PROPS_BLOCK_SIZE_SOLID) 1229*f6dc9357SAndroid Build Coastguard Worker { 1230*f6dc9357SAndroid Build Coastguard Worker xzProps.lzma2Props.blockSize = LZMA2_ENC_PROPS_BLOCK_SIZE_SOLID; 1231*f6dc9357SAndroid Build Coastguard Worker } 1232*f6dc9357SAndroid Build Coastguard Worker 1233*f6dc9357SAndroid Build Coastguard Worker RINOK(encoder->SetCheckSize(_crcSize)) 1234*f6dc9357SAndroid Build Coastguard Worker 1235*f6dc9357SAndroid Build Coastguard Worker { 1236*f6dc9357SAndroid Build Coastguard Worker CXzFilterProps &filter = xzProps.filterProps; 1237*f6dc9357SAndroid Build Coastguard Worker 1238*f6dc9357SAndroid Build Coastguard Worker if (_filterId == XZ_ID_Delta) 1239*f6dc9357SAndroid Build Coastguard Worker { 1240*f6dc9357SAndroid Build Coastguard Worker bool deltaDefined = false; 1241*f6dc9357SAndroid Build Coastguard Worker FOR_VECTOR (j, _filterMethod.Props) 1242*f6dc9357SAndroid Build Coastguard Worker { 1243*f6dc9357SAndroid Build Coastguard Worker const CProp &prop = _filterMethod.Props[j]; 1244*f6dc9357SAndroid Build Coastguard Worker if (prop.Id == NCoderPropID::kDefaultProp && prop.Value.vt == VT_UI4) 1245*f6dc9357SAndroid Build Coastguard Worker { 1246*f6dc9357SAndroid Build Coastguard Worker UInt32 delta = (UInt32)prop.Value.ulVal; 1247*f6dc9357SAndroid Build Coastguard Worker if (delta < 1 || delta > 256) 1248*f6dc9357SAndroid Build Coastguard Worker return E_INVALIDARG; 1249*f6dc9357SAndroid Build Coastguard Worker filter.delta = delta; 1250*f6dc9357SAndroid Build Coastguard Worker deltaDefined = true; 1251*f6dc9357SAndroid Build Coastguard Worker } 1252*f6dc9357SAndroid Build Coastguard Worker else 1253*f6dc9357SAndroid Build Coastguard Worker return E_INVALIDARG; 1254*f6dc9357SAndroid Build Coastguard Worker } 1255*f6dc9357SAndroid Build Coastguard Worker if (!deltaDefined) 1256*f6dc9357SAndroid Build Coastguard Worker return E_INVALIDARG; 1257*f6dc9357SAndroid Build Coastguard Worker } 1258*f6dc9357SAndroid Build Coastguard Worker filter.id = _filterId; 1259*f6dc9357SAndroid Build Coastguard Worker } 1260*f6dc9357SAndroid Build Coastguard Worker 1261*f6dc9357SAndroid Build Coastguard Worker FOR_VECTOR (i, _methods) 1262*f6dc9357SAndroid Build Coastguard Worker { 1263*f6dc9357SAndroid Build Coastguard Worker COneMethodInfo &m = _methods[i]; 1264*f6dc9357SAndroid Build Coastguard Worker 1265*f6dc9357SAndroid Build Coastguard Worker FOR_VECTOR (j, m.Props) 1266*f6dc9357SAndroid Build Coastguard Worker { 1267*f6dc9357SAndroid Build Coastguard Worker const CProp &prop = m.Props[j]; 1268*f6dc9357SAndroid Build Coastguard Worker RINOK(encoder->SetCoderProp(prop.Id, prop.Value)) 1269*f6dc9357SAndroid Build Coastguard Worker } 1270*f6dc9357SAndroid Build Coastguard Worker } 1271*f6dc9357SAndroid Build Coastguard Worker 1272*f6dc9357SAndroid Build Coastguard Worker { 1273*f6dc9357SAndroid Build Coastguard Worker CMyComPtr<ISequentialInStream> fileInStream; 1274*f6dc9357SAndroid Build Coastguard Worker RINOK(updateCallback->GetStream(0, &fileInStream)) 1275*f6dc9357SAndroid Build Coastguard Worker if (!fileInStream) 1276*f6dc9357SAndroid Build Coastguard Worker return S_FALSE; 1277*f6dc9357SAndroid Build Coastguard Worker { 1278*f6dc9357SAndroid Build Coastguard Worker CMyComPtr<IStreamGetSize> streamGetSize; 1279*f6dc9357SAndroid Build Coastguard Worker fileInStream.QueryInterface(IID_IStreamGetSize, &streamGetSize); 1280*f6dc9357SAndroid Build Coastguard Worker if (streamGetSize) 1281*f6dc9357SAndroid Build Coastguard Worker { 1282*f6dc9357SAndroid Build Coastguard Worker UInt64 size; 1283*f6dc9357SAndroid Build Coastguard Worker if (streamGetSize->GetSize(&size) == S_OK) 1284*f6dc9357SAndroid Build Coastguard Worker dataSize = size; 1285*f6dc9357SAndroid Build Coastguard Worker } 1286*f6dc9357SAndroid Build Coastguard Worker } 1287*f6dc9357SAndroid Build Coastguard Worker RINOK(updateCallback->SetTotal(dataSize)) 1288*f6dc9357SAndroid Build Coastguard Worker CMyComPtr2_Create<ICompressProgressInfo, CLocalProgress> lps; 1289*f6dc9357SAndroid Build Coastguard Worker lps->Init(updateCallback, true); 1290*f6dc9357SAndroid Build Coastguard Worker RINOK(encoder.Interface()->Code(fileInStream, outStream, NULL, NULL, lps)) 1291*f6dc9357SAndroid Build Coastguard Worker } 1292*f6dc9357SAndroid Build Coastguard Worker 1293*f6dc9357SAndroid Build Coastguard Worker return updateCallback->SetOperationResult(NArchive::NUpdate::NOperationResult::kOK); 1294*f6dc9357SAndroid Build Coastguard Worker } 1295*f6dc9357SAndroid Build Coastguard Worker 1296*f6dc9357SAndroid Build Coastguard Worker if (indexInArchive != 0) 1297*f6dc9357SAndroid Build Coastguard Worker return E_INVALIDARG; 1298*f6dc9357SAndroid Build Coastguard Worker 1299*f6dc9357SAndroid Build Coastguard Worker Z7_DECL_CMyComPtr_QI_FROM( 1300*f6dc9357SAndroid Build Coastguard Worker IArchiveUpdateCallbackFile, 1301*f6dc9357SAndroid Build Coastguard Worker opCallback, updateCallback) 1302*f6dc9357SAndroid Build Coastguard Worker if (opCallback) 1303*f6dc9357SAndroid Build Coastguard Worker { 1304*f6dc9357SAndroid Build Coastguard Worker RINOK(opCallback->ReportOperation(NEventIndexType::kInArcIndex, 0, NUpdateNotifyOp::kReplicate)) 1305*f6dc9357SAndroid Build Coastguard Worker } 1306*f6dc9357SAndroid Build Coastguard Worker 1307*f6dc9357SAndroid Build Coastguard Worker if (_stream) 1308*f6dc9357SAndroid Build Coastguard Worker { 1309*f6dc9357SAndroid Build Coastguard Worker const CXzStatInfo *stat = GetStat(); 1310*f6dc9357SAndroid Build Coastguard Worker if (stat) 1311*f6dc9357SAndroid Build Coastguard Worker { 1312*f6dc9357SAndroid Build Coastguard Worker RINOK(updateCallback->SetTotal(stat->InSize)) 1313*f6dc9357SAndroid Build Coastguard Worker } 1314*f6dc9357SAndroid Build Coastguard Worker RINOK(InStream_SeekToBegin(_stream)) 1315*f6dc9357SAndroid Build Coastguard Worker } 1316*f6dc9357SAndroid Build Coastguard Worker 1317*f6dc9357SAndroid Build Coastguard Worker CMyComPtr2_Create<ICompressProgressInfo, CLocalProgress> lps; 1318*f6dc9357SAndroid Build Coastguard Worker lps->Init(updateCallback, true); 1319*f6dc9357SAndroid Build Coastguard Worker 1320*f6dc9357SAndroid Build Coastguard Worker return NCompress::CopyStream(_stream, outStream, lps); 1321*f6dc9357SAndroid Build Coastguard Worker 1322*f6dc9357SAndroid Build Coastguard Worker COM_TRY_END 1323*f6dc9357SAndroid Build Coastguard Worker } 1324*f6dc9357SAndroid Build Coastguard Worker 1325*f6dc9357SAndroid Build Coastguard Worker #endif 1326*f6dc9357SAndroid Build Coastguard Worker 1327*f6dc9357SAndroid Build Coastguard Worker 1328*f6dc9357SAndroid Build Coastguard Worker HRESULT CHandler::SetProperty(const wchar_t *nameSpec, const PROPVARIANT &value) 1329*f6dc9357SAndroid Build Coastguard Worker { 1330*f6dc9357SAndroid Build Coastguard Worker UString name = nameSpec; 1331*f6dc9357SAndroid Build Coastguard Worker name.MakeLower_Ascii(); 1332*f6dc9357SAndroid Build Coastguard Worker if (name.IsEmpty()) 1333*f6dc9357SAndroid Build Coastguard Worker return E_INVALIDARG; 1334*f6dc9357SAndroid Build Coastguard Worker 1335*f6dc9357SAndroid Build Coastguard Worker #ifndef Z7_EXTRACT_ONLY 1336*f6dc9357SAndroid Build Coastguard Worker 1337*f6dc9357SAndroid Build Coastguard Worker if (name[0] == L's') 1338*f6dc9357SAndroid Build Coastguard Worker { 1339*f6dc9357SAndroid Build Coastguard Worker const wchar_t *s = name.Ptr(1); 1340*f6dc9357SAndroid Build Coastguard Worker if (*s == 0) 1341*f6dc9357SAndroid Build Coastguard Worker { 1342*f6dc9357SAndroid Build Coastguard Worker bool useStr = false; 1343*f6dc9357SAndroid Build Coastguard Worker bool isSolid; 1344*f6dc9357SAndroid Build Coastguard Worker switch (value.vt) 1345*f6dc9357SAndroid Build Coastguard Worker { 1346*f6dc9357SAndroid Build Coastguard Worker case VT_EMPTY: isSolid = true; break; 1347*f6dc9357SAndroid Build Coastguard Worker case VT_BOOL: isSolid = (value.boolVal != VARIANT_FALSE); break; 1348*f6dc9357SAndroid Build Coastguard Worker case VT_BSTR: 1349*f6dc9357SAndroid Build Coastguard Worker if (!StringToBool(value.bstrVal, isSolid)) 1350*f6dc9357SAndroid Build Coastguard Worker useStr = true; 1351*f6dc9357SAndroid Build Coastguard Worker break; 1352*f6dc9357SAndroid Build Coastguard Worker default: return E_INVALIDARG; 1353*f6dc9357SAndroid Build Coastguard Worker } 1354*f6dc9357SAndroid Build Coastguard Worker if (!useStr) 1355*f6dc9357SAndroid Build Coastguard Worker { 1356*f6dc9357SAndroid Build Coastguard Worker _numSolidBytes = (isSolid ? XZ_PROPS_BLOCK_SIZE_SOLID : XZ_PROPS_BLOCK_SIZE_AUTO); 1357*f6dc9357SAndroid Build Coastguard Worker return S_OK; 1358*f6dc9357SAndroid Build Coastguard Worker } 1359*f6dc9357SAndroid Build Coastguard Worker } 1360*f6dc9357SAndroid Build Coastguard Worker return ParseSizeString(s, value, 1361*f6dc9357SAndroid Build Coastguard Worker 0, // percentsBase 1362*f6dc9357SAndroid Build Coastguard Worker _numSolidBytes) ? S_OK: E_INVALIDARG; 1363*f6dc9357SAndroid Build Coastguard Worker } 1364*f6dc9357SAndroid Build Coastguard Worker 1365*f6dc9357SAndroid Build Coastguard Worker return CMultiMethodProps::SetProperty(name, value); 1366*f6dc9357SAndroid Build Coastguard Worker 1367*f6dc9357SAndroid Build Coastguard Worker #else 1368*f6dc9357SAndroid Build Coastguard Worker 1369*f6dc9357SAndroid Build Coastguard Worker { 1370*f6dc9357SAndroid Build Coastguard Worker HRESULT hres; 1371*f6dc9357SAndroid Build Coastguard Worker if (SetCommonProperty(name, value, hres)) 1372*f6dc9357SAndroid Build Coastguard Worker return hres; 1373*f6dc9357SAndroid Build Coastguard Worker } 1374*f6dc9357SAndroid Build Coastguard Worker 1375*f6dc9357SAndroid Build Coastguard Worker return E_INVALIDARG; 1376*f6dc9357SAndroid Build Coastguard Worker 1377*f6dc9357SAndroid Build Coastguard Worker #endif 1378*f6dc9357SAndroid Build Coastguard Worker } 1379*f6dc9357SAndroid Build Coastguard Worker 1380*f6dc9357SAndroid Build Coastguard Worker 1381*f6dc9357SAndroid Build Coastguard Worker 1382*f6dc9357SAndroid Build Coastguard Worker Z7_COM7F_IMF(CHandler::SetProperties(const wchar_t * const *names, const PROPVARIANT *values, UInt32 numProps)) 1383*f6dc9357SAndroid Build Coastguard Worker { 1384*f6dc9357SAndroid Build Coastguard Worker COM_TRY_BEGIN 1385*f6dc9357SAndroid Build Coastguard Worker 1386*f6dc9357SAndroid Build Coastguard Worker Init(); 1387*f6dc9357SAndroid Build Coastguard Worker 1388*f6dc9357SAndroid Build Coastguard Worker for (UInt32 i = 0; i < numProps; i++) 1389*f6dc9357SAndroid Build Coastguard Worker { 1390*f6dc9357SAndroid Build Coastguard Worker RINOK(SetProperty(names[i], values[i])) 1391*f6dc9357SAndroid Build Coastguard Worker } 1392*f6dc9357SAndroid Build Coastguard Worker 1393*f6dc9357SAndroid Build Coastguard Worker #ifndef Z7_EXTRACT_ONLY 1394*f6dc9357SAndroid Build Coastguard Worker 1395*f6dc9357SAndroid Build Coastguard Worker if (!_filterMethod.MethodName.IsEmpty()) 1396*f6dc9357SAndroid Build Coastguard Worker { 1397*f6dc9357SAndroid Build Coastguard Worker unsigned k; 1398*f6dc9357SAndroid Build Coastguard Worker for (k = 0; k < Z7_ARRAY_SIZE(g_NamePairs); k++) 1399*f6dc9357SAndroid Build Coastguard Worker { 1400*f6dc9357SAndroid Build Coastguard Worker const CMethodNamePair &pair = g_NamePairs[k]; 1401*f6dc9357SAndroid Build Coastguard Worker if (StringsAreEqualNoCase_Ascii(_filterMethod.MethodName, pair.Name)) 1402*f6dc9357SAndroid Build Coastguard Worker { 1403*f6dc9357SAndroid Build Coastguard Worker _filterId = pair.Id; 1404*f6dc9357SAndroid Build Coastguard Worker break; 1405*f6dc9357SAndroid Build Coastguard Worker } 1406*f6dc9357SAndroid Build Coastguard Worker } 1407*f6dc9357SAndroid Build Coastguard Worker if (k == Z7_ARRAY_SIZE(g_NamePairs)) 1408*f6dc9357SAndroid Build Coastguard Worker return E_INVALIDARG; 1409*f6dc9357SAndroid Build Coastguard Worker } 1410*f6dc9357SAndroid Build Coastguard Worker 1411*f6dc9357SAndroid Build Coastguard Worker _methods.DeleteFrontal(GetNumEmptyMethods()); 1412*f6dc9357SAndroid Build Coastguard Worker if (_methods.Size() > 1) 1413*f6dc9357SAndroid Build Coastguard Worker return E_INVALIDARG; 1414*f6dc9357SAndroid Build Coastguard Worker if (_methods.Size() == 1) 1415*f6dc9357SAndroid Build Coastguard Worker { 1416*f6dc9357SAndroid Build Coastguard Worker AString &methodName = _methods[0].MethodName; 1417*f6dc9357SAndroid Build Coastguard Worker if (methodName.IsEmpty()) 1418*f6dc9357SAndroid Build Coastguard Worker methodName = k_LZMA2_Name; 1419*f6dc9357SAndroid Build Coastguard Worker else if ( 1420*f6dc9357SAndroid Build Coastguard Worker !methodName.IsEqualTo_Ascii_NoCase(k_LZMA2_Name) 1421*f6dc9357SAndroid Build Coastguard Worker && !methodName.IsEqualTo_Ascii_NoCase("xz")) 1422*f6dc9357SAndroid Build Coastguard Worker return E_INVALIDARG; 1423*f6dc9357SAndroid Build Coastguard Worker } 1424*f6dc9357SAndroid Build Coastguard Worker 1425*f6dc9357SAndroid Build Coastguard Worker #endif 1426*f6dc9357SAndroid Build Coastguard Worker 1427*f6dc9357SAndroid Build Coastguard Worker return S_OK; 1428*f6dc9357SAndroid Build Coastguard Worker 1429*f6dc9357SAndroid Build Coastguard Worker COM_TRY_END 1430*f6dc9357SAndroid Build Coastguard Worker } 1431*f6dc9357SAndroid Build Coastguard Worker 1432*f6dc9357SAndroid Build Coastguard Worker 1433*f6dc9357SAndroid Build Coastguard Worker REGISTER_ARC_IO( 1434*f6dc9357SAndroid Build Coastguard Worker "xz", "xz txz", "* .tar", 0xC, 1435*f6dc9357SAndroid Build Coastguard Worker XZ_SIG, 0 1436*f6dc9357SAndroid Build Coastguard Worker , NArcInfoFlags::kKeepName 1437*f6dc9357SAndroid Build Coastguard Worker , 0 1438*f6dc9357SAndroid Build Coastguard Worker , NULL) 1439*f6dc9357SAndroid Build Coastguard Worker 1440*f6dc9357SAndroid Build Coastguard Worker }} 1441