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