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.

     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 }}

mercurial