summaryrefslogtreecommitdiffstats
path: root/src/libs/7zip/win/CPP/7zip/UI/Common/ArchiveExtractCallback.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/libs/7zip/win/CPP/7zip/UI/Common/ArchiveExtractCallback.cpp')
-rw-r--r--src/libs/7zip/win/CPP/7zip/UI/Common/ArchiveExtractCallback.cpp1191
1 files changed, 0 insertions, 1191 deletions
diff --git a/src/libs/7zip/win/CPP/7zip/UI/Common/ArchiveExtractCallback.cpp b/src/libs/7zip/win/CPP/7zip/UI/Common/ArchiveExtractCallback.cpp
deleted file mode 100644
index 250f66797..000000000
--- a/src/libs/7zip/win/CPP/7zip/UI/Common/ArchiveExtractCallback.cpp
+++ /dev/null
@@ -1,1191 +0,0 @@
-// ArchiveExtractCallback.cpp
-
-#include "StdAfx.h"
-
-#undef sprintf
-#undef printf
-
-#include "../../../Common/ComTry.h"
-#include "../../../Common/StringConvert.h"
-#include "../../../Common/Wildcard.h"
-
-#include "../../../Windows/FileDir.h"
-#include "../../../Windows/FileFind.h"
-#include "../../../Windows/FileName.h"
-#include "../../../Windows/PropVariant.h"
-#include "../../../Windows/PropVariantConv.h"
-
-#if defined(_WIN32) && !defined(UNDER_CE) && !defined(_SFX)
-#define _USE_SECURITY_CODE
-#include "../../../Windows/SecurityUtils.h"
-#endif
-
-#include "../../Common/FilePathAutoRename.h"
-
-#include "../Common/ExtractingFilePath.h"
-#include "../Common/PropIDUtils.h"
-
-#include "ArchiveExtractCallback.h"
-
-using namespace NWindows;
-using namespace NFile;
-using namespace NDir;
-
-static const char *kCantAutoRename = "Can not create file with auto name";
-static const char *kCantRenameFile = "Can not rename existing file";
-static const char *kCantDeleteOutputFile = "Can not delete output file";
-static const char *kCantDeleteOutputDir = "Can not delete output folder";
-
-
-#ifndef _SFX
-
-STDMETHODIMP COutStreamWithHash::Write(const void *data, UInt32 size, UInt32 *processedSize)
-{
- HRESULT result = S_OK;
- if (_stream)
- result = _stream->Write(data, size, &size);
- if (_calculate)
- _hash->Update(data, size);
- _size += size;
- if (processedSize)
- *processedSize = size;
- return result;
-}
-
-#endif
-
-#ifdef _USE_SECURITY_CODE
-bool InitLocalPrivileges()
-{
- NSecurity::CAccessToken token;
- if (!token.OpenProcessToken(GetCurrentProcess(),
- TOKEN_QUERY | TOKEN_ADJUST_PRIVILEGES))
- return false;
-
- TOKEN_PRIVILEGES tp;
-
- tp.PrivilegeCount = 1;
- tp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
-
- if (!::LookupPrivilegeValue(NULL, SE_SECURITY_NAME, &tp.Privileges[0].Luid))
- return false;
- if (!token.AdjustPrivileges(&tp))
- return false;
- return (GetLastError() == ERROR_SUCCESS);
-}
-#endif
-
-#ifdef SUPPORT_LINKS
-
-int CHardLinkNode::Compare(const CHardLinkNode &a) const
-{
- if (StreamId < a.StreamId) return -1;
- if (StreamId > a.StreamId) return 1;
- return MyCompare(INode, a.INode);
-}
-
-HRESULT Archive_Get_HardLinkNode(IInArchive *archive, UInt32 index, CHardLinkNode &h, bool &defined)
-{
- h.INode = 0;
- h.StreamId = (UInt64)(Int64)-1;
- defined = false;
- {
- NCOM::CPropVariant prop;
- RINOK(archive->GetProperty(index, kpidINode, &prop));
- if (!ConvertPropVariantToUInt64(prop, h.INode))
- return S_OK;
- }
- {
- NCOM::CPropVariant prop;
- RINOK(archive->GetProperty(index, kpidStreamId, &prop));
- ConvertPropVariantToUInt64(prop, h.StreamId);
- }
- defined = true;
- return S_OK;
-}
-
-
-HRESULT CArchiveExtractCallback::PrepareHardLinks(const CRecordVector<UInt32> *realIndices)
-{
- _hardLinks.Clear();
-
- if (!_arc->Ask_INode)
- return S_OK;
-
- IInArchive *archive = _arc->Archive;
- CRecordVector<CHardLinkNode> &hardIDs = _hardLinks.IDs;
-
- {
- UInt32 numItems;
- if (realIndices)
- numItems = realIndices->Size();
- else
- {
- RINOK(archive->GetNumberOfItems(&numItems));
- }
-
- for (UInt32 i = 0; i < numItems; i++)
- {
- CHardLinkNode h;
- bool defined;
- RINOK(Archive_Get_HardLinkNode(archive, realIndices ? (*realIndices)[i] : i, h, defined));
- if (defined)
- hardIDs.Add(h);
- }
- }
-
- hardIDs.Sort2();
-
- {
- // wee keep only items that have 2 or more items
- unsigned k = 0;
- unsigned numSame = 1;
- for (unsigned i = 1; i < hardIDs.Size(); i++)
- {
- if (hardIDs[i].Compare(hardIDs[i - 1]) != 0)
- numSame = 1;
- else if (++numSame == 2)
- {
- if (i - 1 != k)
- hardIDs[k] = hardIDs[i - 1];
- k++;
- }
- }
- hardIDs.DeleteFrom(k);
- }
-
- _hardLinks.PrepareLinks();
- return S_OK;
-}
-
-#endif
-
-CArchiveExtractCallback::CArchiveExtractCallback():
- WriteCTime(true),
- WriteATime(true),
- WriteMTime(true),
- _multiArchives(false)
-{
- LocalProgressSpec = new CLocalProgress();
- _localProgress = LocalProgressSpec;
-
- #ifdef _USE_SECURITY_CODE
- _saclEnabled = InitLocalPrivileges();
- #endif
-}
-
-void CArchiveExtractCallback::Init(
- const CExtractNtOptions &ntOptions,
- const NWildcard::CCensorNode *wildcardCensor,
- const CArc *arc,
- IFolderArchiveExtractCallback *extractCallback2,
- bool stdOutMode, bool testMode,
- const FString &directoryPath,
- const UStringVector &removePathParts,
- UInt64 packSize)
-{
- _extractedFolderPaths.Clear();
- _extractedFolderIndices.Clear();
-
- #ifdef SUPPORT_LINKS
- _hardLinks.Clear();
- #endif
-
- _ntOptions = ntOptions;
- _wildcardCensor = wildcardCensor;
-
- _stdOutMode = stdOutMode;
- _testMode = testMode;
- _unpTotal = 1;
- _packTotal = packSize;
-
- _extractCallback2 = extractCallback2;
- _compressProgress.Release();
- _extractCallback2.QueryInterface(IID_ICompressProgressInfo, &_compressProgress);
-
- #ifndef _SFX
-
- _extractCallback2.QueryInterface(IID_IFolderExtractToStreamCallback, &ExtractToStreamCallback);
- if (ExtractToStreamCallback)
- {
- Int32 useStreams = 0;
- if (ExtractToStreamCallback->UseExtractToStream(&useStreams) != S_OK)
- useStreams = 0;
- if (useStreams == 0)
- ExtractToStreamCallback.Release();
- }
-
- #endif
-
- LocalProgressSpec->Init(extractCallback2, true);
- LocalProgressSpec->SendProgress = false;
-
- _removePathParts = removePathParts;
- _baseParentFolder = (UInt32)(Int32)-1;
- _use_baseParentFolder_mode = false;
-
- _arc = arc;
- _directoryPath = directoryPath;
- NName::NormalizeDirPathPrefix(_directoryPath);
- NDir::MyGetFullPathName(directoryPath, _directoryPathFull);
-}
-
-STDMETHODIMP CArchiveExtractCallback::SetTotal(UInt64 size)
-{
- COM_TRY_BEGIN
- _unpTotal = size;
- if (!_multiArchives && _extractCallback2)
- return _extractCallback2->SetTotal(size);
- return S_OK;
- COM_TRY_END
-}
-
-static void NormalizeVals(UInt64 &v1, UInt64 &v2)
-{
- const UInt64 kMax = (UInt64)1 << 31;
- while (v1 > kMax)
- {
- v1 >>= 1;
- v2 >>= 1;
- }
-}
-
-static UInt64 MyMultDiv64(UInt64 unpCur, UInt64 unpTotal, UInt64 packTotal)
-{
- NormalizeVals(packTotal, unpTotal);
- NormalizeVals(unpCur, unpTotal);
- if (unpTotal == 0)
- unpTotal = 1;
- return unpCur * packTotal / unpTotal;
-}
-
-STDMETHODIMP CArchiveExtractCallback::SetCompleted(const UInt64 *completeValue)
-{
- COM_TRY_BEGIN
- if (!_extractCallback2)
- return S_OK;
-
- if (_multiArchives)
- {
- if (completeValue != NULL)
- {
- UInt64 packCur = LocalProgressSpec->InSize + MyMultDiv64(*completeValue, _unpTotal, _packTotal);
- return _extractCallback2->SetCompleted(&packCur);
- }
- }
- return _extractCallback2->SetCompleted(completeValue);
- COM_TRY_END
-}
-
-STDMETHODIMP CArchiveExtractCallback::SetRatioInfo(const UInt64 *inSize, const UInt64 *outSize)
-{
- COM_TRY_BEGIN
- return _localProgress->SetRatioInfo(inSize, outSize);
- COM_TRY_END
-}
-
-#define IS_LETTER_CHAR(c) ((c) >= 'a' && (c) <= 'z' || (c) >= 'A' && (c) <= 'Z')
-
-static inline bool IsDriveName(const UString &s)
-{
- return s.Len() == 2 && s[1] == ':' && IS_LETTER_CHAR(s[0]);
-}
-
-void CArchiveExtractCallback::CreateComplexDirectory(const UStringVector &dirPathParts, FString &fullPath)
-{
- bool isAbsPath = false;
-
- if (!dirPathParts.IsEmpty())
- {
- const UString &s = dirPathParts[0];
- if (s.IsEmpty())
- isAbsPath = true;
- #ifdef _WIN32
- else
- {
- if (dirPathParts.Size() > 1 && IsDriveName(s))
- isAbsPath = true;
- }
- #endif
- }
-
- if (_pathMode == NExtract::NPathMode::kAbsPaths && isAbsPath)
- fullPath.Empty();
- else
- fullPath = _directoryPath;
-
- FOR_VECTOR (i, dirPathParts)
- {
- if (i > 0)
- fullPath += FCHAR_PATH_SEPARATOR;
- const UString &s = dirPathParts[i];
- fullPath += us2fs(s);
- #ifdef _WIN32
- if (_pathMode == NExtract::NPathMode::kAbsPaths)
- if (i == 0 && IsDriveName(s))
- continue;
- #endif
- CreateDir(fullPath);
- }
-}
-
-HRESULT CArchiveExtractCallback::GetTime(int index, PROPID propID, FILETIME &filetime, bool &filetimeIsDefined)
-{
- filetimeIsDefined = false;
- NCOM::CPropVariant prop;
- RINOK(_arc->Archive->GetProperty(index, propID, &prop));
- if (prop.vt == VT_FILETIME)
- {
- filetime = prop.filetime;
- filetimeIsDefined = (filetime.dwHighDateTime != 0 || filetime.dwLowDateTime != 0);
- }
- else if (prop.vt != VT_EMPTY)
- return E_FAIL;
- return S_OK;
-}
-
-HRESULT CArchiveExtractCallback::GetUnpackSize()
-{
- return _arc->GetItemSize(_index, _curSize, _curSizeDefined);
-}
-
-HRESULT CArchiveExtractCallback::SendMessageError(const char *message, const FString &path)
-{
- return _extractCallback2->MessageError(
- UString(L"ERROR: ") +
- GetUnicodeString(message) + L": " + fs2us(path));
-}
-
-HRESULT CArchiveExtractCallback::SendMessageError2(const char *message, const FString &path1, const FString &path2)
-{
- return _extractCallback2->MessageError(
- UString(L"ERROR: ") +
- GetUnicodeString(message) + UString(L": ") + fs2us(path1) + UString(L" : ") + fs2us(path2));
-}
-
-#ifndef _SFX
-
-STDMETHODIMP CGetProp::GetProp(PROPID propID, PROPVARIANT *value)
-{
- if (propID == kpidName)
- {
- COM_TRY_BEGIN
- NCOM::CPropVariant prop = Name.Ptr();
- prop.Detach(value);
- return S_OK;
- COM_TRY_END
- }
- return Arc->Archive->GetProperty(IndexInArc, propID, value);
-}
-
-#endif
-
-
-#ifdef SUPPORT_LINKS
-
-static UString GetDirPrefixOf(const UString &src)
-{
- UString s = src;
- if (!s.IsEmpty())
- {
- if (s.Back() == WCHAR_PATH_SEPARATOR)
- s.DeleteBack();
- int pos = s.ReverseFind(WCHAR_PATH_SEPARATOR);
- s.DeleteFrom(pos + 1);
- }
- return s;
-}
-
-static bool IsSafePath(const UString &path)
-{
- UStringVector parts;
- SplitPathToParts(path, parts);
- int level = 0;
- FOR_VECTOR(i, parts)
- {
- const UString &s = parts[i];
- if (s.IsEmpty())
- continue;
- if (s == L".")
- continue;
- if (s == L"..")
- {
- if (level <= 0)
- return false;
- level--;
- }
- else
- level++;
- }
- return level > 0;
-}
-
-#endif
-
-
-STDMETHODIMP CArchiveExtractCallback::GetStream(UInt32 index, ISequentialOutStream **outStream, Int32 askExtractMode)
-{
- COM_TRY_BEGIN
-
- *outStream = 0;
-
- #ifndef _SFX
- if (_hashStream)
- _hashStreamSpec->ReleaseStream();
- _hashStreamWasUsed = false;
- #endif
-
- _outFileStream.Release();
-
- _encrypted = false;
- _isSplit = false;
- _isAltStream = false;
- _curSize = 0;
- _curSizeDefined = false;
- _index = index;
-
- UString fullPath;
-
- IInArchive *archive = _arc->Archive;
- RINOK(_arc->GetItemPath(index, fullPath));
- RINOK(Archive_IsItem_Folder(archive, index, _fi.IsDir));
-
- _filePath = fullPath;
-
- {
- NCOM::CPropVariant prop;
- RINOK(archive->GetProperty(index, kpidPosition, &prop));
- if (prop.vt != VT_EMPTY)
- {
- if (prop.vt != VT_UI8)
- return E_FAIL;
- _position = prop.uhVal.QuadPart;
- _isSplit = true;
- }
- }
-
- #ifdef SUPPORT_LINKS
-
- bool isHardLink = false;
- bool isJunction = false;
- bool isRelative = false;
-
- UString linkPath;
- // RINOK(Archive_GetItemBoolProp(archive, index, kpidIsHardLink, isHardLink));
- // if (isHardLink)
- {
- NCOM::CPropVariant prop;
- RINOK(archive->GetProperty(index, kpidHardLink, &prop));
- if (prop.vt == VT_BSTR)
- {
- isHardLink = true;
- linkPath = prop.bstrVal;
- isRelative = false; // TAR: hard links are from root folder of archive
- }
- else if (prop.vt == VT_EMPTY)
- {
- // linkPath.Empty();
- }
- else
- return E_FAIL;
- }
- {
- NCOM::CPropVariant prop;
- RINOK(archive->GetProperty(index, kpidSymLink, &prop));
- if (prop.vt == VT_BSTR)
- {
- isHardLink = false;
- linkPath = prop.bstrVal;
- isRelative = true; // TAR: symbolic links are relative
- }
- else if (prop.vt == VT_EMPTY)
- {
- // linkPath.Empty();
- }
- else
- return E_FAIL;
- }
-
- bool isOkReparse = false;
-
- if (linkPath.IsEmpty() && _arc->GetRawProps)
- {
- const void *data;
- UInt32 dataSize;
- UInt32 propType;
- _arc->GetRawProps->GetRawProp(_index, kpidNtReparse, &data, &dataSize, &propType);
- if (dataSize != 0)
- {
- if (propType != NPropDataType::kRaw)
- return E_FAIL;
- UString s;
- CReparseAttr reparse;
- isOkReparse = reparse.Parse((const Byte *)data, dataSize);
- if (isOkReparse)
- {
- isHardLink = false;
- linkPath = reparse.GetPath();
- isJunction = reparse.IsMountPoint();
- isRelative = reparse.IsRelative();
- #ifndef _WIN32
- linkPath.Replace(WCHAR_PATH_SEPARATOR, '/', );
- #endif
- }
- }
- }
-
- if (!linkPath.IsEmpty())
- {
- #ifdef _WIN32
- linkPath.Replace('/', WCHAR_PATH_SEPARATOR);
- #endif
-
- for (;;)
- // while (NName::IsAbsolutePath(linkPath))
- {
- unsigned n = NName::GetRootPrefixSize(linkPath);
- if (n == 0)
- break;
- isRelative = false;
- linkPath.DeleteFrontal(n);
- }
- }
-
- if (!linkPath.IsEmpty() && !isRelative && _removePathParts.Size() != 0)
- {
- UStringVector pathParts;
- SplitPathToParts(linkPath, pathParts);
- bool badPrefix = false;
- FOR_VECTOR (i, _removePathParts)
- {
- if (CompareFileNames(_removePathParts[i], pathParts[i]) != 0)
- {
- badPrefix = true;
- break;
- }
- }
- if (!badPrefix)
- pathParts.DeleteFrontal(_removePathParts.Size());
- linkPath = MakePathNameFromParts(pathParts);
- }
-
- #endif
-
- RINOK(Archive_GetItemBoolProp(archive, index, kpidEncrypted, _encrypted));
-
- RINOK(GetUnpackSize());
-
- RINOK(Archive_IsItem_AltStream(archive, index, _isAltStream));
-
- if (!_ntOptions.AltStreams.Val && _isAltStream)
- return S_OK;
-
- if (_wildcardCensor)
- {
- if (!_wildcardCensor->CheckPath(_isAltStream, fullPath, !_fi.IsDir))
- return S_OK;
- }
-
-
- UStringVector pathParts;
-
- if (_use_baseParentFolder_mode)
- {
- int baseParent = _baseParentFolder;
- if (_pathMode == NExtract::NPathMode::kFullPaths ||
- _pathMode == NExtract::NPathMode::kAbsPaths)
- baseParent = -1;
- RINOK(_arc->GetItemPathToParent(index, baseParent, pathParts));
- if (_pathMode == NExtract::NPathMode::kNoPaths && !pathParts.IsEmpty())
- pathParts.DeleteFrontal(pathParts.Size() - 1);
- }
- else
- {
- SplitPathToParts(fullPath, pathParts);
-
- if (pathParts.IsEmpty())
- return E_FAIL;
- unsigned numRemovePathParts = 0;
-
- switch (_pathMode)
- {
- case NExtract::NPathMode::kCurPaths:
- {
- bool badPrefix = false;
- if (pathParts.Size() <= _removePathParts.Size())
- badPrefix = true;
- else
- {
- FOR_VECTOR (i, _removePathParts)
- {
- if (!_removePathParts[i].IsEqualToNoCase(pathParts[i]))
- {
- badPrefix = true;
- break;
- }
- }
- }
- if (badPrefix)
- {
- if (askExtractMode == NArchive::NExtract::NAskMode::kExtract && !_testMode)
- return E_FAIL;
- }
- else
- numRemovePathParts = _removePathParts.Size();
- break;
- }
- case NExtract::NPathMode::kNoPaths:
- {
- numRemovePathParts = pathParts.Size() - 1;
- break;
- }
- /*
- case NExtract::NPathMode::kFullPaths:
- case NExtract::NPathMode::kAbsPaths:
- break;
- */
- }
-
- pathParts.DeleteFrontal(numRemovePathParts);
- }
-
- #ifndef _SFX
-
- if (ExtractToStreamCallback)
- {
- if (!GetProp)
- {
- GetProp_Spec = new CGetProp;
- GetProp = GetProp_Spec;
- }
- GetProp_Spec->Arc = _arc;
- GetProp_Spec->IndexInArc = index;
- GetProp_Spec->Name = MakePathNameFromParts(pathParts);
-
- return ExtractToStreamCallback->GetStream7(GetProp_Spec->Name, _fi.IsDir, outStream, askExtractMode, GetProp);
- }
-
- #endif
-
- CMyComPtr<ISequentialOutStream> outStreamLoc;
-
-if (askExtractMode == NArchive::NExtract::NAskMode::kExtract && !_testMode)
-{
- if (_stdOutMode)
- {
- outStreamLoc = new CStdOutFileStream;
- }
- else
- {
- {
- NCOM::CPropVariant prop;
- RINOK(archive->GetProperty(index, kpidAttrib, &prop));
- if (prop.vt == VT_UI4)
- {
- _fi.Attrib = prop.ulVal;
- _fi.AttribDefined = true;
- }
- else if (prop.vt == VT_EMPTY)
- _fi.AttribDefined = false;
- else
- return E_FAIL;
- }
-
- RINOK(GetTime(index, kpidCTime, _fi.CTime, _fi.CTimeDefined));
- RINOK(GetTime(index, kpidATime, _fi.ATime, _fi.ATimeDefined));
- RINOK(GetTime(index, kpidMTime, _fi.MTime, _fi.MTimeDefined));
-
- bool isAnti = false;
- RINOK(_arc->IsItemAnti(index, isAnti));
-
- bool replace = _isAltStream ?
- _ntOptions.ReplaceColonForAltStream :
- !_ntOptions.WriteToAltStreamIfColon;
-
- if (_pathMode != NExtract::NPathMode::kAbsPaths)
- MakeCorrectPath(_directoryPath.IsEmpty(), pathParts, replace);
- Correct_IfEmptyLastPart(pathParts);
- UString processedPath = MakePathNameFromParts(pathParts);
-
- if (!isAnti)
- {
- if (!_fi.IsDir)
- {
- if (!pathParts.IsEmpty())
- pathParts.DeleteBack();
- }
-
- if (!pathParts.IsEmpty())
- {
- FString fullPathNew;
- CreateComplexDirectory(pathParts, fullPathNew);
- if (_fi.IsDir)
- {
- _extractedFolderPaths.Add(fullPathNew);
- _extractedFolderIndices.Add(index);
- SetDirTime(fullPathNew,
- (WriteCTime && _fi.CTimeDefined) ? &_fi.CTime : NULL,
- (WriteATime && _fi.ATimeDefined) ? &_fi.ATime : NULL,
- (WriteMTime && _fi.MTimeDefined) ? &_fi.MTime : (_arc->MTimeDefined ? &_arc->MTime : NULL));
- }
- }
- }
-
-
- FString fullProcessedPath = us2fs(processedPath);
- if (_pathMode != NExtract::NPathMode::kAbsPaths ||
- !NName::IsAbsolutePath(processedPath))
- fullProcessedPath = _directoryPath + fullProcessedPath;
-
- if (_fi.IsDir)
- {
- _diskFilePath = fullProcessedPath;
- if (isAnti)
- RemoveDir(_diskFilePath);
- #ifdef SUPPORT_LINKS
- if (linkPath.IsEmpty())
- #endif
- return S_OK;
- }
- else if (!_isSplit)
- {
- NFind::CFileInfo fileInfo;
- if (fileInfo.Find(fullProcessedPath))
- {
- switch (_overwriteMode)
- {
- case NExtract::NOverwriteMode::kSkip:
- return S_OK;
- case NExtract::NOverwriteMode::kAsk:
- {
- int slashPos = fullProcessedPath.ReverseFind(FTEXT('/'));
- #ifdef _WIN32
- int slash1Pos = fullProcessedPath.ReverseFind(FTEXT('\\'));
- slashPos = MyMax(slashPos, slash1Pos);
- #endif
- FString realFullProcessedPath = fullProcessedPath.Left(slashPos + 1) + fileInfo.Name;
-
- Int32 overwiteResult;
- RINOK(_extractCallback2->AskOverwrite(
- fs2us(realFullProcessedPath), &fileInfo.MTime, &fileInfo.Size, fullPath,
- _fi.MTimeDefined ? &_fi.MTime : NULL,
- _curSizeDefined ? &_curSize : NULL,
- &overwiteResult))
-
- switch (overwiteResult)
- {
- case NOverwriteAnswer::kCancel: return E_ABORT;
- case NOverwriteAnswer::kNo: return S_OK;
- case NOverwriteAnswer::kNoToAll: _overwriteMode = NExtract::NOverwriteMode::kSkip; return S_OK;
- case NOverwriteAnswer::kYes: break;
- case NOverwriteAnswer::kYesToAll: _overwriteMode = NExtract::NOverwriteMode::kOverwrite; break;
- case NOverwriteAnswer::kAutoRename: _overwriteMode = NExtract::NOverwriteMode::kRename; break;
- default:
- return E_FAIL;
- }
- }
- }
- if (_overwriteMode == NExtract::NOverwriteMode::kRename)
- {
- if (!AutoRenamePath(fullProcessedPath))
- {
- RINOK(SendMessageError(kCantAutoRename, fullProcessedPath));
- return E_FAIL;
- }
- }
- else if (_overwriteMode == NExtract::NOverwriteMode::kRenameExisting)
- {
- FString existPath = fullProcessedPath;
- if (!AutoRenamePath(existPath))
- {
- RINOK(SendMessageError(kCantAutoRename, fullProcessedPath));
- return E_FAIL;
- }
- // MyMoveFile can raname folders. So it's OK to use it folders too
- if (!MyMoveFile(fullProcessedPath, existPath))
- {
- RINOK(SendMessageError(kCantRenameFile, fullProcessedPath));
- return E_FAIL;
- }
- }
- else
- {
- if (fileInfo.IsDir())
- {
- // do we need to delete all files in folder?
- if (!RemoveDir(fullProcessedPath))
- {
- RINOK(SendMessageError(kCantDeleteOutputDir, fullProcessedPath));
- return S_OK;
- }
- }
- else if (!DeleteFileAlways(fullProcessedPath))
- {
- RINOK(SendMessageError(kCantDeleteOutputFile, fullProcessedPath));
- return S_OK;
- // return E_FAIL;
- }
- }
- }
- }
- _diskFilePath = fullProcessedPath;
-
-
- if (!isAnti)
- {
- #ifdef SUPPORT_LINKS
-
- if (!linkPath.IsEmpty())
- {
- #ifndef UNDER_CE
-
- UString relatPath;
- if (isRelative)
- relatPath = GetDirPrefixOf(_filePath);
- relatPath += linkPath;
-
- if (!IsSafePath(relatPath))
- {
- RINOK(SendMessageError("Dangerous link path was ignored", us2fs(relatPath)));
- }
- else
- {
- FString existPath;
- if (isHardLink || !isRelative)
- {
- if (!NName::GetFullPath(_directoryPathFull, us2fs(relatPath), existPath))
- {
- RINOK(SendMessageError("Incorrect path", us2fs(relatPath)));
- }
- }
- else
- {
- existPath = us2fs(linkPath);
- }
-
- if (!existPath.IsEmpty())
- {
- if (isHardLink)
- {
- if (!MyCreateHardLink(fullProcessedPath, existPath))
- {
- RINOK(SendMessageError2("Can not create hard link", fullProcessedPath, existPath));
- // return S_OK;
- }
- }
- else if (_ntOptions.SymLinks.Val)
- {
- // bool isSymLink = true; // = false for junction
- if (_fi.IsDir && !isRelative)
- {
- // if it's before Vista we use Junction Point
- // isJunction = true;
- // convertToAbs = true;
- }
-
- CByteBuffer data;
- if (FillLinkData(data, fs2us(existPath), !isJunction))
- {
- CReparseAttr attr;
- if (!attr.Parse(data, data.Size()))
- {
- return E_FAIL; // "Internal conversion error";
- }
-
- if (!NFile::NIO::SetReparseData(fullProcessedPath, _fi.IsDir, data, (DWORD)data.Size()))
- {
- RINOK(SendMessageError("Can not set reparse data", fullProcessedPath));
- }
- }
- }
- }
- }
-
- #endif
- }
- else
- #endif // SUPPORT_LINKS
- {
- bool needWriteFile = true;
-
- #ifdef SUPPORT_LINKS
- if (!_hardLinks.IDs.IsEmpty())
- {
- CHardLinkNode h;
- bool defined;
- RINOK(Archive_Get_HardLinkNode(archive, index, h, defined));
- if (defined)
- {
- {
- int linkIndex = _hardLinks.IDs.FindInSorted2(h);
- if (linkIndex >= 0)
- {
- FString &hl = _hardLinks.Links[linkIndex];
- if (hl.IsEmpty())
- hl = fullProcessedPath;
- else
- {
- if (!MyCreateHardLink(fullProcessedPath, hl))
- {
- RINOK(SendMessageError2("Can not create hard link", fullProcessedPath, hl));
- return S_OK;
- }
- needWriteFile = false;
- }
- }
- }
- }
- }
- #endif
-
- if (needWriteFile)
- {
- _outFileStreamSpec = new COutFileStream;
- CMyComPtr<ISequentialOutStream> outStreamLoc(_outFileStreamSpec);
- if (!_outFileStreamSpec->Open(fullProcessedPath, _isSplit ? OPEN_ALWAYS: CREATE_ALWAYS))
- {
- // if (::GetLastError() != ERROR_FILE_EXISTS || !isSplit)
- {
- RINOK(SendMessageError("Can not open output file ", fullProcessedPath));
- return S_OK;
- }
- }
- if (_isSplit)
- {
- RINOK(_outFileStreamSpec->Seek(_position, STREAM_SEEK_SET, NULL));
- }
- _outFileStream = outStreamLoc;
- }
- }
- }
-
- outStreamLoc = _outFileStream;
- }
-}
-
- #ifndef _SFX
-
- if (_hashStream)
- {
- if (askExtractMode == NArchive::NExtract::NAskMode::kExtract ||
- askExtractMode == NArchive::NExtract::NAskMode::kTest)
- {
- _hashStreamSpec->SetStream(outStreamLoc);
- outStreamLoc = _hashStream;
- _hashStreamSpec->Init(true);
- _hashStreamWasUsed = true;
- }
- }
-
- #endif
-
- if (outStreamLoc)
- *outStream = outStreamLoc.Detach();
- return S_OK;
- COM_TRY_END
-}
-
-STDMETHODIMP CArchiveExtractCallback::PrepareOperation(Int32 askExtractMode)
-{
- COM_TRY_BEGIN
-
- #ifndef _SFX
- if (ExtractToStreamCallback)
- return ExtractToStreamCallback->PrepareOperation7(askExtractMode);
- #endif
-
- _extractMode = false;
- switch (askExtractMode)
- {
- case NArchive::NExtract::NAskMode::kExtract:
- if (_testMode)
- askExtractMode = NArchive::NExtract::NAskMode::kTest;
- else
- _extractMode = true;
- break;
- };
- return _extractCallback2->PrepareOperation(_filePath, _fi.IsDir,
- askExtractMode, _isSplit ? &_position: 0);
- COM_TRY_END
-}
-
-STDMETHODIMP CArchiveExtractCallback::SetOperationResult(Int32 operationResult)
-{
- COM_TRY_BEGIN
-
- #ifndef _SFX
- if (ExtractToStreamCallback)
- return ExtractToStreamCallback->SetOperationResult7(operationResult, _encrypted);
- #endif
-
- #ifndef _SFX
-
- if (_hashStreamWasUsed)
- {
- _hashStreamSpec->_hash->Final(_fi.IsDir, _isAltStream, _filePath);
- _curSize = _hashStreamSpec->GetSize();
- _curSizeDefined = true;
- _hashStreamSpec->ReleaseStream();
- _hashStreamWasUsed = false;
- }
-
- #endif
-
- if (_outFileStream)
- {
- _outFileStreamSpec->SetTime(
- (WriteCTime && _fi.CTimeDefined) ? &_fi.CTime : NULL,
- (WriteATime && _fi.ATimeDefined) ? &_fi.ATime : NULL,
- (WriteMTime && _fi.MTimeDefined) ? &_fi.MTime : (_arc->MTimeDefined ? &_arc->MTime : NULL));
- _curSize = _outFileStreamSpec->ProcessedSize;
- _curSizeDefined = true;
- RINOK(_outFileStreamSpec->Close());
- _outFileStream.Release();
- }
-
- #ifdef _USE_SECURITY_CODE
- if (_ntOptions.NtSecurity.Val && _arc->GetRawProps)
- {
- const void *data;
- UInt32 dataSize;
- UInt32 propType;
- _arc->GetRawProps->GetRawProp(_index, kpidNtSecure, &data, &dataSize, &propType);
- if (dataSize != 0)
- {
- if (propType != NPropDataType::kRaw)
- return E_FAIL;
- if (CheckNtSecure((const Byte *)data, dataSize))
- {
- SECURITY_INFORMATION securInfo = DACL_SECURITY_INFORMATION | GROUP_SECURITY_INFORMATION | OWNER_SECURITY_INFORMATION;
- if (_saclEnabled)
- securInfo |= SACL_SECURITY_INFORMATION;
- ::SetFileSecurityW(fs2us(_diskFilePath), securInfo, (PSECURITY_DESCRIPTOR)(void *)data);
- }
- }
- }
- #endif
-
- if (!_curSizeDefined)
- GetUnpackSize();
- if (_curSizeDefined)
- {
- if (_isAltStream)
- AltStreams_UnpackSize += _curSize;
- else
- UnpackSize += _curSize;
- }
-
- if (_fi.IsDir)
- NumFolders++;
- else if (_isAltStream)
- NumAltStreams++;
- else
- NumFiles++;
-
- if (_extractMode && _fi.AttribDefined)
- SetFileAttrib(_diskFilePath, _fi.Attrib);
- RINOK(_extractCallback2->SetOperationResult(operationResult, _encrypted));
- return S_OK;
- COM_TRY_END
-}
-
-/*
-STDMETHODIMP CArchiveExtractCallback::GetInStream(
- const wchar_t *name, ISequentialInStream **inStream)
-{
- COM_TRY_BEGIN
- CInFileStream *inFile = new CInFileStream;
- CMyComPtr<ISequentialInStream> inStreamTemp = inFile;
- if (!inFile->Open(_srcDirectoryPrefix + name))
- return ::GetLastError();
- *inStream = inStreamTemp.Detach();
- return S_OK;
- COM_TRY_END
-}
-*/
-
-STDMETHODIMP CArchiveExtractCallback::CryptoGetTextPassword(BSTR *password)
-{
- COM_TRY_BEGIN
- if (!_cryptoGetTextPassword)
- {
- RINOK(_extractCallback2.QueryInterface(IID_ICryptoGetTextPassword,
- &_cryptoGetTextPassword));
- }
- return _cryptoGetTextPassword->CryptoGetTextPassword(password);
- COM_TRY_END
-}
-
-
-struct CExtrRefSortPair
-{
- int Len;
- int Index;
-
- int Compare(const CExtrRefSortPair &a) const;
-};
-
-#define RINOZ(x) { int __tt = (x); if (__tt != 0) return __tt; }
-
-int CExtrRefSortPair::Compare(const CExtrRefSortPair &a) const
-{
- RINOZ(-MyCompare(Len, a.Len));
- return MyCompare(Index, a.Index);
-}
-
-static int GetNumSlashes(const FChar *s)
-{
- for (int numSlashes = 0;;)
- {
- FChar c = *s++;
- if (c == 0)
- return numSlashes;
- if (
- #ifdef _WIN32
- c == FTEXT('\\') ||
- #endif
- c == FTEXT('/'))
- numSlashes++;
- }
-}
-
-HRESULT CArchiveExtractCallback::SetDirsTimes()
-{
- CRecordVector<CExtrRefSortPair> pairs;
- pairs.ClearAndSetSize(_extractedFolderPaths.Size());
- unsigned i;
-
- for (i = 0; i < _extractedFolderPaths.Size(); i++)
- {
- CExtrRefSortPair &pair = pairs[i];
- pair.Index = i;
- pair.Len = GetNumSlashes(_extractedFolderPaths[i]);
- }
-
- pairs.Sort2();
-
- for (i = 0; i < pairs.Size(); i++)
- {
- int pairIndex = pairs[i].Index;
- int index = _extractedFolderIndices[pairIndex];
-
- FILETIME CTime;
- FILETIME ATime;
- FILETIME MTime;
-
- bool CTimeDefined;
- bool ATimeDefined;
- bool MTimeDefined;
-
- RINOK(GetTime(index, kpidCTime, CTime, CTimeDefined));
- RINOK(GetTime(index, kpidATime, ATime, ATimeDefined));
- RINOK(GetTime(index, kpidMTime, MTime, MTimeDefined));
-
- // printf("\n%S", _extractedFolderPaths[pairIndex]);
- SetDirTime(_extractedFolderPaths[pairIndex],
- (WriteCTime && CTimeDefined) ? &CTime : NULL,
- (WriteATime && ATimeDefined) ? &ATime : NULL,
- (WriteMTime && MTimeDefined) ? &MTime : (_arc->MTimeDefined ? &_arc->MTime : NULL));
- }
- return S_OK;
-}