view src/win32/7zip/7z/CPP/7zip/Archive/7z/7zFolderOutStream.cpp @ 1:f9f4f1b99eed

importing src directory
author Robert McIntyre <rlm@mit.edu>
date Sat, 03 Mar 2012 10:31:27 -0600
parents
children
line wrap: on
line source
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 bool checkCrc)
24 {
25 _archiveDatabase = archiveDatabase;
26 _ref2Offset = ref2Offset;
27 _startIndex = startIndex;
29 _extractStatuses = extractStatuses;
30 _extractCallback = extractCallback;
31 _testMode = testMode;
33 _checkCrc = checkCrc;
35 _currentIndex = 0;
36 _fileIsOpen = false;
37 return WriteEmptyFiles();
38 }
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;
51 UInt32 index = _startIndex + _currentIndex;
52 RINOK(_extractCallback->GetStream(_ref2Offset + index, &realOutStream, askMode));
54 _outStreamWithHashSpec->SetStream(realOutStream);
55 _outStreamWithHashSpec->Init(_checkCrc);
56 if (askMode == NArchive::NExtract::NAskMode::kExtract &&
57 (!realOutStream))
58 {
59 const CFileItem &fi = _archiveDatabase->Files[index];
60 if (!_archiveDatabase->IsItemAnti(index) && !fi.IsDir)
61 askMode = NArchive::NExtract::NAskMode::kSkip;
62 }
63 return _extractCallback->PrepareOperation(askMode);
64 }
66 HRESULT CFolderOutStream::WriteEmptyFiles()
67 {
68 for(;_currentIndex < _extractStatuses->Size(); _currentIndex++)
69 {
70 UInt32 index = _startIndex + _currentIndex;
71 const CFileItem &fi = _archiveDatabase->Files[index];
72 if (!_archiveDatabase->IsItemAnti(index) && !fi.IsDir && fi.Size != 0)
73 return S_OK;
74 RINOK(OpenFile());
75 RINOK(_extractCallback->SetOperationResult(NArchive::NExtract::NOperationResult::kOK));
76 _outStreamWithHashSpec->ReleaseStream();
77 }
78 return S_OK;
79 }
81 STDMETHODIMP CFolderOutStream::Write(const void *data,
82 UInt32 size, UInt32 *processedSize)
83 {
84 UInt32 realProcessedSize = 0;
85 while(_currentIndex < _extractStatuses->Size())
86 {
87 if (_fileIsOpen)
88 {
89 UInt32 index = _startIndex + _currentIndex;
90 const CFileItem &fi = _archiveDatabase->Files[index];
91 UInt64 fileSize = fi.Size;
93 UInt32 numBytesToWrite = (UInt32)MyMin(fileSize - _filePos,
94 UInt64(size - realProcessedSize));
96 UInt32 processedSizeLocal;
97 RINOK(_outStreamWithHash->Write((const Byte *)data + realProcessedSize,
98 numBytesToWrite, &processedSizeLocal));
100 _filePos += processedSizeLocal;
101 realProcessedSize += processedSizeLocal;
102 if (_filePos == fileSize)
103 {
104 bool digestsAreEqual;
105 if (fi.CrcDefined && _checkCrc)
106 digestsAreEqual = fi.Crc == _outStreamWithHashSpec->GetCRC();
107 else
108 digestsAreEqual = true;
110 RINOK(_extractCallback->SetOperationResult(
111 digestsAreEqual ?
112 NArchive::NExtract::NOperationResult::kOK :
113 NArchive::NExtract::NOperationResult::kCRCError));
114 _outStreamWithHashSpec->ReleaseStream();
115 _fileIsOpen = false;
116 _currentIndex++;
117 }
118 if (realProcessedSize == size)
119 {
120 if (processedSize != NULL)
121 *processedSize = realProcessedSize;
122 return WriteEmptyFiles();
123 }
124 }
125 else
126 {
127 RINOK(OpenFile());
128 _fileIsOpen = true;
129 _filePos = 0;
130 }
131 }
132 if (processedSize != NULL)
133 *processedSize = size;
134 return S_OK;
135 }
137 HRESULT CFolderOutStream::FlushCorrupted(Int32 resultEOperationResult)
138 {
139 while(_currentIndex < _extractStatuses->Size())
140 {
141 if (_fileIsOpen)
142 {
143 RINOK(_extractCallback->SetOperationResult(resultEOperationResult));
144 _outStreamWithHashSpec->ReleaseStream();
145 _fileIsOpen = false;
146 _currentIndex++;
147 }
148 else
149 {
150 RINOK(OpenFile());
151 _fileIsOpen = true;
152 }
153 }
154 return S_OK;
155 }
157 HRESULT CFolderOutStream::WasWritingFinished()
158 {
159 if (_currentIndex == _extractStatuses->Size())
160 return S_OK;
161 return E_FAIL;
162 }
164 }}