Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/kornelski/7z.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'CPP/7zip/UI/Agent/ArchiveFolderOut.cpp')
-rw-r--r--[-rwxr-xr-x]CPP/7zip/UI/Agent/ArchiveFolderOut.cpp197
1 files changed, 142 insertions, 55 deletions
diff --git a/CPP/7zip/UI/Agent/ArchiveFolderOut.cpp b/CPP/7zip/UI/Agent/ArchiveFolderOut.cpp
index 656602cb..003f6d98 100755..100644
--- a/CPP/7zip/UI/Agent/ArchiveFolderOut.cpp
+++ b/CPP/7zip/UI/Agent/ArchiveFolderOut.cpp
@@ -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)
+ FStringVector requestedPaths;
+ FStringVector processedPaths;
+
+ CWorkDirTempFile tempFile;
+ RINOK(tempFile.CreateTempFile(us2fs(_agentSpec->_archiveFilePath)));
{
- 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:
+ CMyComPtr<IOutStream> tailStream;
+ const CArc &arc = *_agentSpec->_archiveLink.GetArc();
+
+ if (arc.ArcStreamOffset == 0)
+ tailStream = tempFile.OutStream;
+ else
{
- 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;
+ 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();
}
- default:
- return E_FAIL;
+
+ 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);
}
-
- 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;