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