1 // 7zFolderOutStream.cpp
5 #include "7zFolderOutStream.h"
10 CFolderOutStream::CFolderOutStream()
12 _outStreamWithHashSpec = new COutStreamWithCRC;
13 _outStreamWithHash = _outStreamWithHashSpec;
16 HRESULT CFolderOutStream::Init(
17 const CArchiveDatabaseEx *archiveDatabase,
20 const CBoolVector *extractStatuses,
21 IArchiveExtractCallback *extractCallback,
25 _archiveDatabase = archiveDatabase;
26 _ref2Offset = ref2Offset;
27 _startIndex = startIndex;
29 _extractStatuses = extractStatuses;
30 _extractCallback = extractCallback;
37 return WriteEmptyFiles();
40 HRESULT CFolderOutStream::OpenFile()
43 if((*_extractStatuses)[_currentIndex])
45 NArchive::NExtract::NAskMode::kTest :
46 NArchive::NExtract::NAskMode::kExtract;
48 askMode = NArchive::NExtract::NAskMode::kSkip;
49 CMyComPtr<ISequentialOutStream> realOutStream;
51 UInt32 index = _startIndex + _currentIndex;
52 RINOK(_extractCallback->GetStream(_ref2Offset + index, &realOutStream, askMode));
54 _outStreamWithHashSpec->SetStream(realOutStream);
55 _outStreamWithHashSpec->Init(_checkCrc);
56 if (askMode == NArchive::NExtract::NAskMode::kExtract &&
59 const CFileItem &fileInfo = _archiveDatabase->Files[index];
60 if (!fileInfo.IsAnti && !fileInfo.IsDirectory)
61 askMode = NArchive::NExtract::NAskMode::kSkip;
63 return _extractCallback->PrepareOperation(askMode);
66 HRESULT CFolderOutStream::WriteEmptyFiles()
68 for(;_currentIndex < _extractStatuses->Size(); _currentIndex++)
70 UInt32 index = _startIndex + _currentIndex;
71 const CFileItem &fileInfo = _archiveDatabase->Files[index];
72 if (!fileInfo.IsAnti && !fileInfo.IsDirectory && fileInfo.UnPackSize != 0)
75 RINOK(_extractCallback->SetOperationResult(
76 NArchive::NExtract::NOperationResult::kOK));
77 _outStreamWithHashSpec->ReleaseStream();
82 STDMETHODIMP CFolderOutStream::Write(const void *data,
83 UInt32 size, UInt32 *processedSize)
85 UInt32 realProcessedSize = 0;
86 while(_currentIndex < _extractStatuses->Size())
90 UInt32 index = _startIndex + _currentIndex;
91 const CFileItem &fileInfo = _archiveDatabase->Files[index];
92 UInt64 fileSize = fileInfo.UnPackSize;
94 UInt32 numBytesToWrite = (UInt32)MyMin(fileSize - _filePos,
95 UInt64(size - realProcessedSize));
97 UInt32 processedSizeLocal;
98 RINOK(_outStreamWithHash->Write((const Byte *)data + realProcessedSize,
99 numBytesToWrite, &processedSizeLocal));
101 _filePos += processedSizeLocal;
102 realProcessedSize += processedSizeLocal;
103 if (_filePos == fileSize)
105 bool digestsAreEqual;
106 if (fileInfo.IsFileCRCDefined && _checkCrc)
107 digestsAreEqual = fileInfo.FileCRC == _outStreamWithHashSpec->GetCRC();
109 digestsAreEqual = true;
111 RINOK(_extractCallback->SetOperationResult(
113 NArchive::NExtract::NOperationResult::kOK :
114 NArchive::NExtract::NOperationResult::kCRCError));
115 _outStreamWithHashSpec->ReleaseStream();
119 if (realProcessedSize == size)
121 if (processedSize != NULL)
122 *processedSize = realProcessedSize;
123 return WriteEmptyFiles();
133 if (processedSize != NULL)
134 *processedSize = size;
138 HRESULT CFolderOutStream::FlushCorrupted(Int32 resultEOperationResult)
140 while(_currentIndex < _extractStatuses->Size())
144 RINOK(_extractCallback->SetOperationResult(resultEOperationResult));
145 _outStreamWithHashSpec->ReleaseStream();
158 HRESULT CFolderOutStream::WasWritingFinished()
160 if (_currentIndex == _extractStatuses->Size())