// 7zFolderInStream.cpp #include "StdAfx.h" #include "../../../Windows/TimeUtils.h" #include "7zFolderInStream.h" namespace NArchive { namespace N7z { void CFolderInStream::Init(IArchiveUpdateCallback *updateCallback, const UInt32 *indexes, unsigned numFiles) { _updateCallback = updateCallback; _indexes = indexes; _numFiles = numFiles; _totalSize_for_Coder = 0; ClearFileInfo(); Processed.ClearAndReserve(numFiles); Sizes.ClearAndReserve(numFiles); CRCs.ClearAndReserve(numFiles); TimesDefined.ClearAndReserve(numFiles); MTimes.ClearAndReserve(Need_MTime ? numFiles : (unsigned)0); CTimes.ClearAndReserve(Need_CTime ? numFiles : (unsigned)0); ATimes.ClearAndReserve(Need_ATime ? numFiles : (unsigned)0); Attribs.ClearAndReserve(Need_Attrib ? numFiles : (unsigned)0); // FolderCrc = CRC_INIT_VAL; _stream.Release(); } void CFolderInStream::ClearFileInfo() { _pos = 0; _crc = CRC_INIT_VAL; _size_Defined = false; _times_Defined = false; _size = 0; FILETIME_Clear(_mTime); FILETIME_Clear(_cTime); FILETIME_Clear(_aTime); _attrib = 0; } HRESULT CFolderInStream::OpenStream() { while (Processed.Size() < _numFiles) { CMyComPtr stream; const HRESULT result = _updateCallback->GetStream(_indexes[Processed.Size()], &stream); if (result != S_OK && result != S_FALSE) return result; _stream = stream; if (stream) { { CMyComPtr getProps; stream.QueryInterface(IID_IStreamGetProps, (void **)&getProps); if (getProps) { // access could be changed in first myx pass if (getProps->GetProps(&_size, Need_CTime ? &_cTime : NULL, Need_ATime ? &_aTime : NULL, Need_MTime ? &_mTime : NULL, Need_Attrib ? &_attrib : NULL) == S_OK) { _size_Defined = true; _times_Defined = true; } return S_OK; } } { CMyComPtr streamGetSize; stream.QueryInterface(IID_IStreamGetSize, &streamGetSize); if (streamGetSize) { if (streamGetSize->GetSize(&_size) == S_OK) _size_Defined = true; } return S_OK; } } RINOK(AddFileInfo(result == S_OK)) } return S_OK; } static void AddFt(CRecordVector &vec, const FILETIME &ft) { vec.AddInReserved(FILETIME_To_UInt64(ft)); } /* HRESULT ReportItemProps(IArchiveUpdateCallbackArcProp *reportArcProp, UInt32 index, UInt64 size, const UInt32 *crc) { PROPVARIANT prop; prop.vt = VT_EMPTY; prop.wReserved1 = 0; NWindows::NCOM::PropVarEm_Set_UInt64(&prop, size); RINOK(reportArcProp->ReportProp(NEventIndexType::kOutArcIndex, index, kpidSize, &prop)); if (crc) { NWindows::NCOM::PropVarEm_Set_UInt32(&prop, *crc); RINOK(reportArcProp->ReportProp(NEventIndexType::kOutArcIndex, index, kpidCRC, &prop)); } return reportArcProp->ReportFinished(NEventIndexType::kOutArcIndex, index, NUpdate::NOperationResult::kOK); } */ HRESULT CFolderInStream::AddFileInfo(bool isProcessed) { // const UInt32 index = _indexes[Processed.Size()]; Processed.AddInReserved(isProcessed); Sizes.AddInReserved(_pos); CRCs.AddInReserved(CRC_GET_DIGEST(_crc)); if (Need_Attrib) Attribs.AddInReserved(_attrib); TimesDefined.AddInReserved(_times_Defined); if (Need_MTime) AddFt(MTimes, _mTime); if (Need_CTime) AddFt(CTimes, _cTime); if (Need_ATime) AddFt(ATimes, _aTime); ClearFileInfo(); /* if (isProcessed && _reportArcProp) RINOK(ReportItemProps(_reportArcProp, index, _pos, &crc)) */ return _updateCallback->SetOperationResult(NArchive::NUpdate::NOperationResult::kOK); } Z7_COM7F_IMF(CFolderInStream::Read(void *data, UInt32 size, UInt32 *processedSize)) { if (processedSize) *processedSize = 0; while (size != 0) { if (_stream) { /* if (_pos == 0) { const UInt32 align = (UInt32)1 << AlignLog; const UInt32 offset = (UInt32)_totalSize_for_Coder & (align - 1); if (offset != 0) { UInt32 cur = align - offset; if (cur > size) cur = size; memset(data, 0, cur); data = (Byte *)data + cur; size -= cur; // _pos += cur; // for debug _totalSize_for_Coder += cur; if (processedSize) *processedSize += cur; continue; } } */ UInt32 cur = size; const UInt32 kMax = (UInt32)1 << 20; if (cur > kMax) cur = kMax; RINOK(_stream->Read(data, cur, &cur)) if (cur != 0) { // if (Need_Crc) _crc = CrcUpdate(_crc, data, cur); /* if (FolderCrc) FolderCrc = CrcUpdate(FolderCrc, data, cur); */ _pos += cur; _totalSize_for_Coder += cur; if (processedSize) *processedSize = cur; // use +=cur, if continue is possible in loop return S_OK; } _stream.Release(); RINOK(AddFileInfo(true)) } if (Processed.Size() >= _numFiles) break; RINOK(OpenStream()) } return S_OK; } Z7_COM7F_IMF(CFolderInStream::GetSubStreamSize(UInt64 subStream, UInt64 *value)) { *value = 0; if (subStream > Sizes.Size()) return S_FALSE; // E_FAIL; const unsigned index = (unsigned)subStream; if (index < Sizes.Size()) { *value = Sizes[index]; return S_OK; } if (!_size_Defined) { *value = _pos; return S_FALSE; } *value = (_pos > _size ? _pos : _size); return S_OK; } /* HRESULT CFolderInStream::CloseCrcStream() { if (!_crcStream) return S_OK; if (!_crcStream_Spec->WasFinished()) return E_FAIL; _crc = _crcStream_Spec->GetCRC() ^ CRC_INIT_VAL; // change it const UInt64 size = _crcStream_Spec->GetSize(); _pos = size; _totalSize_for_Coder += size; _crcStream.Release(); // _crcStream->ReleaseStream(); _stream.Release(); return AddFileInfo(true); } Z7_COM7F_IMF(CFolderInStream::GetNextInSubStream(UInt64 *streamIndexRes, ISequentialInStream **stream) { RINOK(CloseCrcStream()) *stream = NULL; *streamIndexRes = Processed.Size(); if (Processed.Size() >= _numFiles) return S_OK; RINOK(OpenStream()); if (!_stream) return S_OK; if (!_crcStream) { _crcStream_Spec = new CSequentialInStreamWithCRC; _crcStream = _crcStream_Spec; } _crcStream_Spec->Init(); _crcStream_Spec->SetStream(_stream); *stream = _crcStream; _crcStream->AddRef(); return S_OK; } */ }}