mirror of
https://github.com/Xevion/easy7zip.git
synced 2026-01-31 20:24:05 -06:00
9.34
This commit is contained in:
committed by
Kornel Lesiński
parent
83f8ddcc5b
commit
f08f4dcc3c
Executable → Regular
+146
-59
@@ -2,79 +2,157 @@
|
||||
|
||||
#include "StdAfx.h"
|
||||
|
||||
#include "Common/ComTry.h"
|
||||
#include "../../../Common/ComTry.h"
|
||||
|
||||
#include "Windows/FileDir.h"
|
||||
#include "../../../Windows/FileDir.h"
|
||||
|
||||
#include "../../Common/FileStreams.h"
|
||||
#include "../../Common/LimitedStreams.h"
|
||||
|
||||
#include "../../Compress/CopyCoder.h"
|
||||
|
||||
#include "../Common/WorkDir.h"
|
||||
|
||||
#include "Agent.h"
|
||||
|
||||
using namespace NWindows;
|
||||
using namespace NFile;
|
||||
using namespace NDirectory;
|
||||
using namespace NDir;
|
||||
|
||||
void CAgentFolder::GetPathParts(UStringVector &pathParts)
|
||||
{
|
||||
_proxyFolderItem->GetPathParts(pathParts);
|
||||
if (_proxyArchive2)
|
||||
_proxyArchive2->GetPathParts(_proxyFolderItem, pathParts);
|
||||
else
|
||||
_proxyArchive->GetPathParts(_proxyFolderItem, pathParts);
|
||||
}
|
||||
|
||||
static bool DeleteEmptyFolderAndEmptySubFolders(const FString &path)
|
||||
{
|
||||
NFind::CFileInfo fileInfo;
|
||||
FString pathPrefix = path + FCHAR_PATH_SEPARATOR;
|
||||
{
|
||||
NFind::CEnumerator enumerator(pathPrefix + FCHAR_ANY_MASK);
|
||||
while (enumerator.Next(fileInfo))
|
||||
{
|
||||
if (fileInfo.IsDir())
|
||||
if (!DeleteEmptyFolderAndEmptySubFolders(pathPrefix + fileInfo.Name))
|
||||
return false;
|
||||
}
|
||||
}
|
||||
/*
|
||||
// we don't need clear readonly for folders
|
||||
if (!SetFileAttrib(path, 0))
|
||||
return false;
|
||||
*/
|
||||
return RemoveDir(path);
|
||||
}
|
||||
|
||||
|
||||
HRESULT CAgentFolder::CommonUpdateOperation(
|
||||
AGENT_OP operation,
|
||||
bool moveMode,
|
||||
const wchar_t *newItemName,
|
||||
const NUpdateArchive::CActionSet *actionSet,
|
||||
const UINT32 *indices, UINT32 numItems,
|
||||
const UInt32 *indices, UInt32 numItems,
|
||||
IFolderArchiveUpdateCallback *updateCallback100)
|
||||
{
|
||||
CWorkDirTempFile tempFile;
|
||||
RINOK(tempFile.CreateTempFile(us2fs(_agentSpec->_archiveFilePath)));
|
||||
if (!_agentSpec->CanUpdate())
|
||||
return E_NOTIMPL;
|
||||
|
||||
/*
|
||||
if (SetOutProperties(anOutArchive, aCompressionInfo.Method) != S_OK)
|
||||
return NFileOperationReturnCode::kError;
|
||||
*/
|
||||
|
||||
////////////////////////////
|
||||
// Save FolderItem;
|
||||
|
||||
UStringVector pathParts;
|
||||
GetPathParts(pathParts);
|
||||
|
||||
HRESULT result;
|
||||
switch (operation)
|
||||
{
|
||||
case AGENT_OP_Delete:
|
||||
result = _agentSpec->DeleteItems(tempFile.OutStream, indices, numItems, updateCallback100);
|
||||
break;
|
||||
case AGENT_OP_CreateFolder:
|
||||
result = _agentSpec->CreateFolder(tempFile.OutStream, newItemName, updateCallback100);
|
||||
break;
|
||||
case AGENT_OP_Rename:
|
||||
result = _agentSpec->RenameItem(tempFile.OutStream, indices, numItems, newItemName, updateCallback100);
|
||||
break;
|
||||
case AGENT_OP_CopyFromFile:
|
||||
result = _agentSpec->UpdateOneFile(tempFile.OutStream, indices, numItems, newItemName, updateCallback100);
|
||||
break;
|
||||
case AGENT_OP_Uni:
|
||||
{
|
||||
Byte actionSetByte[NUpdateArchive::NPairState::kNumValues];
|
||||
for (int i = 0; i < NUpdateArchive::NPairState::kNumValues; i++)
|
||||
actionSetByte[i] = (Byte)actionSet->StateActions[i];
|
||||
result = _agentSpec->DoOperation2(tempFile.OutStream, actionSetByte, NULL, updateCallback100);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
return E_FAIL;
|
||||
}
|
||||
|
||||
RINOK(result);
|
||||
FStringVector requestedPaths;
|
||||
FStringVector processedPaths;
|
||||
|
||||
CWorkDirTempFile tempFile;
|
||||
RINOK(tempFile.CreateTempFile(us2fs(_agentSpec->_archiveFilePath)));
|
||||
{
|
||||
CMyComPtr<IOutStream> tailStream;
|
||||
const CArc &arc = *_agentSpec->_archiveLink.GetArc();
|
||||
|
||||
if (arc.ArcStreamOffset == 0)
|
||||
tailStream = tempFile.OutStream;
|
||||
else
|
||||
{
|
||||
if (arc.Offset < 0)
|
||||
return E_NOTIMPL;
|
||||
RINOK(arc.InStream->Seek(0, STREAM_SEEK_SET, NULL));
|
||||
RINOK(NCompress::CopyStream_ExactSize(arc.InStream, tempFile.OutStream, arc.ArcStreamOffset, NULL));
|
||||
CTailOutStream *tailStreamSpec = new CTailOutStream;
|
||||
tailStream = tailStreamSpec;
|
||||
tailStreamSpec->Stream = tempFile.OutStream;
|
||||
tailStreamSpec->Offset = arc.ArcStreamOffset;
|
||||
tailStreamSpec->Init();
|
||||
}
|
||||
|
||||
HRESULT result;
|
||||
|
||||
switch (operation)
|
||||
{
|
||||
case AGENT_OP_Delete:
|
||||
result = _agentSpec->DeleteItems(tailStream, indices, numItems, updateCallback100);
|
||||
break;
|
||||
case AGENT_OP_CreateFolder:
|
||||
result = _agentSpec->CreateFolder(tailStream, newItemName, updateCallback100);
|
||||
break;
|
||||
case AGENT_OP_Rename:
|
||||
result = _agentSpec->RenameItem(tailStream, indices, numItems, newItemName, updateCallback100);
|
||||
break;
|
||||
case AGENT_OP_CopyFromFile:
|
||||
result = _agentSpec->UpdateOneFile(tailStream, indices, numItems, newItemName, updateCallback100);
|
||||
break;
|
||||
case AGENT_OP_Uni:
|
||||
{
|
||||
Byte actionSetByte[NUpdateArchive::NPairState::kNumValues];
|
||||
for (int i = 0; i < NUpdateArchive::NPairState::kNumValues; i++)
|
||||
actionSetByte[i] = (Byte)actionSet->StateActions[i];
|
||||
result = _agentSpec->DoOperation2(
|
||||
moveMode ? &requestedPaths : NULL,
|
||||
moveMode ? &processedPaths : NULL,
|
||||
tailStream, actionSetByte, NULL, updateCallback100);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
return E_FAIL;
|
||||
}
|
||||
|
||||
RINOK(result);
|
||||
}
|
||||
|
||||
_agentSpec->KeepModeForNextOpen();
|
||||
_agentSpec->Close();
|
||||
|
||||
// before 9.26: if there was error for MoveToOriginal archive was closed.
|
||||
// now: we reopen archive after close
|
||||
|
||||
// m_FolderItem = NULL;
|
||||
|
||||
RINOK(tempFile.MoveToOriginal(true));
|
||||
HRESULT res = tempFile.MoveToOriginal(true);
|
||||
|
||||
// RINOK(res);
|
||||
if (res == S_OK)
|
||||
{
|
||||
if (moveMode)
|
||||
{
|
||||
unsigned i;
|
||||
for (i = 0; i < processedPaths.Size(); i++)
|
||||
{
|
||||
DeleteFileAlways(processedPaths[i]);
|
||||
}
|
||||
for (i = 0; i < requestedPaths.Size(); i++)
|
||||
{
|
||||
const FString &fs = requestedPaths[i];
|
||||
if (NFind::DoesDirExist(fs))
|
||||
DeleteEmptyFolderAndEmptySubFolders(fs);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
{
|
||||
CMyComPtr<IArchiveOpenCallback> openCallback;
|
||||
@@ -85,12 +163,11 @@ HRESULT CAgentFolder::CommonUpdateOperation(
|
||||
RINOK(_agentSpec->ReOpen(openCallback));
|
||||
}
|
||||
|
||||
////////////////////////////
|
||||
// Restore FolderItem;
|
||||
|
||||
CMyComPtr<IFolderFolder> archiveFolder;
|
||||
RINOK(_agentSpec->BindToRootFolder(&archiveFolder));
|
||||
for (int i = 0; i < pathParts.Size(); i++)
|
||||
FOR_VECTOR (i, pathParts)
|
||||
{
|
||||
CMyComPtr<IFolderFolder> newFolder;
|
||||
archiveFolder->BindToFolder(pathParts[i], &newFolder);
|
||||
@@ -105,15 +182,16 @@ HRESULT CAgentFolder::CommonUpdateOperation(
|
||||
RINOK(archiveFolderInternal->GetAgentFolder(&agentFolder));
|
||||
_proxyFolderItem = agentFolder->_proxyFolderItem;
|
||||
_proxyArchive = agentFolder->_proxyArchive;
|
||||
_proxyArchive2 = agentFolder->_proxyArchive2;
|
||||
_parentFolder = agentFolder->_parentFolder;
|
||||
|
||||
return S_OK;
|
||||
return res;
|
||||
}
|
||||
|
||||
STDMETHODIMP CAgentFolder::CopyFrom(
|
||||
STDMETHODIMP CAgentFolder::CopyFrom(Int32 moveMode,
|
||||
const wchar_t *fromFolderPath, // test it
|
||||
const wchar_t **itemsPaths,
|
||||
UINT32 numItems,
|
||||
UInt32 numItems,
|
||||
IProgress *progress)
|
||||
{
|
||||
COM_TRY_BEGIN
|
||||
@@ -126,8 +204,9 @@ STDMETHODIMP CAgentFolder::CopyFrom(
|
||||
{
|
||||
RINOK(_agentSpec->SetFiles(fromFolderPath, itemsPaths, numItems));
|
||||
RINOK(_agentSpec->SetFolder(this));
|
||||
return CommonUpdateOperation(AGENT_OP_Uni, NULL,
|
||||
&NUpdateArchive::kAddActionSet, 0, 0, updateCallback100);
|
||||
return CommonUpdateOperation(AGENT_OP_Uni, (moveMode != 0), NULL,
|
||||
&NUpdateArchive::k_ActionSet_Add,
|
||||
0, 0, updateCallback100);
|
||||
}
|
||||
catch(const UString &s)
|
||||
{
|
||||
@@ -150,8 +229,8 @@ STDMETHODIMP CAgentFolder::CopyFromFile(UInt32 destIndex, const wchar_t *itemPat
|
||||
try
|
||||
{
|
||||
RINOK(_agentSpec->SetFolder(this));
|
||||
return CommonUpdateOperation(AGENT_OP_CopyFromFile, itemPath,
|
||||
&NUpdateArchive::kAddActionSet,
|
||||
return CommonUpdateOperation(AGENT_OP_CopyFromFile, false, itemPath,
|
||||
&NUpdateArchive::k_ActionSet_Add,
|
||||
&indices.Front(), indices.Size(), updateCallback100);
|
||||
}
|
||||
catch(const UString &s)
|
||||
@@ -162,7 +241,7 @@ STDMETHODIMP CAgentFolder::CopyFromFile(UInt32 destIndex, const wchar_t *itemPat
|
||||
COM_TRY_END
|
||||
}
|
||||
|
||||
STDMETHODIMP CAgentFolder::Delete(const UINT32 *indices, UINT32 numItems, IProgress *progress)
|
||||
STDMETHODIMP CAgentFolder::Delete(const UInt32 *indices, UInt32 numItems, IProgress *progress)
|
||||
{
|
||||
COM_TRY_BEGIN
|
||||
RINOK(_agentSpec->SetFolder(this));
|
||||
@@ -173,16 +252,24 @@ STDMETHODIMP CAgentFolder::Delete(const UINT32 *indices, UINT32 numItems, IProgr
|
||||
RINOK(progressWrapper.QueryInterface(
|
||||
IID_IFolderArchiveUpdateCallback, &updateCallback100));
|
||||
}
|
||||
return CommonUpdateOperation(AGENT_OP_Delete, NULL,
|
||||
&NUpdateArchive::kDeleteActionSet, indices, numItems, updateCallback100);
|
||||
return CommonUpdateOperation(AGENT_OP_Delete, false, NULL,
|
||||
&NUpdateArchive::k_ActionSet_Delete, indices, numItems, updateCallback100);
|
||||
COM_TRY_END
|
||||
}
|
||||
|
||||
STDMETHODIMP CAgentFolder::CreateFolder(const wchar_t *name, IProgress *progress)
|
||||
{
|
||||
COM_TRY_BEGIN
|
||||
if (_proxyFolderItem->FindDirSubItemIndex(name) >= 0)
|
||||
return ERROR_ALREADY_EXISTS;
|
||||
if (_proxyArchive2)
|
||||
{
|
||||
if (_proxyArchive2->IsThere_SubDir(_proxyFolderItem, name))
|
||||
return ERROR_ALREADY_EXISTS;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (_proxyArchive->FindDirSubItemIndex(_proxyFolderItem, name) >= 0)
|
||||
return ERROR_ALREADY_EXISTS;
|
||||
}
|
||||
RINOK(_agentSpec->SetFolder(this));
|
||||
CMyComPtr<IFolderArchiveUpdateCallback> updateCallback100;
|
||||
if (progress)
|
||||
@@ -190,11 +277,11 @@ STDMETHODIMP CAgentFolder::CreateFolder(const wchar_t *name, IProgress *progress
|
||||
CMyComPtr<IProgress> progressWrapper = progress;
|
||||
RINOK(progressWrapper.QueryInterface(IID_IFolderArchiveUpdateCallback, &updateCallback100));
|
||||
}
|
||||
return CommonUpdateOperation(AGENT_OP_CreateFolder, name, NULL, NULL, 0, updateCallback100);
|
||||
return CommonUpdateOperation(AGENT_OP_CreateFolder, false, name, NULL, NULL, 0, updateCallback100);
|
||||
COM_TRY_END
|
||||
}
|
||||
|
||||
STDMETHODIMP CAgentFolder::Rename(UINT32 index, const wchar_t *newName, IProgress *progress)
|
||||
STDMETHODIMP CAgentFolder::Rename(UInt32 index, const wchar_t *newName, IProgress *progress)
|
||||
{
|
||||
COM_TRY_BEGIN
|
||||
CUIntVector indices;
|
||||
@@ -206,7 +293,7 @@ STDMETHODIMP CAgentFolder::Rename(UINT32 index, const wchar_t *newName, IProgres
|
||||
CMyComPtr<IProgress> progressWrapper = progress;
|
||||
RINOK(progressWrapper.QueryInterface(IID_IFolderArchiveUpdateCallback, &updateCallback100));
|
||||
}
|
||||
return CommonUpdateOperation(AGENT_OP_Rename, newName, NULL, &indices.Front(),
|
||||
return CommonUpdateOperation(AGENT_OP_Rename, false, newName, NULL, &indices.Front(),
|
||||
indices.Size(), updateCallback100);
|
||||
COM_TRY_END
|
||||
}
|
||||
@@ -216,7 +303,7 @@ STDMETHODIMP CAgentFolder::CreateFile(const wchar_t * /* name */, IProgress * /*
|
||||
return E_NOTIMPL;
|
||||
}
|
||||
|
||||
STDMETHODIMP CAgentFolder::SetProperty(UINT32 /* index */, PROPID /* propID */,
|
||||
STDMETHODIMP CAgentFolder::SetProperty(UInt32 /* index */, PROPID /* propID */,
|
||||
const PROPVARIANT * /* value */, IProgress * /* progress */)
|
||||
{
|
||||
return E_NOTIMPL;
|
||||
|
||||
Reference in New Issue
Block a user