other-licenses/7zstub/src/7zip/Archive/7z/7zFolderOutStream.cpp

Tue, 06 Jan 2015 21:39:09 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Tue, 06 Jan 2015 21:39:09 +0100
branch
TOR_BUG_9701
changeset 8
97036ab72558
permissions
-rw-r--r--

Conditionally force memory storage according to privacy.thirdparty.isolate;
This solves Tor bug #9701, complying with disk avoidance documented in
https://www.torproject.org/projects/torbrowser/design/#disk-avoidance.

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

mercurial