Mercurial > vba-linux
diff 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 |
line wrap: on
line diff
1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/src/win32/7zip/7z/CPP/7zip/Archive/Tar/TarHandler.cpp Sat Mar 03 10:31:27 2012 -0600 1.3 @@ -0,0 +1,229 @@ 1.4 +// TarHandler.cpp 1.5 + 1.6 +#include "StdAfx.h" 1.7 + 1.8 +#include "Common/ComTry.h" 1.9 +#include "Common/Defs.h" 1.10 +#include "Common/NewHandler.h" 1.11 +#include "Common/StringConvert.h" 1.12 + 1.13 +#include "Windows/PropVariant.h" 1.14 +#include "Windows/Time.h" 1.15 + 1.16 +#include "../../Common/LimitedStreams.h" 1.17 +#include "../../Common/ProgressUtils.h" 1.18 + 1.19 +#include "../../Compress/CopyCoder.h" 1.20 + 1.21 +#include "../Common/DummyOutStream.h" 1.22 +#include "../Common/ItemNameUtils.h" 1.23 + 1.24 +#include "TarHandler.h" 1.25 +#include "TarIn.h" 1.26 + 1.27 +using namespace NWindows; 1.28 + 1.29 +namespace NArchive { 1.30 +namespace NTar { 1.31 + 1.32 +STATPROPSTG kProps[] = 1.33 +{ 1.34 + { NULL, kpidPath, VT_BSTR}, 1.35 + { NULL, kpidIsDir, VT_BOOL}, 1.36 + { NULL, kpidSize, VT_UI8}, 1.37 + { NULL, kpidPackSize, VT_UI8}, 1.38 + { NULL, kpidMTime, VT_FILETIME}, 1.39 + { NULL, kpidUser, VT_BSTR}, 1.40 + { NULL, kpidGroup, VT_BSTR} 1.41 +}; 1.42 + 1.43 +IMP_IInArchive_Props 1.44 +IMP_IInArchive_ArcProps_NO 1.45 + 1.46 +HRESULT CHandler::Open2(IInStream *stream, IArchiveOpenCallback *callback) 1.47 +{ 1.48 + UInt64 endPos = 0; 1.49 + if (callback != NULL) 1.50 + { 1.51 + RINOK(stream->Seek(0, STREAM_SEEK_END, &endPos)); 1.52 + RINOK(stream->Seek(0, STREAM_SEEK_SET, NULL)); 1.53 + } 1.54 + 1.55 + UInt64 pos = 0; 1.56 + for (;;) 1.57 + { 1.58 + CItemEx item; 1.59 + bool filled; 1.60 + item.HeaderPosition = pos; 1.61 + RINOK(ReadItem(stream, filled, item)); 1.62 + if (!filled) 1.63 + break; 1.64 + _items.Add(item); 1.65 + 1.66 + RINOK(stream->Seek(item.GetPackSize(), STREAM_SEEK_CUR, &pos)); 1.67 + if (pos >= endPos) 1.68 + return S_FALSE; 1.69 + if (callback != NULL) 1.70 + { 1.71 + if (_items.Size() == 1) 1.72 + { 1.73 + RINOK(callback->SetTotal(NULL, &endPos)); 1.74 + } 1.75 + if (_items.Size() % 100 == 0) 1.76 + { 1.77 + UInt64 numFiles = _items.Size(); 1.78 + RINOK(callback->SetCompleted(&numFiles, &pos)); 1.79 + } 1.80 + } 1.81 + } 1.82 + 1.83 + if (_items.Size() == 0) 1.84 + { 1.85 + CMyComPtr<IArchiveOpenVolumeCallback> openVolumeCallback; 1.86 + if (!callback) 1.87 + return S_FALSE; 1.88 + callback->QueryInterface(IID_IArchiveOpenVolumeCallback, (void **)&openVolumeCallback); 1.89 + if (!openVolumeCallback) 1.90 + return S_FALSE; 1.91 + NCOM::CPropVariant prop; 1.92 + if (openVolumeCallback->GetProperty(kpidName, &prop) != S_OK) 1.93 + return S_FALSE; 1.94 + if (prop.vt != VT_BSTR) 1.95 + return S_FALSE; 1.96 + UString baseName = prop.bstrVal; 1.97 + baseName = baseName.Right(4); 1.98 + if (baseName.CompareNoCase(L".tar") != 0) 1.99 + return S_FALSE; 1.100 + } 1.101 + return S_OK; 1.102 +} 1.103 + 1.104 +STDMETHODIMP CHandler::Open(IInStream *stream, 1.105 + const UInt64 * /* maxCheckStartPosition */, 1.106 + IArchiveOpenCallback *openArchiveCallback) 1.107 +{ 1.108 + COM_TRY_BEGIN 1.109 + { 1.110 + Close(); 1.111 + RINOK(Open2(stream, openArchiveCallback)); 1.112 + _inStream = stream; 1.113 + } 1.114 + return S_OK; 1.115 + COM_TRY_END 1.116 +} 1.117 + 1.118 +STDMETHODIMP CHandler::Close() 1.119 +{ 1.120 + _items.Clear(); 1.121 + _inStream.Release(); 1.122 + return S_OK; 1.123 +} 1.124 + 1.125 +STDMETHODIMP CHandler::GetNumberOfItems(UInt32 *numItems) 1.126 +{ 1.127 + *numItems = _items.Size(); 1.128 + return S_OK; 1.129 +} 1.130 + 1.131 +STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *value) 1.132 +{ 1.133 + COM_TRY_BEGIN 1.134 + NWindows::NCOM::CPropVariant prop; 1.135 + const CItemEx &item = _items[index]; 1.136 + 1.137 + switch(propID) 1.138 + { 1.139 + case kpidPath: prop = NItemName::GetOSName2(MultiByteToUnicodeString(item.Name, CP_OEMCP)); break; 1.140 + case kpidIsDir: prop = item.IsDir(); break; 1.141 + case kpidSize: prop = item.Size; break; 1.142 + case kpidPackSize: prop = item.GetPackSize(); break; 1.143 + case kpidMTime: 1.144 + if (item.MTime != 0) 1.145 + { 1.146 + FILETIME ft; 1.147 + NTime::UnixTimeToFileTime(item.MTime, ft); 1.148 + prop = ft; 1.149 + } 1.150 + break; 1.151 + case kpidUser: prop = MultiByteToUnicodeString(item.UserName, CP_OEMCP); break; 1.152 + case kpidGroup: prop = MultiByteToUnicodeString(item.GroupName, CP_OEMCP); break; 1.153 + } 1.154 + prop.Detach(value); 1.155 + return S_OK; 1.156 + COM_TRY_END 1.157 +} 1.158 + 1.159 +STDMETHODIMP CHandler::Extract(const UInt32* indices, UInt32 numItems, 1.160 + Int32 _aTestMode, IArchiveExtractCallback *extractCallback) 1.161 +{ 1.162 + COM_TRY_BEGIN 1.163 + bool testMode = (_aTestMode != 0); 1.164 + bool allFilesMode = (numItems == UInt32(-1)); 1.165 + if (allFilesMode) 1.166 + numItems = _items.Size(); 1.167 + if (numItems == 0) 1.168 + return S_OK; 1.169 + UInt64 totalSize = 0; 1.170 + UInt32 i; 1.171 + for (i = 0; i < numItems; i++) 1.172 + totalSize += _items[allFilesMode ? i : indices[i]].Size; 1.173 + extractCallback->SetTotal(totalSize); 1.174 + 1.175 + UInt64 totalPackSize, curPackSize, curSize; 1.176 + totalSize = totalPackSize = 0; 1.177 + 1.178 + NCompress::CCopyCoder *copyCoderSpec = new NCompress::CCopyCoder(); 1.179 + CMyComPtr<ICompressCoder> copyCoder = copyCoderSpec; 1.180 + 1.181 + CLocalProgress *lps = new CLocalProgress; 1.182 + CMyComPtr<ICompressProgressInfo> progress = lps; 1.183 + lps->Init(extractCallback, false); 1.184 + 1.185 + CLimitedSequentialInStream *streamSpec = new CLimitedSequentialInStream; 1.186 + CMyComPtr<ISequentialInStream> inStream(streamSpec); 1.187 + streamSpec->SetStream(_inStream); 1.188 + 1.189 + CDummyOutStream *outStreamSpec = new CDummyOutStream; 1.190 + CMyComPtr<ISequentialOutStream> outStream(outStreamSpec); 1.191 + 1.192 + for (i = 0; i < numItems; i++, totalSize += curSize, totalPackSize += curPackSize) 1.193 + { 1.194 + lps->InSize = totalPackSize; 1.195 + lps->OutSize = totalSize; 1.196 + RINOK(lps->SetCur()); 1.197 + CMyComPtr<ISequentialOutStream> realOutStream; 1.198 + Int32 askMode = testMode ? 1.199 + NArchive::NExtract::NAskMode::kTest : 1.200 + NArchive::NExtract::NAskMode::kExtract; 1.201 + Int32 index = allFilesMode ? i : indices[i]; 1.202 + const CItemEx &item = _items[index]; 1.203 + RINOK(extractCallback->GetStream(index, &realOutStream, askMode)); 1.204 + curSize = item.Size; 1.205 + curPackSize = item.GetPackSize(); 1.206 + if (item.IsDir()) 1.207 + { 1.208 + RINOK(extractCallback->PrepareOperation(askMode)); 1.209 + RINOK(extractCallback->SetOperationResult(NArchive::NExtract::NOperationResult::kOK)); 1.210 + continue; 1.211 + } 1.212 + if (!testMode && (!realOutStream)) 1.213 + continue; 1.214 + RINOK(extractCallback->PrepareOperation(askMode)); 1.215 + 1.216 + outStreamSpec->SetStream(realOutStream); 1.217 + realOutStream.Release(); 1.218 + outStreamSpec->Init(); 1.219 + 1.220 + RINOK(_inStream->Seek(item.GetDataPosition(), STREAM_SEEK_SET, NULL)); 1.221 + streamSpec->Init(item.Size); 1.222 + RINOK(copyCoder->Code(inStream, outStream, NULL, NULL, progress)); 1.223 + outStreamSpec->ReleaseStream(); 1.224 + RINOK(extractCallback->SetOperationResult(copyCoderSpec->TotalSize == item.Size ? 1.225 + NArchive::NExtract::NOperationResult::kOK: 1.226 + NArchive::NExtract::NOperationResult::kDataError)); 1.227 + } 1.228 + return S_OK; 1.229 + COM_TRY_END 1.230 +} 1.231 + 1.232 +}}