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