| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187 |
- // 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<UInt32> 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<UInt64> 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<IArchiveExtractCallback> 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;
- }
|