1 // 7zFolderInStream.cpp
2
3 #include "StdAfx.h"
4
5 #include "../../../Windows/TimeUtils.h"
6
7 #include "7zFolderInStream.h"
8
9 namespace NArchive {
10 namespace N7z {
11
Init(IArchiveUpdateCallback * updateCallback,const UInt32 * indexes,unsigned numFiles)12 void CFolderInStream::Init(IArchiveUpdateCallback *updateCallback,
13 const UInt32 *indexes, unsigned numFiles)
14 {
15 _updateCallback = updateCallback;
16 _indexes = indexes;
17 _numFiles = numFiles;
18
19 Processed.ClearAndReserve(numFiles);
20 CRCs.ClearAndReserve(numFiles);
21 Sizes.ClearAndReserve(numFiles);
22
23 if (Need_CTime) CTimes.ClearAndReserve(numFiles);
24 if (Need_ATime) ATimes.ClearAndReserve(numFiles);
25 if (Need_MTime) MTimes.ClearAndReserve(numFiles);
26 if (Need_Attrib) Attribs.ClearAndReserve(numFiles);
27 TimesDefined.ClearAndReserve(numFiles);
28
29 _stream.Release();
30 }
31
OpenStream()32 HRESULT CFolderInStream::OpenStream()
33 {
34 _pos = 0;
35 _crc = CRC_INIT_VAL;
36 _size_Defined = false;
37 _times_Defined = false;
38 _size = 0;
39 FILETIME_Clear(_cTime);
40 FILETIME_Clear(_aTime);
41 FILETIME_Clear(_mTime);
42 _attrib = 0;
43
44 while (Processed.Size() < _numFiles)
45 {
46 CMyComPtr<ISequentialInStream> stream;
47 const HRESULT result = _updateCallback->GetStream(_indexes[Processed.Size()], &stream);
48 if (result != S_OK && result != S_FALSE)
49 return result;
50
51 _stream = stream;
52
53 if (stream)
54 {
55 {
56 CMyComPtr<IStreamGetProps> getProps;
57 stream.QueryInterface(IID_IStreamGetProps, (void **)&getProps);
58 if (getProps)
59 {
60 // access could be changed in first myx pass
61 if (getProps->GetProps(&_size,
62 Need_CTime ? &_cTime : NULL,
63 Need_ATime ? &_aTime : NULL,
64 Need_MTime ? &_mTime : NULL,
65 Need_Attrib ? &_attrib : NULL)
66 == S_OK)
67 {
68 _size_Defined = true;
69 _times_Defined = true;
70 }
71 return S_OK;
72 }
73 }
74 {
75 CMyComPtr<IStreamGetSize> streamGetSize;
76 stream.QueryInterface(IID_IStreamGetSize, &streamGetSize);
77 if (streamGetSize)
78 {
79 if (streamGetSize->GetSize(&_size) == S_OK)
80 _size_Defined = true;
81 }
82 return S_OK;
83 }
84 }
85
86 RINOK(AddFileInfo(result == S_OK));
87 }
88 return S_OK;
89 }
90
AddFt(CRecordVector<UInt64> & vec,const FILETIME & ft)91 static void AddFt(CRecordVector<UInt64> &vec, const FILETIME &ft)
92 {
93 vec.AddInReserved(FILETIME_To_UInt64(ft));
94 }
95
96 /*
97 HRESULT ReportItemProps(IArchiveUpdateCallbackArcProp *reportArcProp,
98 UInt32 index, UInt64 size, const UInt32 *crc)
99 {
100 PROPVARIANT prop;
101 prop.vt = VT_EMPTY;
102 prop.wReserved1 = 0;
103
104 NWindows::NCOM::PropVarEm_Set_UInt64(&prop, size);
105 RINOK(reportArcProp->ReportProp(NEventIndexType::kOutArcIndex, index, kpidSize, &prop));
106 if (crc)
107 {
108 NWindows::NCOM::PropVarEm_Set_UInt32(&prop, *crc);
109 RINOK(reportArcProp->ReportProp(NEventIndexType::kOutArcIndex, index, kpidCRC, &prop));
110 }
111 return reportArcProp->ReportFinished(NEventIndexType::kOutArcIndex, index, NUpdate::NOperationResult::kOK);
112 }
113 */
114
AddFileInfo(bool isProcessed)115 HRESULT CFolderInStream::AddFileInfo(bool isProcessed)
116 {
117 // const UInt32 index = _indexes[Processed.Size()];
118 Processed.AddInReserved(isProcessed);
119 Sizes.AddInReserved(_pos);
120 const UInt32 crc = CRC_GET_DIGEST(_crc);
121 CRCs.AddInReserved(crc);
122 TimesDefined.AddInReserved(_times_Defined);
123 if (Need_CTime) AddFt(CTimes, _cTime);
124 if (Need_ATime) AddFt(ATimes, _aTime);
125 if (Need_MTime) AddFt(MTimes, _mTime);
126 if (Need_Attrib) Attribs.AddInReserved(_attrib);
127 /*
128 if (isProcessed && _reportArcProp)
129 RINOK(ReportItemProps(_reportArcProp, index, _pos, &crc))
130 */
131 return _updateCallback->SetOperationResult(NArchive::NUpdate::NOperationResult::kOK);
132 }
133
Read(void * data,UInt32 size,UInt32 * processedSize)134 STDMETHODIMP CFolderInStream::Read(void *data, UInt32 size, UInt32 *processedSize)
135 {
136 if (processedSize)
137 *processedSize = 0;
138 while (size != 0)
139 {
140 if (_stream)
141 {
142 UInt32 cur = size;
143 const UInt32 kMax = (UInt32)1 << 20;
144 if (cur > kMax)
145 cur = kMax;
146 RINOK(_stream->Read(data, cur, &cur));
147 if (cur != 0)
148 {
149 _crc = CrcUpdate(_crc, data, cur);
150 _pos += cur;
151 if (processedSize)
152 *processedSize = cur;
153 return S_OK;
154 }
155
156 _stream.Release();
157 RINOK(AddFileInfo(true));
158 }
159
160 if (Processed.Size() >= _numFiles)
161 break;
162 RINOK(OpenStream());
163 }
164 return S_OK;
165 }
166
GetSubStreamSize(UInt64 subStream,UInt64 * value)167 STDMETHODIMP CFolderInStream::GetSubStreamSize(UInt64 subStream, UInt64 *value)
168 {
169 *value = 0;
170 if (subStream > Sizes.Size())
171 return S_FALSE; // E_FAIL;
172
173 unsigned index = (unsigned)subStream;
174 if (index < Sizes.Size())
175 {
176 *value = Sizes[index];
177 return S_OK;
178 }
179
180 if (!_size_Defined)
181 {
182 *value = _pos;
183 return S_FALSE;
184 }
185
186 *value = (_pos > _size ? _pos : _size);
187 return S_OK;
188 }
189
190 }}
191