Update to 7-Zip Version 21.06

See https://sourceforge.net/p/sevenzip/discussion/45797/thread/b463f34259/
This commit is contained in:
Tino Reichardt
2022-08-07 09:41:55 +02:00
parent 3e0e78700e
commit e3067bf67b
43 changed files with 1394 additions and 315 deletions

View File

@@ -348,6 +348,8 @@ STDMETHODIMP CArchiveExtractCallback::SetRatioInfo(const UInt64 *inSize, const U
void CArchiveExtractCallback::CreateComplexDirectory(const UStringVector &dirPathParts, FString &fullPath)
{
// we use (_item.IsDir) in this function
bool isAbsPath = false;
if (!dirPathParts.IsEmpty())
@@ -375,12 +377,41 @@ void CArchiveExtractCallback::CreateComplexDirectory(const UStringVector &dirPat
fullPath.Add_PathSepar();
const UString &s = dirPathParts[i];
fullPath += us2fs(s);
const bool isFinalDir = (i == dirPathParts.Size() - 1 && _item.IsDir);
if (fullPath.IsEmpty())
{
if (isFinalDir)
_itemFailure = true;
continue;
}
#if defined(_WIN32) && !defined(UNDER_CE)
if (_pathMode == NExtract::NPathMode::kAbsPaths)
if (i == 0 && s.Len() == 2 && NName::IsDrivePath2(s))
{
if (isFinalDir)
{
// we don't want to call SetAttrib() for root drive path
_itemFailure = true;
}
continue;
}
#endif
// bool res =
CreateDir(fullPath);
// if (!res)
if (isFinalDir)
{
if (!NFile::NFind::DoesDirExist(fullPath))
{
_itemFailure = true;
SendMessageError("Cannot create folder", fullPath);
// SendMessageError_with_LastError()
}
}
}
}
@@ -655,6 +686,7 @@ HRESULT CArchiveExtractCallback::ReadLink()
{
IInArchive *archive = _arc->Archive;
const UInt32 index = _index;
_link.Clear();
{
NCOM::CPropVariant prop;
@@ -717,7 +749,8 @@ HRESULT CArchiveExtractCallback::ReadLink()
if (propType != NPropDataType::kRaw)
return E_FAIL;
#ifdef _WIN32
// 21.06: we need kpidNtReparse in linux for wim archives created in Windows
// #ifdef _WIN32
NtReparse_Data = data;
NtReparse_Size = dataSize;
@@ -739,11 +772,14 @@ HRESULT CArchiveExtractCallback::ReadLink()
else
_link.isRelative = reparse.IsRelative_Win();
// const AString s = GetAnsiString(_link.linkPath);
// printf("\n_link.linkPath: %s\n", s.Ptr());
#ifndef _WIN32
_link.linkPath.Replace(L'\\', WCHAR_PATH_SEPARATOR);
#endif
}
#endif
// #endif
}
}
@@ -908,7 +944,10 @@ void CArchiveExtractCallback::CreateFolders()
if (!_item.IsDir)
return;
CDirPathTime &pt = _extractedFolders.AddNew();
if (_itemFailure)
return;
CDirPathTime pt;
pt.CTime = _fi.CTime;
pt.CTimeDefined = (WriteCTime && _fi.CTimeDefined);
@@ -931,9 +970,13 @@ void CArchiveExtractCallback::CreateFolders()
pt.MTimeDefined = true;
}
}
pt.Path = fullPathNew;
pt.SetDirTime();
if (pt.MTimeDefined || pt.ATimeDefined || pt.CTimeDefined)
{
pt.Path = fullPathNew;
pt.SetDirTime();
_extractedFolders.Add(pt);
}
}
@@ -1125,7 +1168,11 @@ HRESULT CArchiveExtractCallback::GetExtractStream(CMyComPtr<ISequentialOutStream
#ifdef SUPPORT_LINKS
if (_link.linkPath.IsEmpty())
#endif
{
if (!isAnti)
SetAttrib();
return S_OK;
}
}
else if (!_isSplit)
{
@@ -1154,6 +1201,12 @@ HRESULT CArchiveExtractCallback::GetExtractStream(CMyComPtr<ISequentialOutStream
{
bool linkWasSet = false;
RINOK(SetFromLinkPath(fullProcessedPath, _link, linkWasSet));
if (linkWasSet)
{
_isSymLinkCreated = _link.IsSymLink();
SetAttrib();
// printf("\nlinkWasSet %s\n", GetAnsiString(_diskFilePath));
}
}
#endif // UNDER_CE
@@ -1186,6 +1239,9 @@ HRESULT CArchiveExtractCallback::GetExtractStream(CMyComPtr<ISequentialOutStream
return S_OK;
}
// printf("\nHard linkWasSet Archive_Get_HardLinkNode %s\n", GetAnsiString(_diskFilePath));
// _needSetAttrib = true; // do we need to set attribute ?
SetAttrib();
needExit = false;
return S_OK;
}
@@ -1210,22 +1266,25 @@ HRESULT CArchiveExtractCallback::GetExtractStream(CMyComPtr<ISequentialOutStream
}
}
_fileWasExtracted = true;
_needSetAttrib = true;
bool is_SymLink_in_Data = false;
if (_curSizeDefined && _curSize > 0 && _curSize < (1 << 12))
{
if (_fi.IsLinuxSymLink())
{
_is_SymLink_in_Data = true;
is_SymLink_in_Data = true;
_is_SymLink_in_Data_Linux = true;
}
else if (_fi.IsReparse())
{
_is_SymLink_in_Data = true;
is_SymLink_in_Data = true;
_is_SymLink_in_Data_Linux = false;
}
}
if (_is_SymLink_in_Data)
if (is_SymLink_in_Data)
{
_outMemBuf.Alloc((size_t)_curSize);
_bufPtrSeqOutStream_Spec = new CBufPtrSeqOutStream;
@@ -1347,17 +1406,36 @@ STDMETHODIMP CArchiveExtractCallback::GetStream(UInt32 index, ISequentialOutStre
_diskFilePath.Empty();
_isRenamed = false;
// _fi.Clear();
_is_SymLink_in_Data = false;
_is_SymLink_in_Data_Linux = false;
_fileWasExtracted = false;
// _is_SymLink_in_Data = false;
_is_SymLink_in_Data_Linux = false;
_needSetAttrib = false;
_isSymLinkCreated = false;
_itemFailure = false;
#ifdef SUPPORT_LINKS
// _CopyFile_Path.Empty();
_link.Clear();
#endif
_extractMode = false;
switch (askExtractMode)
{
case NArchive::NExtract::NAskMode::kExtract:
if (_testMode)
{
// askExtractMode = NArchive::NExtract::NAskMode::kTest;
}
else
_extractMode = true;
break;
};
IInArchive *archive = _arc->Archive;
RINOK(GetItem(index));
@@ -1832,6 +1910,7 @@ HRESULT CArchiveExtractCallback::SetFromLinkPath(
bool CLinkInfo::Parse(const Byte *data, size_t dataSize, bool isLinuxData)
{
Clear();
// this->isLinux = isLinuxData;
if (isLinuxData)
@@ -1955,10 +2034,20 @@ HRESULT CArchiveExtractCallback::CloseReparseAndFile()
RINOK(SendMessageError_with_LastError("can't delete file", _diskFilePath));
}
{
/*
// for DEBUG ONLY: we can extract sym links as WSL links
// to elimanate (non-admin) errors for sym links.
#ifdef _WIN32
if (!linkInfo.isHardLink && !linkInfo.isJunction)
linkInfo.isWSL = true;
#endif
*/
bool linkWasSet = false;
RINOK(SetFromLinkPath(_diskFilePath, linkInfo, linkWasSet));
if (!linkWasSet)
_fileWasExtracted = false;
if (linkWasSet)
_isSymLinkCreated = linkInfo.IsSymLink();
else
_needSetAttrib = false;
}
/*
if (!NFile::NIO::SetReparseData(_diskFilePath, _item.IsDir, ))
@@ -1974,11 +2063,40 @@ HRESULT CArchiveExtractCallback::CloseReparseAndFile()
}
void CArchiveExtractCallback::SetAttrib()
{
#ifndef _WIN32
// Linux now doesn't support permissions for symlinks
if (_isSymLinkCreated)
return;
#endif
if (_itemFailure
|| _diskFilePath.IsEmpty()
|| _stdOutMode
|| !_extractMode
|| !_fi.AttribDefined)
return;
{
// const AString s = GetAnsiString(_diskFilePath);
// printf("\nSetFileAttrib_PosixHighDetect: %s: hex:%x\n", s.Ptr(), _fi.Attrib);
bool res = SetFileAttrib_PosixHighDetect(_diskFilePath, _fi.Attrib);
if (!res)
{
// do we need error message here in Windows and in posix?
SendMessageError_with_LastError("Cannot set file attribute", _diskFilePath);
}
}
}
STDMETHODIMP CArchiveExtractCallback::SetOperationResult(Int32 opRes)
{
COM_TRY_BEGIN
// printf("\nCArchiveExtractCallback::SetOperationResult: %d %s\n", opRes, GetAnsiString(_diskFilePath));
#ifndef _SFX
if (ExtractToStreamCallback)
{
@@ -2052,16 +2170,8 @@ STDMETHODIMP CArchiveExtractCallback::SetOperationResult(Int32 opRes)
else
NumFiles++;
if (_fileWasExtracted)
if (!_stdOutMode && _extractMode && _fi.AttribDefined)
{
bool res = SetFileAttrib_PosixHighDetect(_diskFilePath, _fi.Attrib);
if (!res)
{
// do we need error message here in Windows and in posix?
SendMessageError_with_LastError("Cannot set file attribute", _diskFilePath);
}
}
if (_needSetAttrib)
SetAttrib();
RINOK(_extractCallback2->SetOperationResult(opRes, BoolToInt(_encrypted)));

View File

@@ -189,7 +189,17 @@ struct CLinkInfo
bool isRelative;
bool isWSL;
UString linkPath;
bool IsSymLink() const { return !isHardLink; }
CLinkInfo():
// IsCopyLink(false),
isHardLink(false),
isJunction(false),
isRelative(false),
isWSL(false)
{}
void Clear()
{
// IsCopyLink = false;
@@ -291,10 +301,12 @@ class CArchiveExtractCallback:
}
} _fi;
bool _is_SymLink_in_Data;
// bool _is_SymLink_in_Data;
bool _is_SymLink_in_Data_Linux; // false = WIN32, true = LINUX
bool _fileWasExtracted;
bool _needSetAttrib;
bool _isSymLinkCreated;
bool _itemFailure;
UInt32 _index;
UInt64 _curSize;
@@ -352,6 +364,8 @@ class CArchiveExtractCallback:
FString Hash_GetFullFilePath();
void SetAttrib();
public:
HRESULT SendMessageError(const char *message, const FString &path);
HRESULT SendMessageError_with_LastError(const char *message, const FString &path);

View File

@@ -118,7 +118,9 @@ struct CDirItem
UInt32 GetPosixAttrib() const
{
UInt32 v = IsDir() ? MY_LIN_S_IFDIR : MY_LIN_S_IFREG;
v |= (IsReadOnly() ? 0555 : 0777);
/* 21.06: as WSL we allow write permissions (0222) for directories even for (FILE_ATTRIBUTE_READONLY).
So extracting at Linux will be allowed to write files inside (0777) directories. */
v |= ((IsReadOnly() && !IsDir()) ? 0555 : 0777);
return v;
}
#endif

View File

@@ -2,14 +2,15 @@
#include "StdAfx.h"
#include "../../../../C/CpuArch.h"
#include "../../../Common/IntToString.h"
#include "../../../Common/StringToInt.h"
#include "../../../Windows/FileDir.h"
#include "../../../Windows/Registry.h"
#include "../../../Windows/Synchronization.h"
#include "../FileManager/RegistryUtils.h"
#include "ZipRegistry.h"
using namespace NWindows;
@@ -69,7 +70,6 @@ void CInfo::Save() const
CS_LOCK
CKey key;
CreateMainKey(key, kKeyName);
UStringVector Empty;
if (PathMode_Force)
key.SetValue(kExtractMode, (UInt32)PathMode);
@@ -83,10 +83,7 @@ void CInfo::Save() const
Key_Set_BoolPair(key, kShowPassword, ShowPassword);
key.RecurseDeleteKey(kPathHistory);
if (WantPathHistory())
key.SetValue_Strings(kPathHistory, Paths);
else
key.SetValue_Strings(kPathHistory, Empty);
key.SetValue_Strings(kPathHistory, Paths);
}
void Save_ShowPassword(bool showPassword)
@@ -166,7 +163,6 @@ static LPCTSTR const kBlockSize = TEXT("BlockSize");
static LPCTSTR const kNumThreads = TEXT("NumThreads");
static LPCWSTR const kMethod = L"Method";
static LPCWSTR const kOptions = L"Options";
static LPCWSTR const kSplitVolume = L"SplitVolume";
static LPCWSTR const kEncryptionMethod = L"EncryptionMethod";
static LPCTSTR const kNtSecur = TEXT("Security");
@@ -202,9 +198,15 @@ static void GetRegUInt32(CKey &key, LPCTSTR name, UInt32 &value)
value = (UInt32)(Int32)-1;
}
static LPCWSTR const kMemUse = L"MemUse"
#if defined(MY_CPU_SIZEOF_POINTER) && (MY_CPU_SIZEOF_POINTER == 4)
L"32";
#else
L"64";
#endif
void CInfo::Save() const
{
UStringVector Empty;
CS_LOCK
CKey key;
@@ -221,11 +223,7 @@ void CInfo::Save() const
key.SetValue(kShowPassword, ShowPassword);
key.SetValue(kEncryptHeaders, EncryptHeaders);
key.RecurseDeleteKey(kArcHistory);
if (WantArcHistory())
key.SetValue_Strings(kArcHistory, ArcPaths);
else
key.SetValue_Strings(kArcHistory, Empty);
key.SetValue_Strings(kArcHistory, ArcPaths);
key.RecurseDeleteKey(kOptionsKeyName);
{
@@ -245,8 +243,8 @@ void CInfo::Save() const
SetRegString(fk, kMethod, fo.Method);
SetRegString(fk, kOptions, fo.Options);
SetRegString(fk, kSplitVolume, fo.SplitVolume);
SetRegString(fk, kEncryptionMethod, fo.EncryptionMethod);
SetRegString(fk, kMemUse, fo.MemUse);
}
}
}
@@ -289,8 +287,8 @@ void CInfo::Load()
{
GetRegString(fk, kMethod, fo.Method);
GetRegString(fk, kOptions, fo.Options);
GetRegString(fk, kSplitVolume, fo.SplitVolume);
GetRegString(fk, kEncryptionMethod, fo.EncryptionMethod);
GetRegString(fk, kMemUse, fo.MemUse);
GetRegUInt32(fk, kLevel, fo.Level);
GetRegUInt32(fk, kDictionary, fo.Dictionary);
@@ -312,6 +310,116 @@ void CInfo::Load()
key.GetValue_IfOk(kEncryptHeaders, EncryptHeaders);
}
static bool ParseMemUse(const wchar_t *s, CMemUse &mu)
{
mu.Clear();
bool percentMode = false;
{
const wchar_t c = *s;
if (MyCharLower_Ascii(c) == 'p')
{
percentMode = true;
s++;
}
}
const wchar_t *end;
UInt64 number = ConvertStringToUInt64(s, &end);
if (end == s)
return false;
wchar_t c = *end;
if (percentMode)
{
if (c != 0)
return false;
mu.IsPercent = true;
mu.Val = number;
return true;
}
if (c == 0)
{
mu.Val = number;
return true;
}
c = MyCharLower_Ascii(c);
const wchar_t c1 = end[1];
if (c == '%')
{
if (c1 != 0)
return false;
mu.IsPercent = true;
mu.Val = number;
return true;
}
if (c == 'b')
{
if (c1 != 0)
return false;
mu.Val = number;
return true;
}
if (c1 != 0)
if (MyCharLower_Ascii(c1) != 'b' || end[2] != 0)
return false;
unsigned numBits;
switch (c)
{
case 'k': numBits = 10; break;
case 'm': numBits = 20; break;
case 'g': numBits = 30; break;
case 't': numBits = 40; break;
default: return false;
}
if (number >= ((UInt64)1 << (64 - numBits)))
return false;
mu.Val = number << numBits;
return true;
}
void CMemUse::Parse(const UString &s)
{
IsDefined = ParseMemUse(s, *this);
}
/*
void MemLimit_Save(const UString &s)
{
CS_LOCK
CKey key;
CreateMainKey(key, kKeyName);
SetRegString(key, kMemUse, s);
}
bool MemLimit_Load(NCompression::CMemUse &mu)
{
mu.Clear();
UString a;
{
CS_LOCK
CKey key;
if (OpenMainKey(key, kKeyName) != ERROR_SUCCESS)
return false;
if (key.QueryValue(kMemUse, a) != ERROR_SUCCESS)
return false;
}
if (a.IsEmpty())
return false;
mu.Parse(a);
return mu.IsDefined;
}
*/
}
static LPCTSTR const kOptionsInfoKeyName = TEXT("Options");

View File

@@ -6,6 +6,8 @@
#include "../../../Common/MyTypes.h"
#include "../../../Common/MyString.h"
#include "../../Common/MethodProps.h"
#include "ExtractMode.h"
namespace NExtract
@@ -35,6 +37,36 @@ namespace NExtract
namespace NCompression
{
struct CMemUse
{
// UString Str;
bool IsDefined;
bool IsPercent;
UInt64 Val;
CMemUse():
IsDefined(false),
IsPercent(false),
Val(0)
{}
void Clear()
{
// Str.Empty();
IsDefined = false;
IsPercent = false;
Val = 0;
}
UInt64 GetBytes(UInt64 ramSize) const
{
if (!IsPercent)
return Val;
return Calc_From_Val_Percents(ramSize, Val);
}
void Parse(const UString &s);
};
struct CFormatOptions
{
UInt32 Level;
@@ -45,9 +77,9 @@ namespace NCompression
CSysString FormatID;
UString Method;
UString SplitVolume;
UString Options;
UString EncryptionMethod;
UString MemUse;
void Reset_BlockLogSize()
{