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