7zFolderOutStream.cpp 4.3 KB

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