summaryrefslogtreecommitdiffstatshomepage
path: root/3rdparty/lzma/CPP/7zip/UI/Common/Update.cpp
diff options
context:
space:
mode:
author Vas Crabb <vas@vastheman.com>2023-05-04 02:41:16 +1000
committer Vas Crabb <vas@vastheman.com>2023-05-04 02:41:16 +1000
commita504bde3a7462b54fafd5cfc2f52e58d0f3218e1 (patch)
tree8b3108d572b1a0873a6cdbb4e8af1f17179545c3 /3rdparty/lzma/CPP/7zip/UI/Common/Update.cpp
parentbefb9bf4a8cfdb2b693a32e32535b5eac522c5d8 (diff)
3rdparty/lzma: Updated to LZMA SDK version 22.01
Diffstat (limited to '3rdparty/lzma/CPP/7zip/UI/Common/Update.cpp')
-rw-r--r--3rdparty/lzma/CPP/7zip/UI/Common/Update.cpp725
1 files changed, 518 insertions, 207 deletions
diff --git a/3rdparty/lzma/CPP/7zip/UI/Common/Update.cpp b/3rdparty/lzma/CPP/7zip/UI/Common/Update.cpp
index 0db4a87f0d4..042991d196e 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"
@@ -30,17 +31,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,25 +60,12 @@ 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();
}
@@ -111,7 +103,7 @@ public:
_length = 0;
}
- bool SetMTime(const FILETIME *mTime);
+ bool SetMTime(const CFiTime *mTime);
HRESULT Close();
UInt64 GetSize() const { return _length; }
@@ -141,7 +133,7 @@ HRESULT COutMultiVolStream::Close()
return res;
}
-bool COutMultiVolStream::SetMTime(const FILETIME *mTime)
+bool COutMultiVolStream::SetMTime(const CFiTime *mTime)
{
bool res = true;
FOR_VECTOR (i, Streams)
@@ -156,7 +148,7 @@ bool COutMultiVolStream::SetMTime(const FILETIME *mTime)
STDMETHODIMP COutMultiVolStream::Write(const void *data, UInt32 size, UInt32 *processedSize)
{
- if (processedSize != NULL)
+ if (processedSize)
*processedSize = 0;
while (size > 0)
{
@@ -164,16 +156,15 @@ STDMETHODIMP COutMultiVolStream::Write(const void *data, UInt32 size, UInt32 *pr
{
CAltStreamInfo altStream;
- FChar temp[16];
- ConvertUInt32ToString(_streamIndex + 1, temp);
- FString name = temp;
+ FString name;
+ name.Add_UInt32(_streamIndex + 1);
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();
+ return GetLastError_noZero_HRESULT();
{
// NSynchronization::CCriticalSectionLock lock(g_TempPathsCS);
TempFiles->Paths.Add(name);
@@ -202,14 +193,14 @@ STDMETHODIMP COutMultiVolStream::Write(const void *data, UInt32 size, UInt32 *pr
{
// CMyComPtr<IOutStream> outStream;
// RINOK(altStream.Stream.QueryInterface(IID_IOutStream, &outStream));
- RINOK(altStream.Stream->Seek(_offsetPos, STREAM_SEEK_SET, NULL));
+ RINOK(altStream.Stream->Seek((Int64)_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);
+ data = (const void *)((const Byte *)data + realProcessed);
size -= realProcessed;
altStream.Pos += realProcessed;
_offsetPos += realProcessed;
@@ -218,7 +209,7 @@ STDMETHODIMP COutMultiVolStream::Write(const void *data, UInt32 size, UInt32 *pr
_length = _absPos;
if (_offsetPos > altStream.RealSize)
altStream.RealSize = _offsetPos;
- if (processedSize != NULL)
+ if (processedSize)
*processedSize += realProcessed;
if (altStream.Pos == volSize)
{
@@ -238,12 +229,12 @@ STDMETHODIMP COutMultiVolStream::Seek(Int64 offset, UInt32 seekOrigin, UInt64 *n
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;
+ case STREAM_SEEK_SET: _absPos = (UInt64)offset; break;
+ case STREAM_SEEK_CUR: _absPos = (UInt64)((Int64)_absPos + offset); break;
+ case STREAM_SEEK_END: _absPos = (UInt64)((Int64)_length + offset); break;
}
_offsetPos = _absPos;
- if (newPosition != NULL)
+ if (newPosition)
*newPosition = _absPos;
_streamIndex = 0;
return S_OK;
@@ -286,29 +277,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 +305,7 @@ UString CArchivePath::GetFinalPath() const
UString path = GetPathWithoutExt();
if (!BaseExtension.IsEmpty())
{
- path += L'.';
+ path += '.';
path += BaseExtension;
}
return path;
@@ -325,9 +314,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 += '.';
path += VolExtension;
}
return path;
@@ -339,17 +329,17 @@ FString CArchivePath::GetTempPath() const
path += us2fs(Name);
if (!BaseExtension.IsEmpty())
{
- path += FTEXT('.');
+ path += '.';
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 +381,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 +402,43 @@ bool CUpdateOptions::SetArcPath(const CCodecs *codecs, const UString &arcPath)
return true;
}
+
struct CUpdateProduceCallbackImp: public IUpdateProduceCallback
{
const CObjectVector<CArcItem> *_arcItems;
+ CDirItemsStat *_stat;
IUpdateCallbackUI *_callback;
- CUpdateProduceCallbackImp(const CObjectVector<CArcItem> *a,
- IUpdateCallbackUI *callback): _arcItems(a), _callback(callback) {}
+ CUpdateProduceCallbackImp(
+ const CObjectVector<CArcItem> *a,
+ CDirItemsStat *stat,
+ IUpdateCallbackUI *callback):
+ _arcItems(a),
+ _stat(stat),
+ _callback(callback) {}
+
virtual HRESULT ShowDeleteFile(unsigned arcIndex);
};
+
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);
}
@@ -516,7 +530,7 @@ static HRESULT Compress(
}
else
{
- RINOK(codecs->CreateOutArchive(formatIndex, outArchive));
+ RINOK(codecs->CreateOutArchive((unsigned)formatIndex, outArchive));
#ifdef EXTERNAL_CODECS
{
@@ -530,14 +544,49 @@ static HRESULT Compress(
#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));
+
+ // we support any future fileType here.
+ fileTimeType = (NFileTimeType::EEnum)value;
+ /*
+ old 21.07 code:
switch (value)
{
case NFileTimeType::kWindows:
@@ -548,13 +597,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 +626,8 @@ static HRESULT Compress(
UStringVector newNames;
+ CArcToDoStat stat2;
+
if (options.RenamePairs.Size() != 0)
{
FOR_VECTOR (i, arcItems)
@@ -587,7 +653,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 +661,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 +676,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 +686,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 +792,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 +801,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;
@@ -698,9 +851,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();
}
@@ -734,7 +886,7 @@ static HRESULT Compress(
outStream = outSeekStream;
volStreamSpec->Sizes = options.VolumesSizes;
volStreamSpec->Prefix = us2fs(archivePath.GetFinalVolPath());
- volStreamSpec->Prefix += FTEXT('.');
+ volStreamSpec->Prefix += '.';
volStreamSpec->TempFiles = &tempFiles;
volStreamSpec->Init();
@@ -742,12 +894,10 @@ static HRESULT Compress(
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;
@@ -817,29 +967,76 @@ static HRESULT Compress(
if (options.SetArcMTime)
{
- FILETIME ft;
- ft.dwLowDateTime = 0;
- ft.dwHighDateTime = 0;
- FOR_VECTOR (i, updatePairs2)
+ CFiTime ft;
+ FiTime_Clear(ft);
+ bool isDefined = false;
+
+ // 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)
+ {
+ // CArcTime at = StreamCallback_ArcMTime;
+ // updateCallbackSpec->StreamCallback_ArcMTime.Write_To_FiTime(ft);
+ // we must normalize with precision from archive;
+ ft = updateCallbackSpec->LatestMTime;
+ isDefined = true;
+ }
+
+ FOR_VECTOR (i, updatePairs2)
{
- if (::CompareFileTime(&ft, ft2) < 0)
- ft = *ft2;
+ const CUpdatePair2 &pair2 = updatePairs2[i];
+ CFiTime 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 (Compare_FiTime(&ft, &ft2) < 0)
+ {
+ ft = ft2;
+ isDefined = 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 (isDefined)
{
if (outStreamSpec)
outStreamSpec->SetMTime(&ft);
else if (volStreamSpec)
- volStreamSpec->SetMTime(&ft);;
+ volStreamSpec->SetMTime(&ft);
}
}
@@ -860,9 +1057,39 @@ static HRESULT Compress(
result = outStreamSpec->Close();
else if (volStreamSpec)
result = volStreamSpec->Close();
+
+ 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 +1097,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;
@@ -895,6 +1126,8 @@ static HRESULT EnumerateInArchiveItems(
CReadArcItem item;
+ const bool allFilesAreAllowed = Censor_AreAllAllowed(censor);
+
for (UInt32 i = 0; i < numItems; i++)
{
CArcItem ai;
@@ -913,28 +1146,14 @@ static HRESULT EnumerateInArchiveItems(
if (!storeStreamsMode && ai.IsAltStream)
continue;
*/
- ai.Censored = Censor_CheckPath(censor, item);
-
- RINOK(arc.GetItemMTime(i, ai.MTime, ai.MTimeDefined));
- RINOK(arc.GetItemSize(i, ai.Size, ai.SizeDefined));
+ if (allFilesAreAllowed)
+ ai.Censored = true;
+ else
+ ai.Censored = Censor_CheckPath(censor, item);
- {
- 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,38 +1163,8 @@ static HRESULT EnumerateInArchiveItems(
#if defined(_WIN32) && !defined(UNDER_CE)
-#include <mapi.h>
-
-#endif
-
-struct CRefSortPair
-{
- unsigned Len;
- unsigned Index;
-};
-
-#define RINOZ(x) { int __tt = (x); if (__tt != 0) return __tt; }
-
-static int CompareRefSortPair(const CRefSortPair *a1, const CRefSortPair *a2, void *)
-{
- RINOZ(-MyCompare(a1->Len, a2->Len));
- return MyCompare(a1->Index, a2->Index);
-}
-
-static unsigned GetNumSlashes(const FChar *s)
-{
- for (unsigned numSlashes = 0;;)
- {
- FChar c = *s++;
- if (c == 0)
- return numSlashes;
- if (IS_PATH_SEPAR(c))
- numSlashes++;
- }
-}
+#include <MAPI.h>
-#ifdef _WIN32
-void ConvertToLongNames(NWildcard::CCensor &censor);
#endif
HRESULT UpdateArchive(
@@ -1007,7 +1196,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 +1214,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 +1225,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 +1233,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 +1247,15 @@ 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 += '.';
+ arcPath += "001";
+ }
if (cmdArcPath2.IsEmpty())
{
@@ -1068,7 +1265,7 @@ HRESULT UpdateArchive(
else
{
NFind::CFileInfo fi;
- if (!fi.Find(us2fs(arcPath)))
+ if (!fi.Find_FollowLink(us2fs(arcPath)))
{
if (renameMode)
throw "can't find archive";;
@@ -1081,11 +1278,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)
@@ -1121,18 +1346,24 @@ HRESULT UpdateArchive(
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 +1378,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 +1403,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);
}
@@ -1199,10 +1431,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)
@@ -1214,11 +1454,13 @@ HRESULT UpdateArchive(
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 += '.';
// UString prefix = censor.Pairs[0].Prefix;
/*
if (prefix.Back() == WCHAR_PATH_SEPARATOR)
@@ -1229,11 +1471,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 +1480,6 @@ HRESULT UpdateArchive(
dirItems.AddSecurityItem(prefix, secureIndex);
#endif
parentDirItem.SecureIndex = secureIndex;
-
- parentDirItem_Ptr = &parentDirItem;
}
}
}
@@ -1286,6 +1522,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;
@@ -1328,7 +1589,7 @@ 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;
@@ -1353,7 +1614,7 @@ HRESULT UpdateArchive(
if (options.StdOutMode)
{
- name.SetFromAscii("stdout");
+ name = "stdout";
isUpdating = thereIsInArchive;
}
else
@@ -1399,9 +1660,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 +1674,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(...)
{
@@ -1437,7 +1711,7 @@ HRESULT UpdateArchive(
}
*/
- LPMAPISENDMAIL sendMail = (LPMAPISENDMAIL)mapiLib.GetProc("MAPISendMail");
+ LPMAPISENDMAIL sendMail = (LPMAPISENDMAIL)(void *)mapiLib.GetProc("MAPISendMail");
if (sendMail == 0)
{
errorInfo.SetFromLastError("7-Zip cannot find MAPISendMail function");
@@ -1458,34 +1732,47 @@ HRESULT UpdateArchive(
}
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;
}
@@ -1498,7 +1785,7 @@ HRESULT UpdateArchive(
if (options.DeleteAfterCompressing)
{
- CRecordVector<CRefSortPair> pairs;
+ CRecordVector<CDirPathSortPair> pairs;
FStringVector foldersNames;
unsigned i;
@@ -1506,39 +1793,63 @@ 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));