diff -r ea891871f481 -r bb5522e88ab2 misc/libphysfs/lzma/CPP/7zip/UI/Common/Extract.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/misc/libphysfs/lzma/CPP/7zip/UI/Common/Extract.cpp Mon Apr 10 12:06:43 2017 -0400 @@ -0,0 +1,187 @@ +// Extract.cpp + +#include "StdAfx.h" + +#include "Extract.h" + +#include "Windows/Defs.h" +#include "Windows/FileDir.h" + +#include "OpenArchive.h" +#include "SetProperties.h" + +using namespace NWindows; + +HRESULT DecompressArchive( + IInArchive *archive, + UInt64 packSize, + const UString &defaultName, + const NWildcard::CCensorNode &wildcardCensor, + const CExtractOptions &options, + IExtractCallbackUI *callback, + CArchiveExtractCallback *extractCallbackSpec, + UString &errorMessage) +{ + CRecordVector realIndices; + UInt32 numItems; + RINOK(archive->GetNumberOfItems(&numItems)); + + for(UInt32 i = 0; i < numItems; i++) + { + UString filePath; + RINOK(GetArchiveItemPath(archive, i, options.DefaultItemName, filePath)); + bool isFolder; + RINOK(IsArchiveItemFolder(archive, i, isFolder)); + if (!wildcardCensor.CheckPath(filePath, !isFolder)) + continue; + realIndices.Add(i); + } + if (realIndices.Size() == 0) + { + callback->ThereAreNoFiles(); + return S_OK; + } + + UStringVector removePathParts; + + UString outDir = options.OutputDir; + outDir.Replace(L"*", defaultName); + if(!outDir.IsEmpty()) + if(!NFile::NDirectory::CreateComplexDirectory(outDir)) + { + HRESULT res = ::GetLastError(); + if (res == S_OK) + res = E_FAIL; + errorMessage = ((UString)L"Can not create output directory ") + outDir; + return res; + } + + extractCallbackSpec->Init( + archive, + callback, + options.StdOutMode, + outDir, + removePathParts, + options.DefaultItemName, + options.ArchiveFileInfo.LastWriteTime, + options.ArchiveFileInfo.Attributes, + packSize); + + #ifdef COMPRESS_MT + RINOK(SetProperties(archive, options.Properties)); + #endif + + HRESULT result = archive->Extract(&realIndices.Front(), + realIndices.Size(), options.TestMode? 1: 0, extractCallbackSpec); + + return callback->ExtractResult(result); +} + +HRESULT DecompressArchives( + CCodecs *codecs, + UStringVector &archivePaths, UStringVector &archivePathsFull, + const NWildcard::CCensorNode &wildcardCensor, + const CExtractOptions &optionsSpec, + IOpenCallbackUI *openCallback, + IExtractCallbackUI *extractCallback, + UString &errorMessage, + CDecompressStat &stat) +{ + stat.Clear(); + CExtractOptions options = optionsSpec; + int i; + UInt64 totalPackSize = 0; + CRecordVector archiveSizes; + for (i = 0; i < archivePaths.Size(); i++) + { + const UString &archivePath = archivePaths[i]; + NFile::NFind::CFileInfoW archiveFileInfo; + if (!NFile::NFind::FindFile(archivePath, archiveFileInfo)) + throw "there is no such archive"; + if (archiveFileInfo.IsDirectory()) + throw "can't decompress folder"; + archiveSizes.Add(archiveFileInfo.Size); + totalPackSize += archiveFileInfo.Size; + } + CArchiveExtractCallback *extractCallbackSpec = new CArchiveExtractCallback; + CMyComPtr ec(extractCallbackSpec); + bool multi = (archivePaths.Size() > 1); + extractCallbackSpec->InitForMulti(multi, options.PathMode, options.OverwriteMode); + if (multi) + { + RINOK(extractCallback->SetTotal(totalPackSize)); + } + for (i = 0; i < archivePaths.Size(); i++) + { + const UString &archivePath = archivePaths[i]; + NFile::NFind::CFileInfoW archiveFileInfo; + if (!NFile::NFind::FindFile(archivePath, archiveFileInfo)) + throw "there is no such archive"; + + if (archiveFileInfo.IsDirectory()) + throw "there is no such archive"; + + options.ArchiveFileInfo = archiveFileInfo; + + #ifndef _NO_CRYPTO + openCallback->ClearPasswordWasAskedFlag(); + #endif + + RINOK(extractCallback->BeforeOpen(archivePath)); + CArchiveLink archiveLink; + HRESULT result = MyOpenArchive(codecs, archivePath, archiveLink, openCallback); + + bool crypted = false; + #ifndef _NO_CRYPTO + crypted = openCallback->WasPasswordAsked(); + #endif + + RINOK(extractCallback->OpenResult(archivePath, result, crypted)); + if (result != S_OK) + continue; + + for (int v = 0; v < archiveLink.VolumePaths.Size(); v++) + { + int index = archivePathsFull.FindInSorted(archiveLink.VolumePaths[v]); + if (index >= 0 && index > i) + { + archivePaths.Delete(index); + archivePathsFull.Delete(index); + totalPackSize -= archiveSizes[index]; + archiveSizes.Delete(index); + } + } + if (archiveLink.VolumePaths.Size() != 0) + { + totalPackSize += archiveLink.VolumesSize; + RINOK(extractCallback->SetTotal(totalPackSize)); + } + + #ifndef _NO_CRYPTO + UString password; + RINOK(openCallback->GetPasswordIfAny(password)); + if (!password.IsEmpty()) + { + RINOK(extractCallback->SetPassword(password)); + } + #endif + + options.DefaultItemName = archiveLink.GetDefaultItemName(); + RINOK(DecompressArchive( + archiveLink.GetArchive(), + archiveFileInfo.Size + archiveLink.VolumesSize, + archiveLink.GetDefaultItemName(), + wildcardCensor, options, extractCallback, extractCallbackSpec, errorMessage)); + extractCallbackSpec->LocalProgressSpec->InSize += archiveFileInfo.Size + + archiveLink.VolumesSize; + extractCallbackSpec->LocalProgressSpec->OutSize = extractCallbackSpec->UnpackSize; + if (!errorMessage.IsEmpty()) + return E_FAIL; + } + stat.NumFolders = extractCallbackSpec->NumFolders; + stat.NumFiles = extractCallbackSpec->NumFiles; + stat.UnpackSize = extractCallbackSpec->UnpackSize; + stat.NumArchives = archivePaths.Size(); + stat.PackSize = extractCallbackSpec->LocalProgressSpec->InSize; + return S_OK; +}