1// 7zFolderInStream.cpp 2 3#include "StdAfx.h" 4 5#include "../../../Windows/TimeUtils.h" 6 7#include "7zFolderInStream.h" 8 9namespace NArchive { 10namespace N7z { 11 12void CFolderInStream::Init(IArchiveUpdateCallback *updateCallback, 13 const UInt32 *indexes, unsigned numFiles) 14{ 15 _updateCallback = updateCallback; 16 _indexes = indexes; 17 _numFiles = numFiles; 18 19 _totalSize_for_Coder = 0; 20 ClearFileInfo(); 21 22 Processed.ClearAndReserve(numFiles); 23 Sizes.ClearAndReserve(numFiles); 24 CRCs.ClearAndReserve(numFiles); 25 TimesDefined.ClearAndReserve(numFiles); 26 MTimes.ClearAndReserve(Need_MTime ? numFiles : (unsigned)0); 27 CTimes.ClearAndReserve(Need_CTime ? numFiles : (unsigned)0); 28 ATimes.ClearAndReserve(Need_ATime ? numFiles : (unsigned)0); 29 Attribs.ClearAndReserve(Need_Attrib ? numFiles : (unsigned)0); 30 31 // FolderCrc = CRC_INIT_VAL; 32 _stream.Release(); 33} 34 35void CFolderInStream::ClearFileInfo() 36{ 37 _pos = 0; 38 _crc = CRC_INIT_VAL; 39 _size_Defined = false; 40 _times_Defined = false; 41 _size = 0; 42 FILETIME_Clear(_mTime); 43 FILETIME_Clear(_cTime); 44 FILETIME_Clear(_aTime); 45 _attrib = 0; 46} 47 48HRESULT CFolderInStream::OpenStream() 49{ 50 while (Processed.Size() < _numFiles) 51 { 52 CMyComPtr<ISequentialInStream> stream; 53 const HRESULT result = _updateCallback->GetStream(_indexes[Processed.Size()], &stream); 54 if (result != S_OK && result != S_FALSE) 55 return result; 56 57 _stream = stream; 58 59 if (stream) 60 { 61 { 62 CMyComPtr<IStreamGetProps> getProps; 63 stream.QueryInterface(IID_IStreamGetProps, (void **)&getProps); 64 if (getProps) 65 { 66 // access could be changed in first myx pass 67 if (getProps->GetProps(&_size, 68 Need_CTime ? &_cTime : NULL, 69 Need_ATime ? &_aTime : NULL, 70 Need_MTime ? &_mTime : NULL, 71 Need_Attrib ? &_attrib : NULL) 72 == S_OK) 73 { 74 _size_Defined = true; 75 _times_Defined = true; 76 } 77 return S_OK; 78 } 79 } 80 { 81 CMyComPtr<IStreamGetSize> streamGetSize; 82 stream.QueryInterface(IID_IStreamGetSize, &streamGetSize); 83 if (streamGetSize) 84 { 85 if (streamGetSize->GetSize(&_size) == S_OK) 86 _size_Defined = true; 87 } 88 return S_OK; 89 } 90 } 91 92 RINOK(AddFileInfo(result == S_OK)) 93 } 94 return S_OK; 95} 96 97static void AddFt(CRecordVector<UInt64> &vec, const FILETIME &ft) 98{ 99 vec.AddInReserved(FILETIME_To_UInt64(ft)); 100} 101 102/* 103HRESULT ReportItemProps(IArchiveUpdateCallbackArcProp *reportArcProp, 104 UInt32 index, UInt64 size, const UInt32 *crc) 105{ 106 PROPVARIANT prop; 107 prop.vt = VT_EMPTY; 108 prop.wReserved1 = 0; 109 110 NWindows::NCOM::PropVarEm_Set_UInt64(&prop, size); 111 RINOK(reportArcProp->ReportProp(NEventIndexType::kOutArcIndex, index, kpidSize, &prop)); 112 if (crc) 113 { 114 NWindows::NCOM::PropVarEm_Set_UInt32(&prop, *crc); 115 RINOK(reportArcProp->ReportProp(NEventIndexType::kOutArcIndex, index, kpidCRC, &prop)); 116 } 117 return reportArcProp->ReportFinished(NEventIndexType::kOutArcIndex, index, NUpdate::NOperationResult::kOK); 118} 119*/ 120 121HRESULT CFolderInStream::AddFileInfo(bool isProcessed) 122{ 123 // const UInt32 index = _indexes[Processed.Size()]; 124 Processed.AddInReserved(isProcessed); 125 Sizes.AddInReserved(_pos); 126 CRCs.AddInReserved(CRC_GET_DIGEST(_crc)); 127 if (Need_Attrib) Attribs.AddInReserved(_attrib); 128 TimesDefined.AddInReserved(_times_Defined); 129 if (Need_MTime) AddFt(MTimes, _mTime); 130 if (Need_CTime) AddFt(CTimes, _cTime); 131 if (Need_ATime) AddFt(ATimes, _aTime); 132 ClearFileInfo(); 133 /* 134 if (isProcessed && _reportArcProp) 135 RINOK(ReportItemProps(_reportArcProp, index, _pos, &crc)) 136 */ 137 return _updateCallback->SetOperationResult(NArchive::NUpdate::NOperationResult::kOK); 138} 139 140Z7_COM7F_IMF(CFolderInStream::Read(void *data, UInt32 size, UInt32 *processedSize)) 141{ 142 if (processedSize) 143 *processedSize = 0; 144 while (size != 0) 145 { 146 if (_stream) 147 { 148 /* 149 if (_pos == 0) 150 { 151 const UInt32 align = (UInt32)1 << AlignLog; 152 const UInt32 offset = (UInt32)_totalSize_for_Coder & (align - 1); 153 if (offset != 0) 154 { 155 UInt32 cur = align - offset; 156 if (cur > size) 157 cur = size; 158 memset(data, 0, cur); 159 data = (Byte *)data + cur; 160 size -= cur; 161 // _pos += cur; // for debug 162 _totalSize_for_Coder += cur; 163 if (processedSize) 164 *processedSize += cur; 165 continue; 166 } 167 } 168 */ 169 UInt32 cur = size; 170 const UInt32 kMax = (UInt32)1 << 20; 171 if (cur > kMax) 172 cur = kMax; 173 RINOK(_stream->Read(data, cur, &cur)) 174 if (cur != 0) 175 { 176 // if (Need_Crc) 177 _crc = CrcUpdate(_crc, data, cur); 178 /* 179 if (FolderCrc) 180 FolderCrc = CrcUpdate(FolderCrc, data, cur); 181 */ 182 _pos += cur; 183 _totalSize_for_Coder += cur; 184 if (processedSize) 185 *processedSize = cur; // use +=cur, if continue is possible in loop 186 return S_OK; 187 } 188 189 _stream.Release(); 190 RINOK(AddFileInfo(true)) 191 } 192 193 if (Processed.Size() >= _numFiles) 194 break; 195 RINOK(OpenStream()) 196 } 197 return S_OK; 198} 199 200Z7_COM7F_IMF(CFolderInStream::GetSubStreamSize(UInt64 subStream, UInt64 *value)) 201{ 202 *value = 0; 203 if (subStream > Sizes.Size()) 204 return S_FALSE; // E_FAIL; 205 206 const unsigned index = (unsigned)subStream; 207 if (index < Sizes.Size()) 208 { 209 *value = Sizes[index]; 210 return S_OK; 211 } 212 213 if (!_size_Defined) 214 { 215 *value = _pos; 216 return S_FALSE; 217 } 218 219 *value = (_pos > _size ? _pos : _size); 220 return S_OK; 221} 222 223 224/* 225HRESULT CFolderInStream::CloseCrcStream() 226{ 227 if (!_crcStream) 228 return S_OK; 229 if (!_crcStream_Spec->WasFinished()) 230 return E_FAIL; 231 _crc = _crcStream_Spec->GetCRC() ^ CRC_INIT_VAL; // change it 232 const UInt64 size = _crcStream_Spec->GetSize(); 233 _pos = size; 234 _totalSize_for_Coder += size; 235 _crcStream.Release(); 236 // _crcStream->ReleaseStream(); 237 _stream.Release(); 238 return AddFileInfo(true); 239} 240 241Z7_COM7F_IMF(CFolderInStream::GetNextInSubStream(UInt64 *streamIndexRes, ISequentialInStream **stream) 242{ 243 RINOK(CloseCrcStream()) 244 *stream = NULL; 245 *streamIndexRes = Processed.Size(); 246 if (Processed.Size() >= _numFiles) 247 return S_OK; 248 RINOK(OpenStream()); 249 if (!_stream) 250 return S_OK; 251 if (!_crcStream) 252 { 253 _crcStream_Spec = new CSequentialInStreamWithCRC; 254 _crcStream = _crcStream_Spec; 255 } 256 _crcStream_Spec->Init(); 257 _crcStream_Spec->SetStream(_stream); 258 *stream = _crcStream; 259 _crcStream->AddRef(); 260 return S_OK; 261} 262*/ 263 264}} 265