summaryrefslogtreecommitdiffstatshomepage
path: root/3rdparty/lzma/CPP/7zip/UI/Common/Update.cpp
diff options
context:
space:
mode:
Diffstat (limited to '3rdparty/lzma/CPP/7zip/UI/Common/Update.cpp')
-rw-r--r--3rdparty/lzma/CPP/7zip/UI/Common/Update.cpp1136
1 files changed, 720 insertions, 416 deletions
diff --git a/3rdparty/lzma/CPP/7zip/UI/Common/Update.cpp b/3rdparty/lzma/CPP/7zip/UI/Common/Update.cpp
index 0db4a87f0d4..27625aebbe4 100644
--- a/3rdparty/lzma/CPP/7zip/UI/Common/Update.cpp
+++ b/3rdparty/lzma/CPP/7zip/UI/Common/Update.cpp
@@ -2,9 +2,10 @@
#include "StdAfx.h"
+// #include <stdio.h>
+
#include "Update.h"
-#include "../../../Common/IntToString.h"
#include "../../../Common/StringConvert.h"
#include "../../../Windows/DLL.h"
@@ -17,6 +18,8 @@
#include "../../Common/FileStreams.h"
#include "../../Common/LimitedStreams.h"
+#include "../../Common/MultiOutStream.h"
+#include "../../Common/StreamUtils.h"
#include "../../Compress/CopyCoder.h"
@@ -30,17 +33,21 @@
#include "TempFiles.h"
#include "UpdateCallback.h"
-static const char *kUpdateIsNotSupoorted =
+static const char * const kUpdateIsNotSupoorted =
"update operations are not supported for this archive";
+static const char * const kUpdateIsNotSupported_MultiVol =
+ "Updating for multivolume archives is not implemented";
+
using namespace NWindows;
using namespace NCOM;
using namespace NFile;
using namespace NDir;
using namespace NName;
-static CFSTR kTempFolderPrefix = FTEXT("7zE");
-
+#ifdef _WIN32
+static CFSTR const kTempFolderPrefix = FTEXT("7zE");
+#endif
void CUpdateErrorInfo::SetFromLastError(const char *message)
{
@@ -55,228 +62,55 @@ HRESULT CUpdateErrorInfo::SetFromLastError(const char *message, const FString &f
return Get_HRESULT_Error();
}
-static bool DeleteEmptyFolderAndEmptySubFolders(const FString &path)
+HRESULT CUpdateErrorInfo::SetFromError_DWORD(const char *message, const FString &fileName, DWORD error)
{
- 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 read-only for folders
- if (!MySetFileAttributes(path, 0))
- return false;
- */
- return RemoveDir(path);
+ Message = message;
+ FileNames.Add(fileName);
+ SystemError = error;
+ return Get_HRESULT_Error();
}
using namespace NUpdateArchive;
-class COutMultiVolStream:
- public IOutStream,
- public CMyUnknownImp
+struct CMultiOutStream_Rec
{
- unsigned _streamIndex; // required stream
- UInt64 _offsetPos; // offset from start of _streamIndex index
- UInt64 _absPos;
- UInt64 _length;
-
- struct CAltStreamInfo
- {
- COutFileStream *StreamSpec;
- CMyComPtr<IOutStream> Stream;
- FString Name;
- UInt64 Pos;
- UInt64 RealSize;
- };
- CObjectVector<CAltStreamInfo> Streams;
-public:
- // CMyComPtr<IArchiveUpdateCallback2> VolumeCallback;
- CRecordVector<UInt64> Sizes;
- FString Prefix;
- CTempFiles *TempFiles;
-
- void Init()
- {
- _streamIndex = 0;
- _offsetPos = 0;
- _absPos = 0;
- _length = 0;
- }
-
- bool SetMTime(const FILETIME *mTime);
- HRESULT Close();
-
- UInt64 GetSize() const { return _length; }
-
- MY_UNKNOWN_IMP1(IOutStream)
-
- STDMETHOD(Write)(const void *data, UInt32 size, UInt32 *processedSize);
- STDMETHOD(Seek)(Int64 offset, UInt32 seekOrigin, UInt64 *newPosition);
- STDMETHOD(SetSize)(UInt64 newSize);
+ CMultiOutStream *Spec;
+ CMyComPtr<IOutStream> Ref;
};
-// static NSynchronization::CCriticalSection g_TempPathsCS;
-
-HRESULT COutMultiVolStream::Close()
+struct CMultiOutStream_Bunch
{
- HRESULT res = S_OK;
- FOR_VECTOR (i, Streams)
- {
- COutFileStream *s = Streams[i].StreamSpec;
- if (s)
- {
- HRESULT res2 = s->Close();
- if (res2 != S_OK)
- res = res2;
- }
- }
- return res;
-}
-
-bool COutMultiVolStream::SetMTime(const FILETIME *mTime)
-{
- bool res = true;
- FOR_VECTOR (i, Streams)
- {
- COutFileStream *s = Streams[i].StreamSpec;
- if (s)
- if (!s->SetMTime(mTime))
- res = false;
- }
- return res;
-}
-
-STDMETHODIMP COutMultiVolStream::Write(const void *data, UInt32 size, UInt32 *processedSize)
-{
- if (processedSize != NULL)
- *processedSize = 0;
- while (size > 0)
+ CObjectVector<CMultiOutStream_Rec> Items;
+
+ HRESULT Destruct()
{
- if (_streamIndex >= Streams.Size())
+ HRESULT hres = S_OK;
+ FOR_VECTOR (i, Items)
{
- CAltStreamInfo altStream;
-
- FChar temp[16];
- ConvertUInt32ToString(_streamIndex + 1, temp);
- FString name = temp;
- while (name.Len() < 3)
- name.InsertAtFront(FTEXT('0'));
- name.Insert(0, Prefix);
- altStream.StreamSpec = new COutFileStream;
- altStream.Stream = altStream.StreamSpec;
- if (!altStream.StreamSpec->Create(name, false))
- return ::GetLastError();
+ CMultiOutStream_Rec &rec = Items[i];
+ if (rec.Ref)
{
- // NSynchronization::CCriticalSectionLock lock(g_TempPathsCS);
- TempFiles->Paths.Add(name);
+ const HRESULT hres2 = rec.Spec->Destruct();
+ if (hres == S_OK)
+ hres = hres2;
}
-
- altStream.Pos = 0;
- altStream.RealSize = 0;
- altStream.Name = name;
- Streams.Add(altStream);
- continue;
}
- CAltStreamInfo &altStream = Streams[_streamIndex];
-
- unsigned index = _streamIndex;
- if (index >= Sizes.Size())
- index = Sizes.Size() - 1;
- UInt64 volSize = Sizes[index];
-
- if (_offsetPos >= volSize)
- {
- _offsetPos -= volSize;
- _streamIndex++;
- continue;
- }
- if (_offsetPos != altStream.Pos)
- {
- // CMyComPtr<IOutStream> outStream;
- // RINOK(altStream.Stream.QueryInterface(IID_IOutStream, &outStream));
- RINOK(altStream.Stream->Seek(_offsetPos, STREAM_SEEK_SET, NULL));
- altStream.Pos = _offsetPos;
- }
-
- UInt32 curSize = (UInt32)MyMin((UInt64)size, volSize - altStream.Pos);
- UInt32 realProcessed;
- RINOK(altStream.Stream->Write(data, curSize, &realProcessed));
- data = (void *)((Byte *)data + realProcessed);
- size -= realProcessed;
- altStream.Pos += realProcessed;
- _offsetPos += realProcessed;
- _absPos += realProcessed;
- if (_absPos > _length)
- _length = _absPos;
- if (_offsetPos > altStream.RealSize)
- altStream.RealSize = _offsetPos;
- if (processedSize != NULL)
- *processedSize += realProcessed;
- if (altStream.Pos == volSize)
- {
- _streamIndex++;
- _offsetPos = 0;
- }
- if (realProcessed == 0 && curSize != 0)
- return E_FAIL;
- break;
+ Items.Clear();
+ return hres;
}
- return S_OK;
-}
-STDMETHODIMP COutMultiVolStream::Seek(Int64 offset, UInt32 seekOrigin, UInt64 *newPosition)
-{
- if (seekOrigin >= 3)
- return STG_E_INVALIDFUNCTION;
- switch (seekOrigin)
- {
- case STREAM_SEEK_SET: _absPos = offset; break;
- case STREAM_SEEK_CUR: _absPos += offset; break;
- case STREAM_SEEK_END: _absPos = _length + offset; break;
- }
- _offsetPos = _absPos;
- if (newPosition != NULL)
- *newPosition = _absPos;
- _streamIndex = 0;
- return S_OK;
-}
-
-STDMETHODIMP COutMultiVolStream::SetSize(UInt64 newSize)
-{
- unsigned i = 0;
- while (i < Streams.Size())
- {
- CAltStreamInfo &altStream = Streams[i++];
- if ((UInt64)newSize < altStream.RealSize)
- {
- RINOK(altStream.Stream->SetSize(newSize));
- altStream.RealSize = newSize;
- break;
- }
- newSize -= altStream.RealSize;
- }
- while (i < Streams.Size())
+ void DisableDeletion()
{
+ FOR_VECTOR (i, Items)
{
- CAltStreamInfo &altStream = Streams.Back();
- altStream.Stream.Release();
- DeleteFileAlways(altStream.Name);
+ CMultiOutStream_Rec &rec = Items[i];
+ if (rec.Ref)
+ rec.Spec->NeedDelete = false;
}
- Streams.DeleteBack();
}
- _offsetPos = _absPos;
- _streamIndex = 0;
- _length = newSize;
- return S_OK;
-}
+};
+
void CArchivePath::ParseFromPath(const UString &path, EArcNameMode mode)
{
@@ -286,29 +120,27 @@ void CArchivePath::ParseFromPath(const UString &path, EArcNameMode mode)
if (mode == k_ArcNameMode_Add)
return;
- if (mode == k_ArcNameMode_Exact)
- {
- BaseExtension.Empty();
- return;
- }
- int dotPos = Name.ReverseFind_Dot();
- if (dotPos < 0)
- return;
- if ((unsigned)dotPos == Name.Len() - 1)
- {
- Name.DeleteBack();
- BaseExtension.Empty();
- return;
- }
- const UString ext = Name.Ptr(dotPos + 1);
- if (BaseExtension.IsEqualTo_NoCase(ext))
+ if (mode != k_ArcNameMode_Exact)
{
- BaseExtension = ext;
- Name.DeleteFrom(dotPos);
+ int dotPos = Name.ReverseFind_Dot();
+ if (dotPos < 0)
+ return;
+ if ((unsigned)dotPos == Name.Len() - 1)
+ Name.DeleteBack();
+ else
+ {
+ const UString ext = Name.Ptr((unsigned)(dotPos + 1));
+ if (BaseExtension.IsEqualTo_NoCase(ext))
+ {
+ BaseExtension = ext;
+ Name.DeleteFrom((unsigned)dotPos);
+ return;
+ }
+ }
}
- else
- BaseExtension.Empty();
+
+ BaseExtension.Empty();
}
UString CArchivePath::GetFinalPath() const
@@ -316,7 +148,7 @@ UString CArchivePath::GetFinalPath() const
UString path = GetPathWithoutExt();
if (!BaseExtension.IsEmpty())
{
- path += L'.';
+ path.Add_Dot();
path += BaseExtension;
}
return path;
@@ -325,9 +157,10 @@ UString CArchivePath::GetFinalPath() const
UString CArchivePath::GetFinalVolPath() const
{
UString path = GetPathWithoutExt();
+ // if BaseExtension is empty, we must ignore VolExtension also.
if (!BaseExtension.IsEmpty())
{
- path += L'.';
+ path.Add_Dot();
path += VolExtension;
}
return path;
@@ -339,17 +172,17 @@ FString CArchivePath::GetTempPath() const
path += us2fs(Name);
if (!BaseExtension.IsEmpty())
{
- path += FTEXT('.');
+ path.Add_Dot();
path += us2fs(BaseExtension);
}
- path.AddAscii(".tmp");
+ path += ".tmp";
path += TempPostfix;
return path;
}
-static const wchar_t *kDefaultArcType = L"7z";
-static const wchar_t *kDefaultArcExt = L"7z";
-static const char *kSFXExtension =
+static const char * const kDefaultArcType = "7z";
+static const char * const kDefaultArcExt = "7z";
+static const char * const kSFXExtension =
#ifdef _WIN32
"exe";
#else
@@ -391,14 +224,14 @@ bool CUpdateOptions::SetArcPath(const CCodecs *codecs, const UString &arcPath)
}
else
{
- const CArcInfoEx &arcInfo = codecs->Formats[formatIndex];
+ const CArcInfoEx &arcInfo = codecs->Formats[(unsigned)formatIndex];
if (!arcInfo.UpdateEnabled)
return false;
typeExt = arcInfo.GetMainExt();
}
UString ext = typeExt;
if (SfxMode)
- ext.SetFromAscii(kSFXExtension);
+ ext = kSFXExtension;
ArchivePath.BaseExtension = ext;
ArchivePath.VolExtension = typeExt;
ArchivePath.ParseFromPath(arcPath, ArcNameMode);
@@ -412,19 +245,43 @@ bool CUpdateOptions::SetArcPath(const CCodecs *codecs, const UString &arcPath)
return true;
}
-struct CUpdateProduceCallbackImp: public IUpdateProduceCallback
+
+struct CUpdateProduceCallbackImp Z7_final: public IUpdateProduceCallback
{
const CObjectVector<CArcItem> *_arcItems;
+ CDirItemsStat *_stat;
IUpdateCallbackUI *_callback;
- CUpdateProduceCallbackImp(const CObjectVector<CArcItem> *a,
- IUpdateCallbackUI *callback): _arcItems(a), _callback(callback) {}
- virtual HRESULT ShowDeleteFile(unsigned arcIndex);
+ CUpdateProduceCallbackImp(
+ const CObjectVector<CArcItem> *a,
+ CDirItemsStat *stat,
+ IUpdateCallbackUI *callback):
+ _arcItems(a),
+ _stat(stat),
+ _callback(callback) {}
+
+ virtual HRESULT ShowDeleteFile(unsigned arcIndex) Z7_override;
};
+
HRESULT CUpdateProduceCallbackImp::ShowDeleteFile(unsigned arcIndex)
{
const CArcItem &ai = (*_arcItems)[arcIndex];
+ {
+ CDirItemsStat &stat = *_stat;
+ if (ai.IsDir)
+ stat.NumDirs++;
+ else if (ai.IsAltStream)
+ {
+ stat.NumAltStreams++;
+ stat.AltStreamsSize += ai.Size;
+ }
+ else
+ {
+ stat.NumFiles++;
+ stat.FilesSize += ai.Size;
+ }
+ }
return _callback->ShowDeleteFile(ai.Name, ai.IsDir);
}
@@ -485,6 +342,8 @@ bool CRenamePair::GetNewPath(bool isFolder, const UString &src, UString &dest) c
int FindAltStreamColon_in_Path(const wchar_t *path);
#endif
+
+
static HRESULT Compress(
const CUpdateOptions &options,
bool isUpdatingItself,
@@ -497,6 +356,7 @@ static HRESULT Compress(
const CDirItems &dirItems,
const CDirItem *parentDirItem,
CTempFiles &tempFiles,
+ CMultiOutStream_Bunch &multiStreams,
CUpdateErrorInfo &errorInfo,
IUpdateCallbackUI *callback,
CFinishArchiveStat &st)
@@ -516,28 +376,63 @@ static HRESULT Compress(
}
else
{
- RINOK(codecs->CreateOutArchive(formatIndex, outArchive));
+ RINOK(codecs->CreateOutArchive((unsigned)formatIndex, outArchive))
- #ifdef EXTERNAL_CODECS
+ #ifdef Z7_EXTERNAL_CODECS
{
CMyComPtr<ISetCompressCodecsInfo> setCompressCodecsInfo;
outArchive.QueryInterface(IID_ISetCompressCodecsInfo, (void **)&setCompressCodecsInfo);
if (setCompressCodecsInfo)
{
- RINOK(setCompressCodecsInfo->SetCompressCodecsInfo(codecs));
+ RINOK(setCompressCodecsInfo->SetCompressCodecsInfo(codecs))
}
}
#endif
}
- if (outArchive == 0)
+ if (!outArchive)
throw kUpdateIsNotSupoorted;
-
+
+ // we need to set properties to get fileTimeType.
+ RINOK(SetProperties(outArchive, options.MethodMode.Properties))
+
NFileTimeType::EEnum fileTimeType;
{
+ /*
+ how we compare file_in_archive::MTime with dirItem.MTime
+ for GetUpdatePairInfoList():
+
+ if (kpidMTime is not defined), external MTime of archive is used.
+
+ before 22.00:
+ if (kpidTimeType is defined)
+ {
+ kpidTimeType is used as precision.
+ (kpidTimeType > kDOS) is not allowed.
+ }
+ else GetFileTimeType() value is used as precision.
+
+ 22.00:
+ if (kpidMTime is defined)
+ {
+ if (kpidMTime::precision != 0), then kpidMTime::precision is used as precision.
+ else
+ {
+ if (kpidTimeType is defined), kpidTimeType is used as precision.
+ else GetFileTimeType() value is used as precision.
+ }
+ }
+ else external MTime of archive is used as precision.
+ */
+
UInt32 value;
- RINOK(outArchive->GetFileTimeType(&value));
+ RINOK(outArchive->GetFileTimeType(&value))
+
+ // we support any future fileType here.
+ fileTimeType = (NFileTimeType::EEnum)value;
+ /*
+ old 21.07 code:
switch (value)
{
case NFileTimeType::kWindows:
@@ -548,13 +443,28 @@ static HRESULT Compress(
default:
return E_FAIL;
}
+ */
}
+ // bool noTimestampExpected = false;
{
- const CArcInfoEx &arcInfo = codecs->Formats[formatIndex];
+ const CArcInfoEx &arcInfo = codecs->Formats[(unsigned)formatIndex];
+
+ // if (arcInfo.Flags_KeepName()) noTimestampExpected = true;
+ if (arcInfo.Is_Xz() ||
+ arcInfo.Is_BZip2())
+ {
+ /* 7-zip before 22.00 returns NFileTimeType::kUnix for xz and bzip2,
+ but we want to set timestamp without reduction to unix. */
+ // noTimestampExpected = true;
+ fileTimeType = NFileTimeType::kNotDefined; // it means not defined
+ }
+
if (options.AltStreams.Val && !arcInfo.Flags_AltStreams())
return E_NOTIMPL;
- if (options.NtSecurity.Val && !arcInfo.Flags_NtSecure())
+ if (options.NtSecurity.Val && !arcInfo.Flags_NtSecurity())
+ return E_NOTIMPL;
+ if (options.DeleteAfterCompressing && arcInfo.Flags_HashHandler())
return E_NOTIMPL;
}
@@ -562,6 +472,8 @@ static HRESULT Compress(
UStringVector newNames;
+ CArcToDoStat stat2;
+
if (options.RenamePairs.Size() != 0)
{
FOR_VECTOR (i, arcItems)
@@ -587,7 +499,7 @@ static HRESULT Compress(
int colonPos = FindAltStreamColon_in_Path(ai.Name);
if (colonPos >= 0)
{
- UString mainName = ai.Name.Left(colonPos);
+ UString mainName = ai.Name.Left((unsigned)colonPos);
/*
actually we must improve that code to support cases
with folder renaming like: rn arc dir1\ dir2\
@@ -595,8 +507,8 @@ static HRESULT Compress(
if (rp.GetNewPath(false, mainName, dest))
{
needRename = true;
- dest += L':';
- dest += ai.Name.Ptr(colonPos + 1);
+ dest += ':';
+ dest += ai.Name.Ptr((unsigned)(colonPos + 1));
break;
}
}
@@ -610,8 +522,8 @@ static HRESULT Compress(
if (needRename)
{
up2.NewProps = true;
- RINOK(arc->IsItemAnti(i, up2.IsAnti));
- up2.NewNameIndex = newNames.Add(dest);
+ RINOK(arc->IsItem_Anti(i, up2.IsAnti))
+ up2.NewNameIndex = (int)newNames.Add(dest);
}
updatePairs2.Add(up2);
}
@@ -620,23 +532,97 @@ static HRESULT Compress(
{
CRecordVector<CUpdatePair> updatePairs;
GetUpdatePairInfoList(dirItems, arcItems, fileTimeType, updatePairs); // must be done only once!!!
- CUpdateProduceCallbackImp upCallback(&arcItems, callback);
+ CUpdateProduceCallbackImp upCallback(&arcItems, &stat2.DeleteData, callback);
UpdateProduce(updatePairs, actionSet, updatePairs2, isUpdatingItself ? &upCallback : NULL);
}
{
- UInt32 numItems = 0;
FOR_VECTOR (i, updatePairs2)
- if (updatePairs2[i].NewData)
- numItems++;
- RINOK(callback->SetNumItems(numItems));
+ {
+ const CUpdatePair2 &up = updatePairs2[i];
+
+ // 17.01: anti-item is (up.NewData && (p.UseArcProps in most cases))
+
+ if (up.NewData && !up.UseArcProps)
+ {
+ if (up.ExistOnDisk())
+ {
+ CDirItemsStat2 &stat = stat2.NewData;
+ const CDirItem &di = dirItems.Items[(unsigned)up.DirIndex];
+ if (di.IsDir())
+ {
+ if (up.IsAnti)
+ stat.Anti_NumDirs++;
+ else
+ stat.NumDirs++;
+ }
+ #ifdef _WIN32
+ else if (di.IsAltStream)
+ {
+ if (up.IsAnti)
+ stat.Anti_NumAltStreams++;
+ else
+ {
+ stat.NumAltStreams++;
+ stat.AltStreamsSize += di.Size;
+ }
+ }
+ #endif
+ else
+ {
+ if (up.IsAnti)
+ stat.Anti_NumFiles++;
+ else
+ {
+ stat.NumFiles++;
+ stat.FilesSize += di.Size;
+ }
+ }
+ }
+ }
+ else if (up.ArcIndex >= 0)
+ {
+ CDirItemsStat2 &stat = *(up.NewData ? &stat2.NewData : &stat2.OldData);
+ const CArcItem &ai = arcItems[(unsigned)up.ArcIndex];
+ if (ai.IsDir)
+ {
+ if (up.IsAnti)
+ stat.Anti_NumDirs++;
+ else
+ stat.NumDirs++;
+ }
+ else if (ai.IsAltStream)
+ {
+ if (up.IsAnti)
+ stat.Anti_NumAltStreams++;
+ else
+ {
+ stat.NumAltStreams++;
+ stat.AltStreamsSize += ai.Size;
+ }
+ }
+ else
+ {
+ if (up.IsAnti)
+ stat.Anti_NumFiles++;
+ else
+ {
+ stat.NumFiles++;
+ stat.FilesSize += ai.Size;
+ }
+ }
+ }
+ }
+ RINOK(callback->SetNumItems(stat2))
}
CArchiveUpdateCallback *updateCallbackSpec = new CArchiveUpdateCallback;
CMyComPtr<IArchiveUpdateCallback> updateCallback(updateCallbackSpec);
+ updateCallbackSpec->PreserveATime = options.PreserveATime;
updateCallbackSpec->ShareForWrite = options.OpenShareForWrite;
+ updateCallbackSpec->StopAfterOpenError = options.StopAfterOpenError;
updateCallbackSpec->StdInMode = options.StdInMode;
updateCallbackSpec->Callback = callback;
@@ -652,6 +638,8 @@ static HRESULT Compress(
updateCallbackSpec->StoreNtSecurity = options.NtSecurity.Val;
updateCallbackSpec->StoreHardLinks = options.HardLinks.Val;
updateCallbackSpec->StoreSymLinks = options.SymLinks.Val;
+ updateCallbackSpec->StoreOwnerName = options.StoreOwnerName.Val;
+ updateCallbackSpec->StoreOwnerId = options.StoreOwnerId.Val;
updateCallbackSpec->Arc = arc;
updateCallbackSpec->ArcItems = &arcItems;
@@ -659,9 +647,20 @@ static HRESULT Compress(
updateCallbackSpec->ProcessedItemsStatuses = processedItemsStatuses;
+ {
+ const UString arcPath = archivePath.GetFinalPath();
+ updateCallbackSpec->ArcFileName = ExtractFileNameFromPath(arcPath);
+ }
+
if (options.RenamePairs.Size() != 0)
updateCallbackSpec->NewNames = &newNames;
+ if (options.SetArcMTime)
+ {
+ // updateCallbackSpec->Need_ArcMTime_Report = true;
+ updateCallbackSpec->Need_LatestMTime = true;
+ }
+
CMyComPtr<IOutStream> outSeekStream;
CMyComPtr<ISequentialOutStream> outStream;
@@ -675,7 +674,7 @@ static HRESULT Compress(
COutFileStream *outStreamSpec = NULL;
CStdOutFileStream *stdOutFileStreamSpec = NULL;
- COutMultiVolStream *volStreamSpec = NULL;
+ CMultiOutStream *volStreamSpec = NULL;
if (options.VolumesSizes.Size() == 0)
{
@@ -698,9 +697,8 @@ static HRESULT Compress(
{
if (i > 0)
{
- FChar s[16];
- ConvertUInt32ToString(i, s);
- archivePath.TempPostfix = s;
+ archivePath.TempPostfix.Empty();
+ archivePath.TempPostfix.Add_UInt32(i);
}
realPath = archivePath.GetTempPath();
}
@@ -729,25 +727,26 @@ static HRESULT Compress(
if (arc && arc->GetGlobalOffset() > 0)
return E_NOTIMPL;
- volStreamSpec = new COutMultiVolStream;
+ volStreamSpec = new CMultiOutStream();
outSeekStream = volStreamSpec;
outStream = outSeekStream;
- volStreamSpec->Sizes = options.VolumesSizes;
volStreamSpec->Prefix = us2fs(archivePath.GetFinalVolPath());
- volStreamSpec->Prefix += FTEXT('.');
- volStreamSpec->TempFiles = &tempFiles;
- volStreamSpec->Init();
+ volStreamSpec->Prefix.Add_Dot();
+ volStreamSpec->Init(options.VolumesSizes);
+ {
+ CMultiOutStream_Rec &rec = multiStreams.Items.AddNew();
+ rec.Spec = volStreamSpec;
+ rec.Ref = rec.Spec;
+ }
/*
updateCallbackSpec->VolumesSizes = volumesSizes;
updateCallbackSpec->VolName = archivePath.Prefix + archivePath.Name;
if (!archivePath.VolExtension.IsEmpty())
- updateCallbackSpec->VolExt = UString(L'.') + archivePath.VolExtension;
+ updateCallbackSpec->VolExt = UString('.') + archivePath.VolExtension;
*/
}
- RINOK(SetProperties(outArchive, options.MethodMode.Properties));
-
if (options.SfxMode)
{
CInFileStream *sfxStreamSpec = new CInFileStream;
@@ -763,22 +762,22 @@ static HRESULT Compress(
{
outStreamSpec2 = new COutFileStream;
sfxOutStream = outStreamSpec2;
- FString realPath = us2fs(archivePath.GetFinalPath());
+ const FString realPath = us2fs(archivePath.GetFinalPath());
if (!outStreamSpec2->Create(realPath, false))
return errorInfo.SetFromLastError("cannot open file", realPath);
}
{
UInt64 sfxSize;
- RINOK(sfxStreamSpec->GetSize(&sfxSize));
- RINOK(callback->WriteSfx(fs2us(options.SfxModule), sfxSize));
+ RINOK(sfxStreamSpec->GetSize(&sfxSize))
+ RINOK(callback->WriteSfx(fs2us(options.SfxModule), sfxSize))
}
- RINOK(NCompress::CopyStream(sfxStream, sfxOutStream, NULL));
+ RINOK(NCompress::CopyStream(sfxStream, sfxOutStream, NULL))
if (outStreamSpec2)
{
- RINOK(outStreamSpec2->Close());
+ RINOK(outStreamSpec2->Close())
}
}
@@ -789,8 +788,8 @@ static HRESULT Compress(
else
{
// Int64 globalOffset = arc->GetGlobalOffset();
- RINOK(arc->InStream->Seek(0, STREAM_SEEK_SET, NULL));
- RINOK(NCompress::CopyStream_ExactSize(arc->InStream, outStream, arc->ArcStreamOffset, NULL));
+ RINOK(InStream_SeekToBegin(arc->InStream))
+ RINOK(NCompress::CopyStream_ExactSize(arc->InStream, outStream, arc->ArcStreamOffset, NULL))
if (options.StdOutMode)
tailStream = outStream;
else
@@ -803,10 +802,57 @@ static HRESULT Compress(
}
}
+ CFiTime ft;
+ FiTime_Clear(ft);
+ bool ft_Defined = false;
+ {
+ FOR_VECTOR (i, updatePairs2)
+ {
+ const CUpdatePair2 &pair2 = updatePairs2[i];
+ CFiTime ft2;
+ FiTime_Clear(ft2);
+ bool ft2_Defined = false;
+ /* we use full precision of dirItem, if dirItem is defined
+ and (dirItem will be used or dirItem is sameTime in dir and arc */
+ if (pair2.DirIndex >= 0 &&
+ (pair2.NewProps || pair2.IsSameTime))
+ {
+ ft2 = dirItems.Items[(unsigned)pair2.DirIndex].MTime;
+ ft2_Defined = true;
+ }
+ else if (pair2.UseArcProps && pair2.ArcIndex >= 0)
+ {
+ const CArcItem &arcItem = arcItems[(unsigned)pair2.ArcIndex];
+ if (arcItem.MTime.Def)
+ {
+ arcItem.MTime.Write_To_FiTime(ft2);
+ ft2_Defined = true;
+ }
+ }
+ if (ft2_Defined)
+ {
+ if (!ft_Defined || Compare_FiTime(&ft, &ft2) < 0)
+ {
+ ft = ft2;
+ ft_Defined = true;
+ }
+ }
+ }
+ /*
+ if (fileTimeType != NFileTimeType::kNotDefined)
+ FiTime_Normalize_With_Prec(ft, fileTimeType);
+ */
+ }
+
+ if (volStreamSpec && options.SetArcMTime && ft_Defined)
+ {
+ volStreamSpec->MTime = ft;
+ volStreamSpec->MTime_Defined = true;
+ }
HRESULT result = outArchive->UpdateItems(tailStream, updatePairs2.Size(), updateCallback);
// callback->Finalize();
- RINOK(result);
+ RINOK(result)
if (!updateCallbackSpec->AreAllFilesClosed())
{
@@ -817,29 +863,43 @@ static HRESULT Compress(
if (options.SetArcMTime)
{
- FILETIME ft;
- ft.dwLowDateTime = 0;
- ft.dwHighDateTime = 0;
- FOR_VECTOR (i, updatePairs2)
+ // bool needNormalizeAfterStream;
+ // needParse;
+ /*
+ if (updateCallbackSpec->ArcMTime_WasReported)
{
- CUpdatePair2 &pair2 = updatePairs2[i];
- const FILETIME *ft2 = NULL;
- if (pair2.NewProps && pair2.DirIndex >= 0)
- ft2 = &dirItems.Items[pair2.DirIndex].MTime;
- else if (pair2.UseArcProps && pair2.ArcIndex >= 0)
- ft2 = &arcItems[pair2.ArcIndex].MTime;
- if (ft2)
+ isDefined = updateCallbackSpec->Reported_ArcMTime.Def;
+ if (isDefined)
+ updateCallbackSpec->Reported_ArcMTime.Write_To_FiTime(ft);
+ else
+ fileTimeType = NFileTimeType::kNotDefined;
+ }
+ if (!isDefined)
+ */
+ {
+ if (updateCallbackSpec->LatestMTime_Defined)
{
- if (::CompareFileTime(&ft, ft2) < 0)
- ft = *ft2;
+ // CArcTime at = StreamCallback_ArcMTime;
+ // updateCallbackSpec->StreamCallback_ArcMTime.Write_To_FiTime(ft);
+ // we must normalize with precision from archive;
+ if (!ft_Defined || Compare_FiTime(&ft, &updateCallbackSpec->LatestMTime) < 0)
+ ft = updateCallbackSpec->LatestMTime;
+ ft_Defined = true;
}
+ /*
+ if (fileTimeType != NFileTimeType::kNotDefined)
+ FiTime_Normalize_With_Prec(ft, fileTimeType);
+ */
}
- if (ft.dwLowDateTime != 0 || ft.dwHighDateTime != 0)
+ // if (ft.dwLowDateTime != 0 || ft.dwHighDateTime != 0)
+ if (ft_Defined)
{
+ // we ignore set time errors here.
+ // note that user could move some finished volumes to another folder.
if (outStreamSpec)
outStreamSpec->SetMTime(&ft);
else if (volStreamSpec)
- volStreamSpec->SetMTime(&ft);;
+ volStreamSpec->SetMTime_Final(ft);
}
}
@@ -859,10 +919,43 @@ static HRESULT Compress(
if (outStreamSpec)
result = outStreamSpec->Close();
else if (volStreamSpec)
- result = volStreamSpec->Close();
+ {
+ result = volStreamSpec->FinalFlush_and_CloseFiles(st.NumVolumes);
+ st.IsMultiVolMode = true;
+ }
+
+ RINOK(result)
+
+ if (processedItemsStatuses)
+ {
+ FOR_VECTOR (i, updatePairs2)
+ {
+ const CUpdatePair2 &up = updatePairs2[i];
+ if (up.NewData && up.DirIndex >= 0)
+ {
+ const CDirItem &di = dirItems.Items[(unsigned)up.DirIndex];
+ if (di.AreReparseData() || (!di.IsDir() && di.Size == 0))
+ processedItemsStatuses[(unsigned)up.DirIndex] = 1;
+ }
+ }
+ }
+
return result;
}
+
+
+static bool Censor_AreAllAllowed(const NWildcard::CCensor &censor)
+{
+ if (censor.Pairs.Size() != 1)
+ return false;
+ const NWildcard::CPair &pair = censor.Pairs[0];
+ /* Censor_CheckPath() ignores (CPair::Prefix).
+ So we also ignore (CPair::Prefix) here */
+ // if (!pair.Prefix.IsEmpty()) return false;
+ return pair.Head.AreAllAllowed();
+}
+
bool CensorNode_CheckPath2(const NWildcard::CCensorNode &node, const CReadArcItem &item, bool &include);
static bool Censor_CheckPath(const NWildcard::CCensor &censor, const CReadArcItem &item)
@@ -870,9 +963,13 @@ static bool Censor_CheckPath(const NWildcard::CCensor &censor, const CReadArcIte
bool finded = false;
FOR_VECTOR (i, censor.Pairs)
{
+ /* (CPair::Prefix) in not used for matching items in archive.
+ So we ignore (CPair::Prefix) here */
bool include;
if (CensorNode_CheckPath2(censor.Pairs[i].Head, item, include))
{
+ // Check it and FIXME !!!!
+ // here we can exclude item via some Pair, that is still allowed by another Pair
if (!include)
return false;
finded = true;
@@ -890,16 +987,18 @@ static HRESULT EnumerateInArchiveItems(
arcItems.Clear();
UInt32 numItems;
IInArchive *archive = arc.Archive;
- RINOK(archive->GetNumberOfItems(&numItems));
+ RINOK(archive->GetNumberOfItems(&numItems))
arcItems.ClearAndReserve(numItems);
CReadArcItem item;
+ const bool allFilesAreAllowed = Censor_AreAllAllowed(censor);
+
for (UInt32 i = 0; i < numItems; i++)
{
CArcItem ai;
- RINOK(arc.GetItem(i, item));
+ RINOK(arc.GetItem(i, item))
ai.Name = item.Path;
ai.IsDir = item.IsDir;
ai.IsAltStream =
@@ -913,28 +1012,14 @@ static HRESULT EnumerateInArchiveItems(
if (!storeStreamsMode && ai.IsAltStream)
continue;
*/
- ai.Censored = Censor_CheckPath(censor, item);
+ if (allFilesAreAllowed)
+ ai.Censored = true;
+ else
+ ai.Censored = Censor_CheckPath(censor, item);
- RINOK(arc.GetItemMTime(i, ai.MTime, ai.MTimeDefined));
- RINOK(arc.GetItemSize(i, ai.Size, ai.SizeDefined));
-
- {
- CPropVariant prop;
- RINOK(archive->GetProperty(i, kpidTimeType, &prop));
- if (prop.vt == VT_UI4)
- {
- ai.TimeType = (int)(NFileTimeType::EEnum)prop.ulVal;
- switch (ai.TimeType)
- {
- case NFileTimeType::kWindows:
- case NFileTimeType::kUnix:
- case NFileTimeType::kDOS:
- break;
- default:
- return E_FAIL;
- }
- }
- }
+ // ai.MTime will be set to archive MTime, if not present in archive item
+ RINOK(arc.GetItem_MTime(i, ai.MTime))
+ RINOK(arc.GetItem_Size(i, ai.Size, ai.Size_Defined))
ai.IndexInServer = i;
arcItems.AddInReserved(ai);
@@ -944,39 +1029,72 @@ static HRESULT EnumerateInArchiveItems(
#if defined(_WIN32) && !defined(UNDER_CE)
+#if defined(__MINGW32__) || defined(__MINGW64__)
#include <mapi.h>
-
+#else
+#include <MAPI.h>
#endif
-struct CRefSortPair
-{
- unsigned Len;
- unsigned Index;
-};
+extern "C" {
-#define RINOZ(x) { int __tt = (x); if (__tt != 0) return __tt; }
+#ifdef MAPI_FORCE_UNICODE
-static int CompareRefSortPair(const CRefSortPair *a1, const CRefSortPair *a2, void *)
-{
- RINOZ(-MyCompare(a1->Len, a2->Len));
- return MyCompare(a1->Index, a2->Index);
-}
+#define Z7_WIN_LPMAPISENDMAILW LPMAPISENDMAILW
+#define Z7_WIN_MapiFileDescW MapiFileDescW
+#define Z7_WIN_MapiMessageW MapiMessageW
+#define Z7_WIN_MapiRecipDescW MapiRecipDescW
+
+#else
-static unsigned GetNumSlashes(const FChar *s)
+typedef struct
{
- for (unsigned numSlashes = 0;;)
- {
- FChar c = *s++;
- if (c == 0)
- return numSlashes;
- if (IS_PATH_SEPAR(c))
- numSlashes++;
- }
+ ULONG ulReserved;
+ ULONG ulRecipClass;
+ PWSTR lpszName;
+ PWSTR lpszAddress;
+ ULONG ulEIDSize;
+ PVOID lpEntryID;
+} Z7_WIN_MapiRecipDescW, *Z7_WIN_lpMapiRecipDescW;
+
+typedef struct
+{
+ ULONG ulReserved;
+ ULONG flFlags;
+ ULONG nPosition;
+ PWSTR lpszPathName;
+ PWSTR lpszFileName;
+ PVOID lpFileType;
+} Z7_WIN_MapiFileDescW, *Z7_WIN_lpMapiFileDescW;
+
+typedef struct
+{
+ ULONG ulReserved;
+ PWSTR lpszSubject;
+ PWSTR lpszNoteText;
+ PWSTR lpszMessageType;
+ PWSTR lpszDateReceived;
+ PWSTR lpszConversationID;
+ FLAGS flFlags;
+ Z7_WIN_lpMapiRecipDescW lpOriginator;
+ ULONG nRecipCount;
+ Z7_WIN_lpMapiRecipDescW lpRecips;
+ ULONG nFileCount;
+ Z7_WIN_lpMapiFileDescW lpFiles;
+} Z7_WIN_MapiMessageW, *Z7_WIN_lpMapiMessageW;
+
+typedef ULONG (FAR PASCAL Z7_WIN_MAPISENDMAILW)(
+ LHANDLE lhSession,
+ ULONG_PTR ulUIParam,
+ Z7_WIN_lpMapiMessageW lpMessage,
+ FLAGS flFlags,
+ ULONG ulReserved
+);
+typedef Z7_WIN_MAPISENDMAILW FAR *Z7_WIN_LPMAPISENDMAILW;
+
+#endif // MAPI_FORCE_UNICODE
}
+#endif // _WIN32
-#ifdef _WIN32
-void ConvertToLongNames(NWildcard::CCensor &censor);
-#endif
HRESULT UpdateArchive(
CCodecs *codecs,
@@ -1007,7 +1125,7 @@ HRESULT UpdateArchive(
if (options.Commands.Size() != 1)
return E_NOTIMPL;
const CActionSet &as = options.Commands[0].ActionSet;
- for (int i = 2; i < NPairState::kNumValues; i++)
+ for (unsigned i = 2; i < NPairState::kNumValues; i++)
if (as.StateActions[i] != NPairAction::kCompress)
return E_NOTIMPL;
}
@@ -1025,7 +1143,7 @@ HRESULT UpdateArchive(
if (options.SfxMode)
{
CProperty property;
- property.Name.SetFromAscii("rsfx");
+ property.Name = "rsfx";
options.MethodMode.Properties.Add(property);
if (options.SfxModule.IsEmpty())
{
@@ -1036,7 +1154,7 @@ HRESULT UpdateArchive(
if (options.SfxModule.Find(FCHAR_PATH_SEPARATOR) < 0)
{
const FString fullName = NDLL::GetModuleDirPrefix() + options.SfxModule;
- if (NFind::DoesFileExist(fullName))
+ if (NFind::DoesFileExist_FollowLink(fullName))
{
options.SfxModule = fullName;
found = true;
@@ -1044,7 +1162,7 @@ HRESULT UpdateArchive(
}
if (!found)
{
- if (!NFind::DoesFileExist(options.SfxModule))
+ if (!NFind::DoesFileExist_FollowLink(options.SfxModule))
return errorInfo.SetFromLastError("cannot find specified SFX module", options.SfxModule);
}
}
@@ -1058,7 +1176,14 @@ HRESULT UpdateArchive(
!options.SetArcPath(codecs, cmdArcPath2))
return E_NOTIMPL;
}
- const UString arcPath = options.ArchivePath.GetFinalPath();
+
+ UString arcPath = options.ArchivePath.GetFinalPath();
+
+ if (!options.VolumesSizes.IsEmpty())
+ {
+ arcPath = options.ArchivePath.GetFinalVolPath();
+ arcPath += ".001";
+ }
if (cmdArcPath2.IsEmpty())
{
@@ -1068,10 +1193,10 @@ HRESULT UpdateArchive(
else
{
NFind::CFileInfo fi;
- if (!fi.Find(us2fs(arcPath)))
+ if (!fi.Find_FollowLink(us2fs(arcPath)))
{
if (renameMode)
- throw "can't find archive";;
+ throw "can't find archive";
if (options.MethodMode.Type.FormatIndex < 0)
{
if (!options.SetArcPath(codecs, cmdArcPath2))
@@ -1081,11 +1206,39 @@ HRESULT UpdateArchive(
else
{
if (fi.IsDir())
- throw "there is no such archive";
+ return errorInfo.SetFromError_DWORD("There is a folder with the name of archive",
+ us2fs(arcPath),
+ #ifdef _WIN32
+ ERROR_ACCESS_DENIED
+ #else
+ EISDIR
+ #endif
+ );
+ #ifdef _WIN32
if (fi.IsDevice)
return E_NOTIMPL;
+ #endif
+
+ if (!options.StdOutMode && options.UpdateArchiveItself)
+ if (fi.IsReadOnly())
+ {
+ return errorInfo.SetFromError_DWORD("The file is read-only",
+ us2fs(arcPath),
+ #ifdef _WIN32
+ ERROR_ACCESS_DENIED
+ #else
+ EACCES
+ #endif
+ );
+ }
+
if (options.VolumesSizes.Size() > 0)
+ {
+ errorInfo.FileNames.Add(us2fs(arcPath));
+ // errorInfo.SystemError = (DWORD)E_NOTIMPL;
+ errorInfo.Message = kUpdateIsNotSupported_MultiVol;
return E_NOTIMPL;
+ }
CObjectVector<COpenType> types2;
// change it.
if (options.MethodMode.Type_Defined)
@@ -1094,7 +1247,7 @@ HRESULT UpdateArchive(
CIntVector excl;
COpenOptions op;
- #ifndef _SFX
+ #ifndef Z7_SFX
op.props = &options.MethodMode.Properties;
#endif
op.codecs = codecs;
@@ -1104,7 +1257,7 @@ HRESULT UpdateArchive(
op.stream = NULL;
op.filePath = arcPath;
- RINOK(callback->StartOpenArchive(arcPath));
+ RINOK(callback->StartOpenArchive(arcPath))
HRESULT result = arcLink.Open_Strict(op, openCallback);
@@ -1116,23 +1269,29 @@ HRESULT UpdateArchive(
if (result == S_FALSE)
return E_FAIL;
*/
- RINOK(res2);
- RINOK(result);
+ RINOK(res2)
+ RINOK(result)
if (arcLink.VolumePaths.Size() > 1)
{
- errorInfo.SystemError = (DWORD)E_NOTIMPL;
- errorInfo.Message = "Updating for multivolume archives is not implemented";
+ // errorInfo.SystemError = (DWORD)E_NOTIMPL;
+ errorInfo.Message = kUpdateIsNotSupported_MultiVol;
return E_NOTIMPL;
}
CArc &arc = arcLink.Arcs.Back();
- arc.MTimeDefined = !fi.IsDevice;
- arc.MTime = fi.MTime;
+ arc.MTime.Def =
+ #ifdef _WIN32
+ !fi.IsDevice;
+ #else
+ true;
+ #endif
+ if (arc.MTime.Def)
+ arc.MTime.Set_From_FiTime(fi.MTime);
if (arc.ErrorInfo.ThereIsTail)
{
- errorInfo.SystemError = (DWORD)E_NOTIMPL;
+ // errorInfo.SystemError = (DWORD)E_NOTIMPL;
errorInfo.Message = "There is some data block after the end of the archive";
return E_NOTIMPL;
}
@@ -1147,7 +1306,7 @@ HRESULT UpdateArchive(
if (options.MethodMode.Type.FormatIndex < 0)
{
- options.MethodMode.Type.FormatIndex = codecs->FindFormatForArchiveType(kDefaultArcType);
+ options.MethodMode.Type.FormatIndex = codecs->FindFormatForArchiveType((UString)kDefaultArcType);
if (options.MethodMode.Type.FormatIndex < 0)
return E_NOTIMPL;
}
@@ -1172,10 +1331,11 @@ HRESULT UpdateArchive(
if (options.StdInMode)
{
CDirItem di;
+ di.ClearBase();
di.Name = options.StdInFileName;
di.Size = (UInt64)(Int64)-1;
- di.Attrib = 0;
- NTime::GetCurUtcFileTime(di.MTime);
+ di.SetAsFile();
+ NTime::GetCurUtc_FiTime(di.MTime);
di.CTime = di.ATime = di.MTime;
dirItems.Items.Add(di);
}
@@ -1190,7 +1350,7 @@ HRESULT UpdateArchive(
if (needScanning)
{
- RINOK(callback->StartScanning());
+ RINOK(callback->StartScanning())
dirItems.SymLinks = options.SymLinks.Val;
@@ -1199,10 +1359,18 @@ HRESULT UpdateArchive(
#endif
dirItems.ScanAltStreams = options.AltStreams.Val;
+ dirItems.ExcludeDirItems = censor.ExcludeDirItems;
+ dirItems.ExcludeFileItems = censor.ExcludeFileItems;
+
+ dirItems.ShareForWrite = options.OpenShareForWrite;
+
+ #ifndef _WIN32
+ dirItems.StoreOwnerName = options.StoreOwnerName.Val;
+ #endif
- HRESULT res = EnumerateItems(censor,
+ const HRESULT res = EnumerateItems(censor,
options.PathMode,
- options.AddPathPrefix,
+ UString(), // options.AddPathPrefix,
dirItems);
if (res != S_OK)
@@ -1212,13 +1380,15 @@ HRESULT UpdateArchive(
return res;
}
- RINOK(callback->FinishScanning(dirItems.Stat));
+ RINOK(callback->FinishScanning(dirItems.Stat))
+ // 22.00: we don't need parent folder, if absolute path mode
+ if (options.PathMode != NWildcard::k_AbsPath)
if (censor.Pairs.Size() == 1)
{
NFind::CFileInfo fi;
FString prefix = us2fs(censor.Pairs[0].Prefix);
- prefix += FTEXT('.');
+ prefix.Add_Dot();
// UString prefix = censor.Pairs[0].Prefix;
/*
if (prefix.Back() == WCHAR_PATH_SEPARATOR)
@@ -1229,11 +1399,7 @@ HRESULT UpdateArchive(
if (fi.Find(prefix))
if (fi.IsDir())
{
- parentDirItem.Size = fi.Size;
- parentDirItem.CTime = fi.CTime;
- parentDirItem.ATime = fi.ATime;
- parentDirItem.MTime = fi.MTime;
- parentDirItem.Attrib = fi.Attrib;
+ parentDirItem.Copy_From_FileInfoBase(fi);
parentDirItem_Ptr = &parentDirItem;
int secureIndex = -1;
@@ -1242,8 +1408,6 @@ HRESULT UpdateArchive(
dirItems.AddSecurityItem(prefix, secureIndex);
#endif
parentDirItem.SecureIndex = secureIndex;
-
- parentDirItem_Ptr = &parentDirItem;
}
}
}
@@ -1286,6 +1450,31 @@ HRESULT UpdateArchive(
unsigned ci;
+
+ // self including protection
+ if (options.DeleteAfterCompressing)
+ {
+ for (ci = 0; ci < options.Commands.Size(); ci++)
+ {
+ CArchivePath &ap = options.Commands[ci].ArchivePath;
+ const FString path = us2fs(ap.GetFinalPath());
+ // maybe we must compare absolute paths path here
+ FOR_VECTOR (i, dirItems.Items)
+ {
+ const FString phyPath = dirItems.GetPhyPath(i);
+ if (phyPath == path)
+ {
+ UString s;
+ s = "It is not allowed to include archive to itself";
+ s.Add_LF();
+ s += fs2us(path);
+ throw s;
+ }
+ }
+ }
+ }
+
+
for (ci = 0; ci < options.Commands.Size(); ci++)
{
CArchivePath &ap = options.Commands[ci].ArchivePath;
@@ -1315,7 +1504,7 @@ HRESULT UpdateArchive(
{
RINOK(EnumerateInArchiveItems(
// options.StoreAltStreams,
- censor, arcLink.Arcs.Back(), arcItems));
+ censor, arcLink.Arcs.Back(), arcItems))
}
/*
@@ -1328,14 +1517,16 @@ HRESULT UpdateArchive(
CByteBuffer processedItems;
if (options.DeleteAfterCompressing)
{
- unsigned num = dirItems.Items.Size();
+ const unsigned num = dirItems.Items.Size();
processedItems.Alloc(num);
for (unsigned i = 0; i < num; i++)
processedItems[i] = 0;
}
+ CMultiOutStream_Bunch multiStreams;
+
/*
- #ifndef _NO_CRYPTO
+ #ifndef Z7_NO_CRYPTO
if (arcLink.PasswordWasAsked)
{
// We set password, if open have requested password
@@ -1353,7 +1544,7 @@ HRESULT UpdateArchive(
if (options.StdOutMode)
{
- name.SetFromAscii("stdout");
+ name = "stdout";
isUpdating = thereIsInArchive;
}
else
@@ -1379,18 +1570,22 @@ HRESULT UpdateArchive(
parentDirItem_Ptr,
tempFiles,
- errorInfo, callback, st));
+ multiStreams,
+ errorInfo, callback, st))
- RINOK(callback->FinishArchive(st));
+ RINOK(callback->FinishArchive(st))
}
if (thereIsInArchive)
{
- RINOK(arcLink.Close());
+ RINOK(arcLink.Close())
arcLink.Release();
}
+ multiStreams.DisableDeletion();
+ RINOK(multiStreams.Destruct())
+
tempFiles.Paths.Clear();
if (createTempFile)
{
@@ -1399,9 +1594,13 @@ HRESULT UpdateArchive(
CArchivePath &ap = options.Commands[0].ArchivePath;
const FString &tempPath = ap.GetTempPath();
+ // DWORD attrib = 0;
if (thereIsInArchive)
+ {
+ // attrib = NFind::GetFileAttrib(us2fs(arcPath));
if (!DeleteFileAlways(us2fs(arcPath)))
return errorInfo.SetFromLastError("cannot delete the file", us2fs(arcPath));
+ }
if (!MyMoveFile(tempPath, us2fs(arcPath)))
{
@@ -1409,6 +1608,15 @@ HRESULT UpdateArchive(
errorInfo.FileNames.Add(us2fs(arcPath));
return errorInfo.Get_HRESULT_Error();
}
+
+ /*
+ if (attrib != INVALID_FILE_ATTRIBUTES && (attrib & FILE_ATTRIBUTE_READONLY))
+ {
+ DWORD attrib2 = NFind::GetFileAttrib(us2fs(arcPath));
+ if (attrib2 != INVALID_FILE_ATTRIBUTES)
+ NDir::SetFileAttrib(us2fs(arcPath), attrib2 | FILE_ATTRIBUTE_READONLY);
+ }
+ */
}
catch(...)
{
@@ -1428,6 +1636,19 @@ HRESULT UpdateArchive(
return errorInfo.Get_HRESULT_Error();
}
+ FStringVector fullPaths;
+ unsigned i;
+
+ for (i = 0; i < options.Commands.Size(); i++)
+ {
+ CArchivePath &ap = options.Commands[i].ArchivePath;
+ const FString finalPath = us2fs(ap.GetFinalPath());
+ FString arcPath2;
+ if (!MyGetFullPathName(finalPath, arcPath2))
+ return errorInfo.SetFromLastError("GetFullPathName error", finalPath);
+ fullPaths.Add(arcPath2);
+ }
+
/*
LPMAPISENDDOCUMENTS fnSend = (LPMAPISENDDOCUMENTS)mapiLib.GetProc("MAPISendDocuments");
if (fnSend == 0)
@@ -1436,69 +1657,128 @@ HRESULT UpdateArchive(
return errorInfo.Get_HRESULT_Error();
}
*/
+ const
+ Z7_WIN_LPMAPISENDMAILW sendMailW = Z7_GET_PROC_ADDRESS(
+ Z7_WIN_LPMAPISENDMAILW, mapiLib.Get_HMODULE(),
+ "MAPISendMailW");
+ if (sendMailW)
+ {
+
+ CCurrentDirRestorer curDirRestorer;
+
+ UStringVector paths;
+ UStringVector names;
- LPMAPISENDMAIL sendMail = (LPMAPISENDMAIL)mapiLib.GetProc("MAPISendMail");
- if (sendMail == 0)
+ for (i = 0; i < fullPaths.Size(); i++)
{
- errorInfo.SetFromLastError("7-Zip cannot find MAPISendMail function");
- return errorInfo.Get_HRESULT_Error();;
+ const UString arcPath2 = fs2us(fullPaths[i]);
+ const UString fileName = ExtractFileNameFromPath(arcPath2);
+ paths.Add(arcPath2);
+ names.Add(fileName);
+ // Warning!!! MAPISendDocuments function changes Current directory
+ // fnSend(0, ";", (LPSTR)(LPCSTR)path, (LPSTR)(LPCSTR)name, 0);
}
- FStringVector fullPaths;
- unsigned i;
+ CRecordVector<Z7_WIN_MapiFileDescW> files;
+ files.ClearAndSetSize(paths.Size());
- for (i = 0; i < options.Commands.Size(); i++)
+ for (i = 0; i < paths.Size(); i++)
{
- CArchivePath &ap = options.Commands[i].ArchivePath;
- FString finalPath = us2fs(ap.GetFinalPath());
- FString arcPath2;
- if (!MyGetFullPathName(finalPath, arcPath2))
- return errorInfo.SetFromLastError("GetFullPathName error", finalPath);
- fullPaths.Add(arcPath2);
+ Z7_WIN_MapiFileDescW &f = files[i];
+ memset(&f, 0, sizeof(f));
+ f.nPosition = 0xFFFFFFFF;
+ f.lpszPathName = paths[i].Ptr_non_const();
+ f.lpszFileName = names[i].Ptr_non_const();
+ }
+
+ {
+ Z7_WIN_MapiMessageW m;
+ memset(&m, 0, sizeof(m));
+ m.nFileCount = files.Size();
+ m.lpFiles = &files.Front();
+
+ const UString addr (options.EMailAddress);
+ Z7_WIN_MapiRecipDescW rec;
+ if (!addr.IsEmpty())
+ {
+ memset(&rec, 0, sizeof(rec));
+ rec.ulRecipClass = MAPI_TO;
+ rec.lpszAddress = addr.Ptr_non_const();
+ m.nRecipCount = 1;
+ m.lpRecips = &rec;
+ }
+
+ sendMailW((LHANDLE)0, 0, &m, MAPI_DIALOG, 0);
+ }
+ }
+ else
+ {
+ const
+ LPMAPISENDMAIL sendMail = Z7_GET_PROC_ADDRESS(
+ LPMAPISENDMAIL, mapiLib.Get_HMODULE(),
+ "MAPISendMail");
+ if (!sendMail)
+ {
+ errorInfo.SetFromLastError("7-Zip cannot find MAPISendMail function");
+ return errorInfo.Get_HRESULT_Error();
}
CCurrentDirRestorer curDirRestorer;
+
+ AStringVector paths;
+ AStringVector names;
for (i = 0; i < fullPaths.Size(); i++)
{
- UString arcPath2 = fs2us(fullPaths[i]);
- UString fileName = ExtractFileNameFromPath(arcPath2);
- AString path = GetAnsiString(arcPath2);
- AString name = GetAnsiString(fileName);
+ const UString arcPath2 = fs2us(fullPaths[i]);
+ const UString fileName = ExtractFileNameFromPath(arcPath2);
+ paths.Add(GetAnsiString(arcPath2));
+ names.Add(GetAnsiString(fileName));
+ // const AString path (GetAnsiString(arcPath2));
+ // const AString name (GetAnsiString(fileName));
// Warning!!! MAPISendDocuments function changes Current directory
// fnSend(0, ";", (LPSTR)(LPCSTR)path, (LPSTR)(LPCSTR)name, 0);
+ }
- MapiFileDesc f;
+ CRecordVector<MapiFileDesc> files;
+ files.ClearAndSetSize(paths.Size());
+
+ for (i = 0; i < paths.Size(); i++)
+ {
+ MapiFileDesc &f = files[i];
memset(&f, 0, sizeof(f));
f.nPosition = 0xFFFFFFFF;
- f.lpszPathName = (char *)(const char *)path;
- f.lpszFileName = (char *)(const char *)name;
-
+ f.lpszPathName = paths[i].Ptr_non_const();
+ f.lpszFileName = names[i].Ptr_non_const();
+ }
+
+ {
MapiMessage m;
memset(&m, 0, sizeof(m));
- m.nFileCount = 1;
- m.lpFiles = &f;
+ m.nFileCount = files.Size();
+ m.lpFiles = &files.Front();
- const AString addr = GetAnsiString(options.EMailAddress);
+ const AString addr (GetAnsiString(options.EMailAddress));
MapiRecipDesc rec;
if (!addr.IsEmpty())
{
memset(&rec, 0, sizeof(rec));
rec.ulRecipClass = MAPI_TO;
- rec.lpszAddress = (char *)(const char *)addr;
+ rec.lpszAddress = addr.Ptr_non_const();
m.nRecipCount = 1;
m.lpRecips = &rec;
}
sendMail((LHANDLE)0, 0, &m, MAPI_DIALOG, 0);
}
+ }
}
#endif
if (options.DeleteAfterCompressing)
{
- CRecordVector<CRefSortPair> pairs;
+ CRecordVector<CDirPathSortPair> pairs;
FStringVector foldersNames;
unsigned i;
@@ -1506,47 +1786,71 @@ HRESULT UpdateArchive(
for (i = 0; i < dirItems.Items.Size(); i++)
{
const CDirItem &dirItem = dirItems.Items[i];
- FString phyPath = dirItems.GetPhyPath(i);
+ const FString phyPath = dirItems.GetPhyPath(i);
if (dirItem.IsDir())
{
- CRefSortPair pair;
+ CDirPathSortPair pair;
pair.Index = i;
- pair.Len = GetNumSlashes(phyPath);
+ pair.SetNumSlashes(phyPath);
pairs.Add(pair);
}
else
{
- if (processedItems[i] != 0 || dirItem.Size == 0)
+ // 21.04: we have set processedItems[*] before for all required items
+ if (processedItems[i] != 0
+ // || dirItem.Size == 0
+ // || dirItem.AreReparseData()
+ )
{
- RINOK(callback->DeletingAfterArchiving(phyPath, false));
- DeleteFileAlways(phyPath);
+ NFind::CFileInfo fileInfo;
+ /* if (!SymLinks), we follow link here, similar to (dirItem) filling */
+ if (fileInfo.Find(phyPath, !options.SymLinks.Val))
+ {
+ bool is_SameSize = false;
+ if (options.SymLinks.Val && dirItem.AreReparseData())
+ {
+ /* (dirItem.Size = dirItem.ReparseData.Size()) was set before.
+ So we don't compare sizes for that case here */
+ is_SameSize = fileInfo.IsOsSymLink();
+ }
+ else
+ is_SameSize = (fileInfo.Size == dirItem.Size);
+
+ if (is_SameSize
+ && Compare_FiTime(&fileInfo.MTime, &dirItem.MTime) == 0
+ && Compare_FiTime(&fileInfo.CTime, &dirItem.CTime) == 0)
+ {
+ RINOK(callback->DeletingAfterArchiving(phyPath, false))
+ DeleteFileAlways(phyPath);
+ }
+ }
}
else
{
- // file was skipped
+ // file was skipped by some reason. We can throw error for debug:
/*
errorInfo.SystemError = 0;
errorInfo.Message = "file was not processed";
- errorInfo.FileName = phyPath;
+ errorInfo.FileNames.Add(phyPath);
return E_FAIL;
*/
}
}
}
- pairs.Sort(CompareRefSortPair, NULL);
+ pairs.Sort2();
for (i = 0; i < pairs.Size(); i++)
{
- FString phyPath = dirItems.GetPhyPath(pairs[i].Index);
+ const FString phyPath = dirItems.GetPhyPath(pairs[i].Index);
if (NFind::DoesDirExist(phyPath))
{
- RINOK(callback->DeletingAfterArchiving(phyPath, true));
+ RINOK(callback->DeletingAfterArchiving(phyPath, true))
RemoveDir(phyPath);
}
}
- RINOK(callback->FinishDeletingAfterArchiving());
+ RINOK(callback->FinishDeletingAfterArchiving())
}
return S_OK;