rlm@1
|
1 // 7zFolderOutStream.cpp
|
rlm@1
|
2
|
rlm@1
|
3 #include "StdAfx.h"
|
rlm@1
|
4
|
rlm@1
|
5 #include "7zFolderOutStream.h"
|
rlm@1
|
6
|
rlm@1
|
7 namespace NArchive {
|
rlm@1
|
8 namespace N7z {
|
rlm@1
|
9
|
rlm@1
|
10 CFolderOutStream::CFolderOutStream()
|
rlm@1
|
11 {
|
rlm@1
|
12 _outStreamWithHashSpec = new COutStreamWithCRC;
|
rlm@1
|
13 _outStreamWithHash = _outStreamWithHashSpec;
|
rlm@1
|
14 }
|
rlm@1
|
15
|
rlm@1
|
16 HRESULT CFolderOutStream::Init(
|
rlm@1
|
17 const CArchiveDatabaseEx *archiveDatabase,
|
rlm@1
|
18 UInt32 ref2Offset,
|
rlm@1
|
19 UInt32 startIndex,
|
rlm@1
|
20 const CBoolVector *extractStatuses,
|
rlm@1
|
21 IArchiveExtractCallback *extractCallback,
|
rlm@1
|
22 bool testMode,
|
rlm@1
|
23 bool checkCrc)
|
rlm@1
|
24 {
|
rlm@1
|
25 _archiveDatabase = archiveDatabase;
|
rlm@1
|
26 _ref2Offset = ref2Offset;
|
rlm@1
|
27 _startIndex = startIndex;
|
rlm@1
|
28
|
rlm@1
|
29 _extractStatuses = extractStatuses;
|
rlm@1
|
30 _extractCallback = extractCallback;
|
rlm@1
|
31 _testMode = testMode;
|
rlm@1
|
32
|
rlm@1
|
33 _checkCrc = checkCrc;
|
rlm@1
|
34
|
rlm@1
|
35 _currentIndex = 0;
|
rlm@1
|
36 _fileIsOpen = false;
|
rlm@1
|
37 return WriteEmptyFiles();
|
rlm@1
|
38 }
|
rlm@1
|
39
|
rlm@1
|
40 HRESULT CFolderOutStream::OpenFile()
|
rlm@1
|
41 {
|
rlm@1
|
42 Int32 askMode;
|
rlm@1
|
43 if((*_extractStatuses)[_currentIndex])
|
rlm@1
|
44 askMode = _testMode ?
|
rlm@1
|
45 NArchive::NExtract::NAskMode::kTest :
|
rlm@1
|
46 NArchive::NExtract::NAskMode::kExtract;
|
rlm@1
|
47 else
|
rlm@1
|
48 askMode = NArchive::NExtract::NAskMode::kSkip;
|
rlm@1
|
49 CMyComPtr<ISequentialOutStream> realOutStream;
|
rlm@1
|
50
|
rlm@1
|
51 UInt32 index = _startIndex + _currentIndex;
|
rlm@1
|
52 RINOK(_extractCallback->GetStream(_ref2Offset + index, &realOutStream, askMode));
|
rlm@1
|
53
|
rlm@1
|
54 _outStreamWithHashSpec->SetStream(realOutStream);
|
rlm@1
|
55 _outStreamWithHashSpec->Init(_checkCrc);
|
rlm@1
|
56 if (askMode == NArchive::NExtract::NAskMode::kExtract &&
|
rlm@1
|
57 (!realOutStream))
|
rlm@1
|
58 {
|
rlm@1
|
59 const CFileItem &fi = _archiveDatabase->Files[index];
|
rlm@1
|
60 if (!_archiveDatabase->IsItemAnti(index) && !fi.IsDir)
|
rlm@1
|
61 askMode = NArchive::NExtract::NAskMode::kSkip;
|
rlm@1
|
62 }
|
rlm@1
|
63 return _extractCallback->PrepareOperation(askMode);
|
rlm@1
|
64 }
|
rlm@1
|
65
|
rlm@1
|
66 HRESULT CFolderOutStream::WriteEmptyFiles()
|
rlm@1
|
67 {
|
rlm@1
|
68 for(;_currentIndex < _extractStatuses->Size(); _currentIndex++)
|
rlm@1
|
69 {
|
rlm@1
|
70 UInt32 index = _startIndex + _currentIndex;
|
rlm@1
|
71 const CFileItem &fi = _archiveDatabase->Files[index];
|
rlm@1
|
72 if (!_archiveDatabase->IsItemAnti(index) && !fi.IsDir && fi.Size != 0)
|
rlm@1
|
73 return S_OK;
|
rlm@1
|
74 RINOK(OpenFile());
|
rlm@1
|
75 RINOK(_extractCallback->SetOperationResult(NArchive::NExtract::NOperationResult::kOK));
|
rlm@1
|
76 _outStreamWithHashSpec->ReleaseStream();
|
rlm@1
|
77 }
|
rlm@1
|
78 return S_OK;
|
rlm@1
|
79 }
|
rlm@1
|
80
|
rlm@1
|
81 STDMETHODIMP CFolderOutStream::Write(const void *data,
|
rlm@1
|
82 UInt32 size, UInt32 *processedSize)
|
rlm@1
|
83 {
|
rlm@1
|
84 UInt32 realProcessedSize = 0;
|
rlm@1
|
85 while(_currentIndex < _extractStatuses->Size())
|
rlm@1
|
86 {
|
rlm@1
|
87 if (_fileIsOpen)
|
rlm@1
|
88 {
|
rlm@1
|
89 UInt32 index = _startIndex + _currentIndex;
|
rlm@1
|
90 const CFileItem &fi = _archiveDatabase->Files[index];
|
rlm@1
|
91 UInt64 fileSize = fi.Size;
|
rlm@1
|
92
|
rlm@1
|
93 UInt32 numBytesToWrite = (UInt32)MyMin(fileSize - _filePos,
|
rlm@1
|
94 UInt64(size - realProcessedSize));
|
rlm@1
|
95
|
rlm@1
|
96 UInt32 processedSizeLocal;
|
rlm@1
|
97 RINOK(_outStreamWithHash->Write((const Byte *)data + realProcessedSize,
|
rlm@1
|
98 numBytesToWrite, &processedSizeLocal));
|
rlm@1
|
99
|
rlm@1
|
100 _filePos += processedSizeLocal;
|
rlm@1
|
101 realProcessedSize += processedSizeLocal;
|
rlm@1
|
102 if (_filePos == fileSize)
|
rlm@1
|
103 {
|
rlm@1
|
104 bool digestsAreEqual;
|
rlm@1
|
105 if (fi.CrcDefined && _checkCrc)
|
rlm@1
|
106 digestsAreEqual = fi.Crc == _outStreamWithHashSpec->GetCRC();
|
rlm@1
|
107 else
|
rlm@1
|
108 digestsAreEqual = true;
|
rlm@1
|
109
|
rlm@1
|
110 RINOK(_extractCallback->SetOperationResult(
|
rlm@1
|
111 digestsAreEqual ?
|
rlm@1
|
112 NArchive::NExtract::NOperationResult::kOK :
|
rlm@1
|
113 NArchive::NExtract::NOperationResult::kCRCError));
|
rlm@1
|
114 _outStreamWithHashSpec->ReleaseStream();
|
rlm@1
|
115 _fileIsOpen = false;
|
rlm@1
|
116 _currentIndex++;
|
rlm@1
|
117 }
|
rlm@1
|
118 if (realProcessedSize == size)
|
rlm@1
|
119 {
|
rlm@1
|
120 if (processedSize != NULL)
|
rlm@1
|
121 *processedSize = realProcessedSize;
|
rlm@1
|
122 return WriteEmptyFiles();
|
rlm@1
|
123 }
|
rlm@1
|
124 }
|
rlm@1
|
125 else
|
rlm@1
|
126 {
|
rlm@1
|
127 RINOK(OpenFile());
|
rlm@1
|
128 _fileIsOpen = true;
|
rlm@1
|
129 _filePos = 0;
|
rlm@1
|
130 }
|
rlm@1
|
131 }
|
rlm@1
|
132 if (processedSize != NULL)
|
rlm@1
|
133 *processedSize = size;
|
rlm@1
|
134 return S_OK;
|
rlm@1
|
135 }
|
rlm@1
|
136
|
rlm@1
|
137 HRESULT CFolderOutStream::FlushCorrupted(Int32 resultEOperationResult)
|
rlm@1
|
138 {
|
rlm@1
|
139 while(_currentIndex < _extractStatuses->Size())
|
rlm@1
|
140 {
|
rlm@1
|
141 if (_fileIsOpen)
|
rlm@1
|
142 {
|
rlm@1
|
143 RINOK(_extractCallback->SetOperationResult(resultEOperationResult));
|
rlm@1
|
144 _outStreamWithHashSpec->ReleaseStream();
|
rlm@1
|
145 _fileIsOpen = false;
|
rlm@1
|
146 _currentIndex++;
|
rlm@1
|
147 }
|
rlm@1
|
148 else
|
rlm@1
|
149 {
|
rlm@1
|
150 RINOK(OpenFile());
|
rlm@1
|
151 _fileIsOpen = true;
|
rlm@1
|
152 }
|
rlm@1
|
153 }
|
rlm@1
|
154 return S_OK;
|
rlm@1
|
155 }
|
rlm@1
|
156
|
rlm@1
|
157 HRESULT CFolderOutStream::WasWritingFinished()
|
rlm@1
|
158 {
|
rlm@1
|
159 if (_currentIndex == _extractStatuses->Size())
|
rlm@1
|
160 return S_OK;
|
rlm@1
|
161 return E_FAIL;
|
rlm@1
|
162 }
|
rlm@1
|
163
|
rlm@1
|
164 }}
|