Mercurial > vba-linux
comparison src/win32/7zip/7z/CPP/7zip/Archive/Tar/TarHandler.cpp @ 1:f9f4f1b99eed
importing src directory
author | Robert McIntyre <rlm@mit.edu> |
---|---|
date | Sat, 03 Mar 2012 10:31:27 -0600 |
parents | |
children |
comparison
equal
deleted
inserted
replaced
0:8ced16adf2e1 | 1:f9f4f1b99eed |
---|---|
1 // TarHandler.cpp | |
2 | |
3 #include "StdAfx.h" | |
4 | |
5 #include "Common/ComTry.h" | |
6 #include "Common/Defs.h" | |
7 #include "Common/NewHandler.h" | |
8 #include "Common/StringConvert.h" | |
9 | |
10 #include "Windows/PropVariant.h" | |
11 #include "Windows/Time.h" | |
12 | |
13 #include "../../Common/LimitedStreams.h" | |
14 #include "../../Common/ProgressUtils.h" | |
15 | |
16 #include "../../Compress/CopyCoder.h" | |
17 | |
18 #include "../Common/DummyOutStream.h" | |
19 #include "../Common/ItemNameUtils.h" | |
20 | |
21 #include "TarHandler.h" | |
22 #include "TarIn.h" | |
23 | |
24 using namespace NWindows; | |
25 | |
26 namespace NArchive { | |
27 namespace NTar { | |
28 | |
29 STATPROPSTG kProps[] = | |
30 { | |
31 { NULL, kpidPath, VT_BSTR}, | |
32 { NULL, kpidIsDir, VT_BOOL}, | |
33 { NULL, kpidSize, VT_UI8}, | |
34 { NULL, kpidPackSize, VT_UI8}, | |
35 { NULL, kpidMTime, VT_FILETIME}, | |
36 { NULL, kpidUser, VT_BSTR}, | |
37 { NULL, kpidGroup, VT_BSTR} | |
38 }; | |
39 | |
40 IMP_IInArchive_Props | |
41 IMP_IInArchive_ArcProps_NO | |
42 | |
43 HRESULT CHandler::Open2(IInStream *stream, IArchiveOpenCallback *callback) | |
44 { | |
45 UInt64 endPos = 0; | |
46 if (callback != NULL) | |
47 { | |
48 RINOK(stream->Seek(0, STREAM_SEEK_END, &endPos)); | |
49 RINOK(stream->Seek(0, STREAM_SEEK_SET, NULL)); | |
50 } | |
51 | |
52 UInt64 pos = 0; | |
53 for (;;) | |
54 { | |
55 CItemEx item; | |
56 bool filled; | |
57 item.HeaderPosition = pos; | |
58 RINOK(ReadItem(stream, filled, item)); | |
59 if (!filled) | |
60 break; | |
61 _items.Add(item); | |
62 | |
63 RINOK(stream->Seek(item.GetPackSize(), STREAM_SEEK_CUR, &pos)); | |
64 if (pos >= endPos) | |
65 return S_FALSE; | |
66 if (callback != NULL) | |
67 { | |
68 if (_items.Size() == 1) | |
69 { | |
70 RINOK(callback->SetTotal(NULL, &endPos)); | |
71 } | |
72 if (_items.Size() % 100 == 0) | |
73 { | |
74 UInt64 numFiles = _items.Size(); | |
75 RINOK(callback->SetCompleted(&numFiles, &pos)); | |
76 } | |
77 } | |
78 } | |
79 | |
80 if (_items.Size() == 0) | |
81 { | |
82 CMyComPtr<IArchiveOpenVolumeCallback> openVolumeCallback; | |
83 if (!callback) | |
84 return S_FALSE; | |
85 callback->QueryInterface(IID_IArchiveOpenVolumeCallback, (void **)&openVolumeCallback); | |
86 if (!openVolumeCallback) | |
87 return S_FALSE; | |
88 NCOM::CPropVariant prop; | |
89 if (openVolumeCallback->GetProperty(kpidName, &prop) != S_OK) | |
90 return S_FALSE; | |
91 if (prop.vt != VT_BSTR) | |
92 return S_FALSE; | |
93 UString baseName = prop.bstrVal; | |
94 baseName = baseName.Right(4); | |
95 if (baseName.CompareNoCase(L".tar") != 0) | |
96 return S_FALSE; | |
97 } | |
98 return S_OK; | |
99 } | |
100 | |
101 STDMETHODIMP CHandler::Open(IInStream *stream, | |
102 const UInt64 * /* maxCheckStartPosition */, | |
103 IArchiveOpenCallback *openArchiveCallback) | |
104 { | |
105 COM_TRY_BEGIN | |
106 { | |
107 Close(); | |
108 RINOK(Open2(stream, openArchiveCallback)); | |
109 _inStream = stream; | |
110 } | |
111 return S_OK; | |
112 COM_TRY_END | |
113 } | |
114 | |
115 STDMETHODIMP CHandler::Close() | |
116 { | |
117 _items.Clear(); | |
118 _inStream.Release(); | |
119 return S_OK; | |
120 } | |
121 | |
122 STDMETHODIMP CHandler::GetNumberOfItems(UInt32 *numItems) | |
123 { | |
124 *numItems = _items.Size(); | |
125 return S_OK; | |
126 } | |
127 | |
128 STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *value) | |
129 { | |
130 COM_TRY_BEGIN | |
131 NWindows::NCOM::CPropVariant prop; | |
132 const CItemEx &item = _items[index]; | |
133 | |
134 switch(propID) | |
135 { | |
136 case kpidPath: prop = NItemName::GetOSName2(MultiByteToUnicodeString(item.Name, CP_OEMCP)); break; | |
137 case kpidIsDir: prop = item.IsDir(); break; | |
138 case kpidSize: prop = item.Size; break; | |
139 case kpidPackSize: prop = item.GetPackSize(); break; | |
140 case kpidMTime: | |
141 if (item.MTime != 0) | |
142 { | |
143 FILETIME ft; | |
144 NTime::UnixTimeToFileTime(item.MTime, ft); | |
145 prop = ft; | |
146 } | |
147 break; | |
148 case kpidUser: prop = MultiByteToUnicodeString(item.UserName, CP_OEMCP); break; | |
149 case kpidGroup: prop = MultiByteToUnicodeString(item.GroupName, CP_OEMCP); break; | |
150 } | |
151 prop.Detach(value); | |
152 return S_OK; | |
153 COM_TRY_END | |
154 } | |
155 | |
156 STDMETHODIMP CHandler::Extract(const UInt32* indices, UInt32 numItems, | |
157 Int32 _aTestMode, IArchiveExtractCallback *extractCallback) | |
158 { | |
159 COM_TRY_BEGIN | |
160 bool testMode = (_aTestMode != 0); | |
161 bool allFilesMode = (numItems == UInt32(-1)); | |
162 if (allFilesMode) | |
163 numItems = _items.Size(); | |
164 if (numItems == 0) | |
165 return S_OK; | |
166 UInt64 totalSize = 0; | |
167 UInt32 i; | |
168 for (i = 0; i < numItems; i++) | |
169 totalSize += _items[allFilesMode ? i : indices[i]].Size; | |
170 extractCallback->SetTotal(totalSize); | |
171 | |
172 UInt64 totalPackSize, curPackSize, curSize; | |
173 totalSize = totalPackSize = 0; | |
174 | |
175 NCompress::CCopyCoder *copyCoderSpec = new NCompress::CCopyCoder(); | |
176 CMyComPtr<ICompressCoder> copyCoder = copyCoderSpec; | |
177 | |
178 CLocalProgress *lps = new CLocalProgress; | |
179 CMyComPtr<ICompressProgressInfo> progress = lps; | |
180 lps->Init(extractCallback, false); | |
181 | |
182 CLimitedSequentialInStream *streamSpec = new CLimitedSequentialInStream; | |
183 CMyComPtr<ISequentialInStream> inStream(streamSpec); | |
184 streamSpec->SetStream(_inStream); | |
185 | |
186 CDummyOutStream *outStreamSpec = new CDummyOutStream; | |
187 CMyComPtr<ISequentialOutStream> outStream(outStreamSpec); | |
188 | |
189 for (i = 0; i < numItems; i++, totalSize += curSize, totalPackSize += curPackSize) | |
190 { | |
191 lps->InSize = totalPackSize; | |
192 lps->OutSize = totalSize; | |
193 RINOK(lps->SetCur()); | |
194 CMyComPtr<ISequentialOutStream> realOutStream; | |
195 Int32 askMode = testMode ? | |
196 NArchive::NExtract::NAskMode::kTest : | |
197 NArchive::NExtract::NAskMode::kExtract; | |
198 Int32 index = allFilesMode ? i : indices[i]; | |
199 const CItemEx &item = _items[index]; | |
200 RINOK(extractCallback->GetStream(index, &realOutStream, askMode)); | |
201 curSize = item.Size; | |
202 curPackSize = item.GetPackSize(); | |
203 if (item.IsDir()) | |
204 { | |
205 RINOK(extractCallback->PrepareOperation(askMode)); | |
206 RINOK(extractCallback->SetOperationResult(NArchive::NExtract::NOperationResult::kOK)); | |
207 continue; | |
208 } | |
209 if (!testMode && (!realOutStream)) | |
210 continue; | |
211 RINOK(extractCallback->PrepareOperation(askMode)); | |
212 | |
213 outStreamSpec->SetStream(realOutStream); | |
214 realOutStream.Release(); | |
215 outStreamSpec->Init(); | |
216 | |
217 RINOK(_inStream->Seek(item.GetDataPosition(), STREAM_SEEK_SET, NULL)); | |
218 streamSpec->Init(item.Size); | |
219 RINOK(copyCoder->Code(inStream, outStream, NULL, NULL, progress)); | |
220 outStreamSpec->ReleaseStream(); | |
221 RINOK(extractCallback->SetOperationResult(copyCoderSpec->TotalSize == item.Size ? | |
222 NArchive::NExtract::NOperationResult::kOK: | |
223 NArchive::NExtract::NOperationResult::kDataError)); | |
224 } | |
225 return S_OK; | |
226 COM_TRY_END | |
227 } | |
228 | |
229 }} |