This commit is contained in:
Igor Pavlov 2026-02-12 00:00:00 +00:00
parent 5e96a82794
commit 839151eaaa
56 changed files with 1764 additions and 984 deletions

View file

@ -1,7 +1,7 @@
#define MY_VER_MAJOR 25
#define MY_VER_MINOR 1
#define MY_VER_MAJOR 26
#define MY_VER_MINOR 0
#define MY_VER_BUILD 0
#define MY_VERSION_NUMBERS "25.01"
#define MY_VERSION_NUMBERS "26.00"
#define MY_VERSION MY_VERSION_NUMBERS
#ifdef MY_CPU_NAME
@ -10,12 +10,12 @@
#define MY_VERSION_CPU MY_VERSION
#endif
#define MY_DATE "2025-08-03"
#define MY_DATE "2026-02-12"
#undef MY_COPYRIGHT
#undef MY_VERSION_COPYRIGHT_DATE
#define MY_AUTHOR_NAME "Igor Pavlov"
#define MY_COPYRIGHT_PD "Igor Pavlov : Public domain"
#define MY_COPYRIGHT_CR "Copyright (c) 1999-2025 Igor Pavlov"
#define MY_COPYRIGHT_CR "Copyright (c) 1999-2026 Igor Pavlov"
#ifdef USE_COPYRIGHT_CR
#define MY_COPYRIGHT MY_COPYRIGHT_CR

View file

@ -1,11 +1,17 @@
/* 7zWindows.h -- StdAfx
2023-04-02 : Igor Pavlov : Public domain */
/* 7zWindows.h -- Windows.h and related code
Igor Pavlov : Public domain */
#ifndef ZIP7_INC_7Z_WINDOWS_H
#define ZIP7_INC_7Z_WINDOWS_H
#ifdef _WIN32
#if defined(_MSC_VER) && _MSC_VER >= 1950 && !defined(__clang__) // VS2026
// <Windows.h> and some another windows files need that option
// VS2026: wtypesbase.h: warning C4865: 'tagCLSCTX': the underlying type will change from 'int' to 'unsigned int' when '/Zc:enumTypes' is specified on the command line
#pragma warning(disable : 4865)
#endif
#if defined(__clang__)
# pragma clang diagnostic push
#endif

View file

@ -106,7 +106,7 @@ DEL_OBJ_EXE = -$(RM) $(O)\*.o $(O)\$(PROG).exe $(O)\$(PROG).dll
endif
LIB2 = -lOle32 -loleaut32 -luuid -ladvapi32 -lUser32 -lShell32
LIB2 = -lole32 -loleaut32 -luuid -ladvapi32 -luser32 -lshell32
CFLAGS_EXTRA = -DUNICODE -D_UNICODE
# -Wno-delete-non-virtual-dtor

View file

@ -859,7 +859,7 @@ BoolInt CPU_IsSupported_AES (void) { return APPLE_CRYPTO_SUPPORT_VAL; }
#if defined(__GLIBC__) && (__GLIBC__ * 100 + __GLIBC_MINOR__ >= 216)
#define Z7_GETAUXV_AVAILABLE
#else
#elif !defined(__QNXNTO__)
// #pragma message("=== is not NEW GLIBC === ")
#if defined __has_include
#if __has_include (<sys/auxv.h>)
@ -877,7 +877,7 @@ BoolInt CPU_IsSupported_AES (void) { return APPLE_CRYPTO_SUPPORT_VAL; }
#ifdef USE_HWCAP
#if defined(__FreeBSD__)
#if defined(__FreeBSD__) || defined(__OpenBSD__)
static unsigned long MY_getauxval(int aux)
{
unsigned long val;

View file

@ -31,7 +31,12 @@ MY_CPU_64BIT means that processor can work with 64-bit registers.
#define MY_CPU_NAME "x32"
#define MY_CPU_SIZEOF_POINTER 4
#else
#define MY_CPU_NAME "x64"
#if defined(__APX_EGPR__) || defined(__EGPR__)
#define MY_CPU_NAME "x64-apx"
#define MY_CPU_AMD64_APX
#else
#define MY_CPU_NAME "x64"
#endif
#define MY_CPU_SIZEOF_POINTER 8
#endif
#define MY_CPU_64BIT
@ -596,8 +601,20 @@ problem-4 : performace:
#define SetBe32a(p, v) { *(UInt32 *)(void *)(p) = (v); }
#define SetBe16a(p, v) { *(UInt16 *)(void *)(p) = (v); }
// gcc and clang for powerpc can transform load byte access to load reverse word access.
// sp we can use byte access instead of word access. Z7_BSWAP64 cab be slow
#if 1 && defined(Z7_CPU_FAST_BSWAP_SUPPORTED) && defined(MY_CPU_64BIT)
#define GetUi64a(p) Z7_BSWAP64 (*(const UInt64 *)(const void *)(p))
#else
#define GetUi64a(p) GetUi64(p)
#endif
#if 1 && defined(Z7_CPU_FAST_BSWAP_SUPPORTED)
#define GetUi32a(p) Z7_BSWAP32 (*(const UInt32 *)(const void *)(p))
#else
#define GetUi32a(p) GetUi32(p)
#endif
#define GetUi16a(p) GetUi16(p)
#define SetUi32a(p, v) SetUi32(p, v)
#define SetUi16a(p, v) SetUi16(p, v)

View file

@ -13,7 +13,7 @@ Igor Pavlov : Public domain */
#define NUM_BITS 10
#define MASK ((1u << NUM_BITS) - 1)
#define FREQ_MASK (~(UInt32)MASK)
#define NUM_COUNTERS (48 * 2)
#define NUM_COUNTERS (104 * 2) // (80 * 2) or (128 * 2) : ((prime_number + 1) * 2) for smaller code.
#if 1 && (defined(MY_CPU_LE) || defined(MY_CPU_BE))
#if defined(MY_CPU_LE)
@ -95,9 +95,10 @@ void Huffman_Generate(const UInt32 *freqs, UInt32 *p, Byte *lens, unsigned numSy
counters[1] = 0;
for (i = 2; i != NUM_COUNTERS; i += 2)
{
unsigned c;
c = (counters )[i]; (counters )[i] = num; num += c;
c = (counters + 1)[i]; (counters + 1)[i] = num; num += c;
const unsigned c0 = (counters )[i];
const unsigned c1 = (counters + 1)[i];
(counters )[i] = num; num += c0;
(counters + 1)[i] = num; num += c1;
}
counters[0] = num; // we want to write (freq==0) symbols to the end of (p) array
{

View file

@ -16,7 +16,7 @@ Conditions:
1 <= maxLen <= 16 = Z7_HUFFMAN_LEN_MAX
Num_Items(p) >= HUFFMAN_TEMP_SIZE(num)
*/
void Huffman_Generate(const UInt32 *freqs, UInt32 *p, Byte *lens, UInt32 num, UInt32 maxLen);
void Huffman_Generate(const UInt32 *freqs, UInt32 *p, Byte *lens, unsigned num, unsigned maxLen);
EXTERN_C_END

View file

@ -1,6 +1,6 @@
/* Xxh64.c -- XXH64 hash calculation
original code: Copyright (c) Yann Collet.
2023-08-18 : modified by Igor Pavlov.
modified by Igor Pavlov.
This source code is licensed under BSD 2-Clause License.
*/
@ -27,6 +27,14 @@ void Xxh64State_Init(CXxh64State *p)
#if !defined(MY_CPU_64BIT) && defined(MY_CPU_X86) && defined(_MSC_VER)
#define Z7_XXH64_USE_ASM
#elif !defined(MY_CPU_LE_UNALIGN_64) // && defined (MY_CPU_LE)
#define Z7_XXH64_USE_ALIGNED
#endif
#ifdef Z7_XXH64_USE_ALIGNED
#define Xxh64State_UpdateBlocks_Unaligned_Select Xxh64State_UpdateBlocks_Unaligned
#else
#define Xxh64State_UpdateBlocks_Unaligned_Select Xxh64State_UpdateBlocks
#endif
#if !defined(MY_CPU_64BIT) && defined(MY_CPU_X86) \
@ -188,32 +196,76 @@ Xxh64State_UpdateBlocks(CXxh64State *p, const void *data, const void *end)
#else
#ifdef Z7_XXH64_USE_ALIGNED
static
#endif
void
Z7_NO_INLINE
Z7_FASTCALL
Xxh64State_UpdateBlocks(CXxh64State *p, const void *_data, const void *end)
Xxh64State_UpdateBlocks_Unaligned_Select(CXxh64State *p, const void *_data, const void *end)
{
const Byte *data = (const Byte *)_data;
UInt64 v[4];
v[0] = p->v[0];
v[1] = p->v[1];
v[2] = p->v[2];
v[3] = p->v[3];
UInt64 v0, v1, v2, v3;
v0 = p->v[0];
v1 = p->v[1];
v2 = p->v[2];
v3 = p->v[3];
do
{
v[0] = Xxh64_Round(v[0], GetUi64(data)); data += 8;
v[1] = Xxh64_Round(v[1], GetUi64(data)); data += 8;
v[2] = Xxh64_Round(v[2], GetUi64(data)); data += 8;
v[3] = Xxh64_Round(v[3], GetUi64(data)); data += 8;
v0 = Xxh64_Round(v0, GetUi64(data)); data += 8;
v1 = Xxh64_Round(v1, GetUi64(data)); data += 8;
v2 = Xxh64_Round(v2, GetUi64(data)); data += 8;
v3 = Xxh64_Round(v3, GetUi64(data)); data += 8;
}
while (data != end);
p->v[0] = v[0];
p->v[1] = v[1];
p->v[2] = v[2];
p->v[3] = v[3];
p->v[0] = v0;
p->v[1] = v1;
p->v[2] = v2;
p->v[3] = v3;
}
#endif
#ifdef Z7_XXH64_USE_ALIGNED
static
void
Z7_NO_INLINE
Z7_FASTCALL
Xxh64State_UpdateBlocks_Aligned(CXxh64State *p, const void *_data, const void *end)
{
const Byte *data = (const Byte *)_data;
UInt64 v0, v1, v2, v3;
v0 = p->v[0];
v1 = p->v[1];
v2 = p->v[2];
v3 = p->v[3];
do
{
v0 = Xxh64_Round(v0, GetUi64a(data)); data += 8;
v1 = Xxh64_Round(v1, GetUi64a(data)); data += 8;
v2 = Xxh64_Round(v2, GetUi64a(data)); data += 8;
v3 = Xxh64_Round(v3, GetUi64a(data)); data += 8;
}
while (data != end);
p->v[0] = v0;
p->v[1] = v1;
p->v[2] = v2;
p->v[3] = v3;
}
void
Z7_NO_INLINE
Z7_FASTCALL
Xxh64State_UpdateBlocks(CXxh64State *p, const void *data, const void *end)
{
if (((unsigned)(ptrdiff_t)data & 7) == 0)
Xxh64State_UpdateBlocks_Aligned(p, data, end);
else
Xxh64State_UpdateBlocks_Unaligned(p, data, end);
}
#endif // Z7_XXH64_USE_ALIGNED
#endif // Z7_XXH64_USE_ASM
UInt64 Xxh64State_Digest(const CXxh64State *p, const void *_data, UInt64 count)
{
@ -306,12 +358,22 @@ void Xxh64_Update(CXxh64 *p, const void *_data, size_t size)
while (--rem);
if (cnt != 32)
return;
Xxh64State_UpdateBlocks(&p->state, p->buf64, &p->buf64[4]);
#ifdef Z7_XXH64_USE_ALIGNED
Xxh64State_UpdateBlocks_Aligned
#else
Xxh64State_UpdateBlocks_Unaligned_Select
#endif
(&p->state, p->buf64, &p->buf64[4]);
}
if (size &= ~(size_t)31)
{
Xxh64State_UpdateBlocks(&p->state, data, data + size);
#ifdef Z7_XXH64_USE_ALIGNED
if (((unsigned)(ptrdiff_t)data & 7) == 0)
Xxh64State_UpdateBlocks_Aligned(&p->state, data, data + size);
else
#endif
Xxh64State_UpdateBlocks_Unaligned_Select(&p->state, data, data + size);
data += size;
}

View file

@ -142,8 +142,8 @@ MY_MKDIR=mkdir
DEL_OBJ_EXE = -$(RM) $(O)\*.o $(O)\$(PROG).exe $(O)\$(PROG).dll
endif
LIB2_GUI = -lOle32 -lGdi32 -lComctl32 -lComdlg32 -lShell32 $(LIB_HTMLHELP)
LIB2 = -loleaut32 -luuid -ladvapi32 -lUser32 $(LIB2_GUI)
LIB2_GUI = -lole32 -lgdi32 -lcomctl32 -lcomdlg32 -lshell32 $(LIB_HTMLHELP)
LIB2 = -loleaut32 -luuid -ladvapi32 -luser32 $(LIB2_GUI)
# v24.00: -DUNICODE and -D_UNICODE are defined in precompilation header files
# CXXFLAGS_EXTRA = -DUNICODE -D_UNICODE

View file

@ -721,7 +721,7 @@ static int CompareEmptyItems(const unsigned *p1, const unsigned *p2, void *param
return (u1.IsDir && u1.IsAnti) ? -n : n;
}
static const char *g_Exts =
static const char * const g_Exts =
" 7z xz lzma ace arc arj bz tbz bz2 tbz2 cab deb gz tgz ha lha lzh lzo lzx pak rar rpm sit zoo"
" zip jar ear war msi"
" 3gp avi mov mpeg mpg mpe wmv"

File diff suppressed because it is too large Load diff

View file

@ -927,7 +927,7 @@ Z7_COM7F_IMF(CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *val
{
#ifdef _WIN32
UString u;
ConvertUTF8ToUnicode(item.Name, u);
ConvertUTF8ToUnicode(s, u);
#else
const UString u = MultiByteToUnicodeString(s, CP_OEMCP);
#endif

View file

@ -482,6 +482,10 @@ HRESULT CHandler::Open2(IInStream *stream, IArchiveOpenCallback *openCallback)
if (_phySize < headerSize)
_phySize = headerSize;
// we use 32 MiB limit for L1 size, as QEMU with QCOW_MAX_L1_SIZE limit.
if (l1Size > (1u << 22)) // if (l1Size > (1u << (sizeof(size_t) * 8 - 4)))
return S_FALSE;
_isArc = true;
{
const UInt64 backOffset = Get64((const Byte *)(const void *)buf64 + 8);
@ -519,7 +523,6 @@ HRESULT CHandler::Open2(IInStream *stream, IArchiveOpenCallback *openCallback)
}
CObjArray<UInt64> table64(l1Size);
{
// if ((t1SizeBytes >> 3) != l1Size) return S_FALSE;
RINOK(InStream_SeekSet(stream, l1Offset))
RINOK(ReadStream_FALSE(stream, table64, t1SizeBytes))
}

View file

@ -8,6 +8,7 @@
#include "../../../Common/ComTry.h"
#include "../../../Common/IntToString.h"
#include "../../../Common/MyBuffer2.h"
#include "../../../Common/MyLinux.h"
#include "../../../Common/UTFConvert.h"
#include "../../../Windows/PropVariantUtils.h"
@ -1184,7 +1185,15 @@ HRESULT CUnpacker::Code(const CItem &item, const CItem &lastItem, UInt64 packSiz
const UInt64 processedSize = outStream->GetPos();
if (res == S_OK && !lastItem.Is_UnknownSize() && processedSize != lastItem.Size)
res = S_FALSE;
{
// rar_v7.13-: linux archive contains symLink with (packSize == 0 && lastItem.Size != 0)
// v25.02: we ignore such record in rar headers:
if (packSize != 0
|| method != 0
|| lastItem.HostOS != kHost_Unix
|| !MY_LIN_S_ISLNK(lastItem.Attrib))
res = S_FALSE;
}
// if (res == S_OK)
{

View file

@ -7,6 +7,7 @@
#include "../../../Common/ComTry.h"
#include "../../../Common/IntToString.h"
#include "../../../Common/MyBuffer2.h"
#include "../../../Common/MyLinux.h"
#include "../../../Common/UTFConvert.h"
#include "../../../Windows/PropVariantUtils.h"
@ -70,8 +71,14 @@ bool CItem::IsDir() const
case NHeader::NFile::kHostMSDOS:
case NHeader::NFile::kHostOS2:
case NHeader::NFile::kHostWin32:
if ((Attrib & FILE_ATTRIBUTE_DIRECTORY) != 0)
if (Attrib & FILE_ATTRIBUTE_DIRECTORY)
return true;
break;
case NHeader::NFile::kHostUnix:
case NHeader::NFile::kHostBeOS:
if (MY_LIN_S_ISDIR(Attrib))
return true;
break;
}
return false;
}
@ -86,11 +93,20 @@ UInt32 CItem::GetWinAttrib() const
case NHeader::NFile::kHostWin32:
a = Attrib;
break;
case NHeader::NFile::kHostUnix:
case NHeader::NFile::kHostBeOS:
a = Attrib << 16;
a |= 0x8000; // add posix mode marker
break;
// case NHeader::NFile::kHostMacOS:
// kHostMacOS was used only by some very old rare case rar.
// New rar4-rar7 for macos probably uses kHostUnix.
// So we process kHostMacOS without attribute parsing:
default:
a = 0; // must be converted from unix value;
a = 0;
}
if (IsDir())
a |= NHeader::NFile::kWinFileDirectoryAttributeMask;
a |= FILE_ATTRIBUTE_DIRECTORY;
return a;
}

View file

@ -65,7 +65,7 @@ static const Byte kArcProps[] =
kpidComment
};
static const char *k_Characts_Prefix = "PREFIX";
static const char * const k_Characts_Prefix = "PREFIX";
IMP_IInArchive_Props
IMP_IInArchive_ArcProps
@ -684,10 +684,14 @@ Z7_COM7F_IMF(CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *val
s.Add_OptSpaced("SCHILY.fflags=");
s += item->SCHILY_fflags;
}
if (item->Is_Sparse())
s.Add_OptSpaced("SPARSE");
if (item->IsThereWarning())
s.Add_OptSpaced("WARNING");
if (item->HeaderError)
s.Add_OptSpaced("ERROR");
if (item->Method_Error)
s.Add_OptSpaced("METHOD_ERROR");
if (item->Pax_Error)
s.Add_OptSpaced("PAX_error");
if (!item->PaxExtra.RawLines.IsEmpty())
@ -812,11 +816,16 @@ Z7_COM7F_IMF(CHandler::Extract(const UInt32 *indices, UInt32 numItems,
inStream2 = inStream;
else
{
GetStream(index, &inStream2);
if (!inStream2)
return E_FAIL;
const HRESULT hres = GetStream(index, &inStream2);
if (hres == E_NOTIMPL)
opRes = NExtract::NOperationResult::kHeadersError; // kUnsupportedMethod
else if (!inStream2)
{
opRes = NExtract::NOperationResult::kDataError;
// return E_FAIL;
}
}
if (opRes == NExtract::NOperationResult::kOK)
{
if (item->Is_SymLink())
{
@ -855,9 +864,9 @@ Z7_CLASS_IMP_IInStream(
bool _needStartSeek;
public:
unsigned ItemIndex;
CHandler *Handler;
CMyComPtr<IUnknown> HandlerRef;
unsigned ItemIndex;
CRecordVector<UInt64> PhyOffsets;
void Init()
@ -879,7 +888,7 @@ Z7_COM7F_IMF(CSparseStream::Read(void *data, UInt32 size, UInt32 *processedSize)
if (_virtPos >= item.Size)
return S_OK;
{
UInt64 rem = item.Size - _virtPos;
const UInt64 rem = item.Size - _virtPos;
if (size > rem)
size = (UInt32)rem;
}
@ -903,17 +912,17 @@ Z7_COM7F_IMF(CSparseStream::Read(void *data, UInt32 size, UInt32 *processedSize)
}
const CSparseBlock &sb = item.SparseBlocks[left];
UInt64 relat = _virtPos - sb.Offset;
const UInt64 relat = _virtPos - sb.Offset;
if (_virtPos >= sb.Offset && relat < sb.Size)
{
UInt64 rem = sb.Size - relat;
const UInt64 rem = sb.Size - relat;
if (size > rem)
size = (UInt32)rem;
UInt64 phyPos = PhyOffsets[left] + relat;
const UInt64 phyPos = PhyOffsets[left] + relat;
if (_needStartSeek || _phyPos != phyPos)
{
RINOK(InStream_SeekSet(Handler->_stream, (item.Get_DataPos() + phyPos)))
RINOK(InStream_SeekSet(Handler->_stream, item.Get_DataPos() + phyPos))
_needStartSeek = false;
_phyPos = phyPos;
}
@ -927,7 +936,7 @@ Z7_COM7F_IMF(CSparseStream::Read(void *data, UInt32 size, UInt32 *processedSize)
next = sb.Offset;
else if (left + 1 < item.SparseBlocks.Size())
next = item.SparseBlocks[left + 1].Offset;
UInt64 rem = next - _virtPos;
const UInt64 rem = next - _virtPos;
if (size > rem)
size = (UInt32)rem;
memset(data, 0, size);
@ -965,6 +974,8 @@ Z7_COM7F_IMF(CHandler::GetStream(UInt32 index, ISequentialInStream **stream))
if (item.Is_Sparse())
{
if (item.Method_Error)
return E_NOTIMPL; // S_FALSE
CSparseStream *streamSpec = new CSparseStream;
CMyComPtr<IInStream> streamTemp = streamSpec;
streamSpec->Init();

View file

@ -181,6 +181,7 @@ HRESULT CArchive::GetNextItemReal(CItemEx &item)
{
char buf[NFileHeader::kRecordSize];
item.Method_Error = false;
error = k_ErrorType_OK;
filled = false;
@ -218,10 +219,7 @@ HRESULT CArchive::GetNextItemReal(CItemEx &item)
break;
item.HeaderSize += NFileHeader::kRecordSize;
thereAreEmptyRecords = true;
if (OpenCallback)
{
RINOK(Progress(item, 0))
}
RINOK(Progress(item, 0))
}
if (thereAreEmptyRecords)
{
@ -335,37 +333,60 @@ HRESULT CArchive::GetNextItemReal(CItemEx &item)
if (item.LinkFlag == NFileHeader::NLinkFlag::kSparse)
{
Byte isExtended = (Byte)buf[482];
if (isExtended != 0 && isExtended != 1)
return S_OK;
// OLD GNU format: parse sparse file information:
// PackSize = cumulative size of all non-empty blocks of the file.
// We read actual file size from 'realsize' member of oldgnu_header:
RIF(ParseSize(buf + 483, item.Size, item.Size_IsBin))
UInt64 min = 0;
for (unsigned i = 0; i < 4; i++)
{
p = buf + 386 + 24 * i;
if (GetBe32(p) == 0)
{
if (isExtended != 0)
return S_OK;
break;
}
CSparseBlock sb;
RIF(ParseSize(p, sb.Offset))
RIF(ParseSize(p + 12, sb.Size))
item.SparseBlocks.Add(sb);
if (sb.Offset < min || sb.Offset > item.Size)
return S_OK;
if ((sb.Offset & 0x1FF) != 0 || (sb.Size & 0x1FF) != 0)
return S_OK;
min = sb.Offset + sb.Size;
if (min < sb.Offset)
return S_OK;
}
if (min > item.Size)
if (item.Size < item.PackSize) // additional check
return S_OK;
while (isExtended != 0)
p = buf + 386;
UInt64 end = 0, packSum = 0;
unsigned numRecords = 4;
unsigned isExtended = (Byte)p[4 * 24]; // (Byte)p[numRecords * 24];
// the list of blocks contains non-empty blocks. All another data is empty.
for (;;)
{
// const unsigned isExtended = (Byte)p[numRecords * 24];
if (isExtended > 1)
return S_OK;
do
{
if (GetBe32(p) == 0)
{
if (isExtended)
return S_OK;
break;
}
CSparseBlock sb;
RIF(ParseSize(p, sb.Offset))
RIF(ParseSize(p + 12, sb.Size))
p += 24;
/* for all non-last blocks we expect :
((sb.Size & 0x1ff) == 0) && ((sb.Offset & 0x1ff) == 0)
for last block : (sb.Size == 0) is possible.
*/
if (sb.Offset < end
|| item.Size < sb.Offset
|| item.Size - sb.Offset < sb.Size)
return S_OK;
// optional check:
if (sb.Size && ((end & 0x1ff) || (sb.Offset & 0x1ff)))
{
item.Method_Error = true; // relaxed check
// return S_OK;
}
end = sb.Offset + sb.Size;
packSum += sb.Size;
item.SparseBlocks.Add(sb);
}
while (--numRecords);
if (!isExtended)
break;
size_t processedSize = NFileHeader::kRecordSize;
RINOK(ReadStream(SeqStream, buf, &processedSize))
if (processedSize != NFileHeader::kRecordSize)
@ -373,46 +394,22 @@ HRESULT CArchive::GetNextItemReal(CItemEx &item)
error = k_ErrorType_UnexpectedEnd;
return S_OK;
}
item.HeaderSize += NFileHeader::kRecordSize;
if (OpenCallback)
{
RINOK(Progress(item, 0))
}
isExtended = (Byte)buf[21 * 24];
if (isExtended != 0 && isExtended != 1)
return S_OK;
for (unsigned i = 0; i < 21; i++)
{
p = buf + 24 * i;
if (GetBe32(p) == 0)
{
if (isExtended != 0)
return S_OK;
break;
}
CSparseBlock sb;
RIF(ParseSize(p, sb.Offset))
RIF(ParseSize(p + 12, sb.Size))
item.SparseBlocks.Add(sb);
if (sb.Offset < min || sb.Offset > item.Size)
return S_OK;
if ((sb.Offset & 0x1FF) != 0 || (sb.Size & 0x1FF) != 0)
return S_OK;
min = sb.Offset + sb.Size;
if (min < sb.Offset)
return S_OK;
}
RINOK(Progress(item, 0))
p = buf;
numRecords = 21;
isExtended = (Byte)p[21 * 24]; // (Byte)p[numRecords * 24];
}
// optional checks for strict size consistency:
if (end != item.Size || packSum != item.PackSize)
{
item.Method_Error = true; // relaxed check
// return S_OK;
}
if (min > item.Size)
return S_OK;
}
if (item.PackSize >= (UInt64)1 << 63)
if (item.PackSize >= (UInt64)1 << 63) // optional check. It was checked in ParseSize() already
return S_OK;
filled = true;
error = k_ErrorType_OK;
return S_OK;
@ -421,6 +418,8 @@ HRESULT CArchive::GetNextItemReal(CItemEx &item)
HRESULT CArchive::Progress(const CItemEx &item, UInt64 posOffset)
{
if (!OpenCallback)
return S_OK;
const UInt64 pos = item.Get_DataPos() + posOffset;
if (NumFiles - NumFiles_Prev < (1 << 16)
// && NumRecords - NumRecords_Prev < (1 << 16)
@ -500,10 +499,7 @@ HRESULT CArchive::ReadDataToBuffer(const CItemEx &item,
do
{
if (OpenCallback)
{
RINOK(Progress(item, pos))
}
RINOK(Progress(item, pos))
unsigned size = kBufSize;
if (size > packSize)
@ -813,6 +809,7 @@ HRESULT CArchive::ReadItem2(CItemEx &item)
item.LongLink_WasUsed_2 = false;
item.HeaderError = false;
item.Method_Error = false;
item.IsSignedChecksum = false;
item.Prefix_WasUsed = false;
@ -838,13 +835,8 @@ HRESULT CArchive::ReadItem2(CItemEx &item)
for (;;)
{
if (OpenCallback)
{
RINOK(Progress(item, 0))
}
RINOK(Progress(item, 0))
RINOK(GetNextItemReal(item))
// NumRecords++;
if (!filled)
@ -1064,9 +1056,14 @@ HRESULT CArchive::ReadItem2(CItemEx &item)
// GNU TAR ignores (item.Size) in that case
if (item.Size != 0 && item.Size != piSize)
item.Pax_Error = true;
item.Size = piSize;
item.PackSize = piSize;
item.pax_size_WasUsed = true;
if (piSize >= ((UInt64)1 << 63))
item.Pax_Error = true;
else
{
item.Size = piSize;
item.PackSize = piSize;
item.pax_size_WasUsed = true;
}
}
item.PaxTimes = paxInfo;

View file

@ -322,6 +322,7 @@ struct CPaxExtra
struct CItemEx: public CItem
{
bool HeaderError;
bool Method_Error;
bool IsSignedChecksum;
bool Prefix_WasUsed;

View file

@ -500,10 +500,15 @@ size_t CFileId::Parse(const Byte *p, size_t size)
processed += impLen;
Id.Parse(p + processed, idLen);
processed += idLen;
// const size_t processed2 = processed;
for (;(processed & 3) != 0; processed++)
if (p[processed] != 0)
return 0;
if ((size_t)tag.CrcLen + 16 != processed) return 0;
// some program can create non-standard UDF file where CrcLen doesn't include Padding data
if ((size_t)tag.CrcLen + 16 != processed
// && (size_t)tag.CrcLen + 16 != processed2 // we can enable this check to support non-standard UDF
)
return 0;
return (processed <= size) ? processed : 0;
}
@ -577,15 +582,20 @@ HRESULT CInArchive::ReadItem(unsigned volIndex, int fsIndex, const CLongAllocDes
item.IcbTag.Parse(p + 16);
// maybe another FileType values are possible in rare cases.
// Shoud we ignore FileType here?
if (fsIndex < 0)
{
// if (item.IcbTag.FileType == ICB_FILE_TYPE_DIR) return S_FALSE;
if (item.IcbTag.FileType != ICB_FILE_TYPE_METADATA &&
item.IcbTag.FileType != ICB_FILE_TYPE_METADATA_MIRROR)
item.IcbTag.FileType != ICB_FILE_TYPE_METADATA_MIRROR &&
item.IcbTag.FileType != ICB_FILE_TYPE_METADATA_BITMAP)
return S_FALSE;
}
else if (
item.IcbTag.FileType != ICB_FILE_TYPE_DIR &&
item.IcbTag.FileType != ICB_FILE_TYPE_FILE)
item.IcbTag.FileType != ICB_FILE_TYPE_FILE &&
item.IcbTag.FileType != ICB_FILE_TYPE_REAL_TIME_FILE) // M2TS files in /BDMV/STREAM/ in Blu-ray movie
return S_FALSE;
item.Parse(p);
@ -1210,7 +1220,7 @@ HRESULT CInArchive::Open2()
if (tag.Id != DESC_TYPE_FileSet)
return S_FALSE;
PRF(printf("\n FileSet", volIndex));
PRF(printf("\n FileSet"));
CFileSet fs;
fs.RecordingTime.Parse(p + 16);
// fs.InterchangeLevel = Get16(p + 18);

View file

@ -250,9 +250,10 @@ enum EIcbFileType
{
ICB_FILE_TYPE_DIR = 4,
ICB_FILE_TYPE_FILE = 5,
ICB_FILE_TYPE_METADATA = 250, // 2.2.13.1 Metadata File
ICB_FILE_TYPE_METADATA_MIRROR = 251
ICB_FILE_TYPE_REAL_TIME_FILE = 249, // 2.3.5.2.1
ICB_FILE_TYPE_METADATA = 250, // 2.2.13.1
ICB_FILE_TYPE_METADATA_MIRROR = 251, // 2.2.13.1
ICB_FILE_TYPE_METADATA_BITMAP = 252 // 2.2.13.2
};
enum EIcbDescriptorType

View file

@ -1718,61 +1718,49 @@ HRESULT CInArchive::TryEcd64(UInt64 offset, CCdInfo &cdInfo)
HRESULT CInArchive::FindCd(bool checkOffsetMode)
{
CCdInfo &cdInfo = Vols.ecd;
UInt64 endPos;
// There are no useful data in cache in most cases here.
// So here we don't use cache data from previous operations .
// So here we don't use cache data from previous operations.
InitBuf();
UInt64 endPos;
RINOK(InStream_GetSize_SeekToEnd(Stream, endPos))
_streamPos = endPos;
// const UInt32 kBufSizeMax2 = ((UInt32)1 << 16) + kEcdSize + kEcd64Locator_Size + kEcd64_FullSize;
const size_t kBufSizeMax = ((size_t)1 << 17); // must be larger than kBufSizeMax2
const size_t kBufSizeMax = (size_t)1 << 17; // must be larger than
// (1 << 16) + kEcdSize + kEcd64Locator_Size + kEcd64_FullSize
const size_t bufSize = (endPos < kBufSizeMax) ? (size_t)endPos : kBufSizeMax;
if (bufSize < kEcdSize)
return S_FALSE;
// CByteArr byteBuffer(bufSize);
RINOK(AllocateBuffer(kBufSizeMax))
{
RINOK(Seek_SavePos(endPos - bufSize))
size_t processed = bufSize;
const HRESULT res = ReadStream(Stream, Buffer, &processed);
_streamPos += processed;
_bufCached = processed;
_bufPos = 0;
_cnt += processed;
if (res != S_OK)
return res;
if (processed != bufSize)
return S_FALSE;
}
RINOK(Seek_SavePos(endPos - bufSize))
size_t processed = bufSize;
HRESULT res = ReadStream(Stream, Buffer, &processed);
_streamPos += processed;
_bufCached = processed;
_bufPos = 0;
_cnt += processed;
if (res != S_OK)
return res;
if (processed != bufSize)
return S_FALSE;
CCdInfo &cdInfo = Vols.ecd;
for (size_t i = bufSize - kEcdSize + 1;;)
{
if (i == 0)
return S_FALSE;
const Byte *buf = Buffer;
for (;;)
{
i--;
if (buf[i] == 0x50)
break;
if (i == 0)
return S_FALSE;
}
if (Get32(buf + i) != NSignature::kEcd)
continue;
const Byte *p = buf + i;
do
if (p == buf)
return S_FALSE;
while (*(--p) != 0x50);
cdInfo.ParseEcd32(buf + i);
i = (size_t)(p - buf);
if (Get32(p) != NSignature::kEcd)
continue;
cdInfo.ParseEcd32(p);
}
if (i >= kEcd64Locator_Size)
{
@ -1793,29 +1781,24 @@ HRESULT CInArchive::FindCd(bool checkOffsetMode)
// Most of the zip64 use fixed size Zip64 ECD
// we try relative backward reading.
UInt64 absEcd64 = endPos - bufSize + i - (kEcd64Locator_Size + kEcd64_FullSize);
const UInt64 absEcd64 = endPos - bufSize + i - (kEcd64Locator_Size + kEcd64_FullSize);
if (locatorIndex >= kEcd64_FullSize)
if (checkOffsetMode || absEcd64 == locator.Ecd64Offset)
{
const Byte *ecd64 = buf + locatorIndex - kEcd64_FullSize;
if (Get32(ecd64) == NSignature::kEcd64)
if (Get32(ecd64) == NSignature::kEcd64 &&
Get64(ecd64 + 4) == kEcd64_MainSize)
{
UInt64 mainEcd64Size = Get64(ecd64 + 4);
if (mainEcd64Size == kEcd64_MainSize)
{
cdInfo.ParseEcd64e(ecd64 + 12);
ArcInfo.Base = (Int64)(absEcd64 - locator.Ecd64Offset);
// ArcInfo.BaseVolIndex = cdInfo.ThisDisk;
return S_OK;
}
cdInfo.ParseEcd64e(ecd64 + 12);
ArcInfo.Base = (Int64)(absEcd64 - locator.Ecd64Offset);
// ArcInfo.BaseVolIndex = cdInfo.ThisDisk;
return S_OK;
}
}
// some zip64 use variable size Zip64 ECD.
// we try to use absolute offset from locator.
if (absEcd64 != locator.Ecd64Offset)
{
if (TryEcd64(locator.Ecd64Offset, cdInfo) == S_OK)
@ -1881,6 +1864,9 @@ HRESULT CInArchive::TryReadCd(CObjectVector<CItemEx> &items, const CCdInfo &cdIn
items.Clear();
IsCdUnsorted = false;
if ((Int64)cdOffset < 0)
return S_FALSE;
// _startLocalFromCd_Disk = (UInt32)(Int32)-1;
// _startLocalFromCd_Offset = (UInt64)(Int64)-1;

View file

@ -49,42 +49,54 @@ void COutArchive::SeekToCurPos()
// #define DOES_NEED_ZIP64(v) (v >= 0)
Z7_NO_INLINE
void COutArchive::WriteBytes(const void *data, size_t size)
{
m_OutBuffer.WriteBytes(data, size);
m_CurPos += size;
}
Z7_NO_INLINE
void COutArchive::Write8(Byte b)
{
m_OutBuffer.WriteByte(b);
m_CurPos++;
}
Z7_NO_INLINE
void COutArchive::Write16(UInt16 val)
{
Write8((Byte)val);
Write8((Byte)(val >> 8));
}
Z7_NO_INLINE
void COutArchive::Write32(UInt32 val)
{
for (int i = 0; i < 4; i++)
{
Write8((Byte)val);
// Write8((Byte)val);
m_OutBuffer.WriteByte((Byte)val);
val >>= 8;
}
m_CurPos += 4;
}
#define WRITE_CONST_PAIR_16_16(a, b) { Write32((a) | ((UInt32)(b) << 16)); }
Z7_NO_INLINE
void COutArchive::Write64(UInt64 val)
{
for (int i = 0; i < 8; i++)
{
Write8((Byte)val);
// Write8((Byte)val);
m_OutBuffer.WriteByte((Byte)val);
val >>= 8;
}
m_CurPos += 8;
}
Z7_NO_INLINE
void COutArchive::WriteExtra(const CExtraBlock &extra)
{
FOR_VECTOR (i, extra.SubBlocks)
@ -134,11 +146,9 @@ void COutArchive::WriteTimeExtra(const CItemOut &item, bool writeNtfs)
if (writeNtfs)
{
// windows explorer ignores that extra
Write16(NFileHeader::NExtraID::kNTFS);
Write16(k_Ntfs_ExtraSize);
WRITE_CONST_PAIR_16_16(NFileHeader::NExtraID::kNTFS, k_Ntfs_ExtraSize)
Write32(0); // reserved
Write16(NFileHeader::NNtfsExtra::kTagTime);
Write16(8 * 3);
WRITE_CONST_PAIR_16_16(NFileHeader::NNtfsExtra::kTagTime, 8 * 3)
WriteNtfsTime(item.Ntfs_MTime);
WriteNtfsTime(item.Ntfs_ATime);
WriteNtfsTime(item.Ntfs_CTime);
@ -148,8 +158,7 @@ void COutArchive::WriteTimeExtra(const CItemOut &item, bool writeNtfs)
{
// windows explorer ignores that extra
// by specification : should we write to local header also?
Write16(NFileHeader::NExtraID::kUnixTime);
Write16(k_UnixTime_ExtraSize);
WRITE_CONST_PAIR_16_16(NFileHeader::NExtraID::kUnixTime, k_UnixTime_ExtraSize)
const Byte flags = (Byte)((unsigned)1 << NFileHeader::NUnixTime::kMTime);
Write8(flags);
UInt32 unixTime;
@ -217,8 +226,7 @@ void COutArchive::WriteLocalHeader(CItemOut &item, bool needCheck)
if (isZip64)
{
Write16(NFileHeader::NExtraID::kZip64);
Write16(8 + 8);
WRITE_CONST_PAIR_16_16(NFileHeader::NExtraID::kZip64, 8 + 8)
Write64(size);
Write64(packSize);
}
@ -357,8 +365,9 @@ HRESULT COutArchive::WriteCentralDir(const CObjectVector<CItemOut> &items, const
const UInt64 cdSize = cd64EndOffset - cdOffset;
const bool cdOffset64 = DOES_NEED_ZIP64(cdOffset);
const bool cdSize64 = DOES_NEED_ZIP64(cdSize);
const bool items64 = items.Size() >= 0xFFFF;
const bool isZip64 = (cdOffset64 || cdSize64 || items64);
const bool need_Items_64 = items.Size() >= 0xFFFF;
const unsigned items16 = (UInt16)(need_Items_64 ? 0xFFFF: items.Size());
const bool isZip64 = (cdOffset64 || cdSize64 || need_Items_64);
// isZip64 = true; // to test Zip64
@ -371,8 +380,8 @@ HRESULT COutArchive::WriteCentralDir(const CObjectVector<CItemOut> &items, const
// const UInt32 extraSize = 1 << 26;
// Write64(kEcd64_MainSize + extraSize);
Write16(45); // made by version
Write16(45); // extract version
WRITE_CONST_PAIR_16_16(45, // made by version
45) // extract version
Write32(0); // ThisDiskNumber
Write32(0); // StartCentralDirectoryDiskNumber
Write64((UInt64)items.Size());
@ -389,10 +398,9 @@ HRESULT COutArchive::WriteCentralDir(const CObjectVector<CItemOut> &items, const
}
Write32(NSignature::kEcd);
Write16(0); // ThisDiskNumber
Write16(0); // StartCentralDirectoryDiskNumber
Write16((UInt16)(items64 ? 0xFFFF: items.Size()));
Write16((UInt16)(items64 ? 0xFFFF: items.Size()));
WRITE_CONST_PAIR_16_16(0, 0) // ThisDiskNumber, StartCentralDirectoryDiskNumber
Write16((UInt16)items16);
Write16((UInt16)items16);
WRITE_32_VAL_SPEC(cdSize, cdSize64)
WRITE_32_VAL_SPEC(cdOffset, cdOffset64)

View file

@ -153,7 +153,7 @@ namespace NCommandType
};
}
static const char *g_Commands = "txl";
static const char * const g_Commands = "txl";
struct CArchiveCommand
{

View file

@ -48,72 +48,60 @@ static bool ReadDataString(CFSTR fileName, LPCSTR startID,
NIO::CInFile inFile;
if (!inFile.Open(fileName))
return false;
const size_t kBufferSize = (1 << 12);
const size_t kBufferSize = 1 << 12;
Byte buffer[kBufferSize];
const unsigned signatureStartSize = MyStringLen(startID);
const unsigned signatureEndSize = MyStringLen(endID);
const size_t signatureStartSize = MyStringLen(startID + 1);
const size_t signatureEndSize = MyStringLen(endID + 1);
size_t numBytesPrev = 0;
bool writeMode = false;
UInt64 posTotal = 0;
UInt32 posTotal = 0;
for (;;)
{
if (posTotal > (1 << 20))
return (stringResult.IsEmpty());
const size_t numReadBytes = kBufferSize - numBytesPrev;
size_t processedSize;
if (!inFile.ReadFull(buffer + numBytesPrev, numReadBytes, processedSize))
return false;
if (processedSize == 0)
return true;
const size_t numBytesInBuffer = numBytesPrev + processedSize;
UInt32 pos = 0;
numBytesPrev += processedSize;
size_t pos = 0;
for (;;)
{
if (writeMode)
{
if (pos + signatureEndSize > numBytesInBuffer)
if (pos + signatureEndSize > numBytesPrev)
break;
if (memcmp(buffer + pos, endID, signatureEndSize) == 0)
return true;
const Byte b = buffer[pos];
const Byte b = buffer[pos++];
if (b == 0)
return false;
if (b == ';' && memcmp(buffer + pos, endID + 1, signatureEndSize) == 0)
return true;
stringResult += (char)b;
pos++;
}
else
{
if (pos + signatureStartSize > numBytesInBuffer)
if (pos + signatureStartSize > numBytesPrev)
break;
if (memcmp(buffer + pos, startID, signatureStartSize) == 0)
const Byte b = buffer[pos++];
if (b == ';' && memcmp(buffer + pos, startID + 1, signatureStartSize) == 0)
{
writeMode = true;
pos += signatureStartSize;
}
else
pos++;
}
}
numBytesPrev = numBytesInBuffer - pos;
posTotal += pos;
posTotal += (UInt32)pos;
if (posTotal > (1 << 21))
return stringResult.IsEmpty();
numBytesPrev -= pos;
memmove(buffer, buffer + pos, numBytesPrev);
}
}
static char kStartID[] = { ',','!','@','I','n','s','t','a','l','l','@','!','U','T','F','-','8','!', 0 };
static char kEndID[] = { ',','!','@','I','n','s','t','a','l','l','E','n','d','@','!', 0 };
static struct CInstallIDInit
{
CInstallIDInit()
{
kStartID[0] = ';';
kEndID[0] = ';';
}
} g_CInstallIDInit;
static const char * const kStartID = ",!@Install@!UTF-8!";
static const char * const kEndID = ",!@InstallEnd@!";
#if defined(_WIN32) && defined(_UNICODE) && !defined(_WIN64) && !defined(UNDER_CE)
#define NT_CHECK_FAIL_ACTION ShowErrorMessage(L"Unsupported Windows version"); return 1;

View file

@ -753,7 +753,7 @@ Z7_COM7F_IMF(CInFileStream::GetProperty(PROPID propID, PROPVARIANT *value))
{
if (StoreOwnerName)
{
const uid_t gid = st.st_gid;
const gid_t gid = st.st_gid;
{
if (!OwnerGroup.IsEmpty() && _gid == gid)
prop = OwnerGroup;

View file

@ -84,8 +84,8 @@ public:
BY_HANDLE_FILE_INFORMATION _info;
#else
struct stat _info;
UInt32 _uid;
UInt32 _gid;
uid_t _uid; // uid_t can be unsigned or signed int
gid_t _gid;
UString OwnerName;
UString OwnerGroup;
bool StoreOwnerId;

View file

@ -426,7 +426,7 @@ static NRecursedType::EEnum GetRecursedTypeFromIndex(int index)
}
}
static const char *g_Commands = "audtexlbih";
static const char * const g_Commands = "audtexlbih";
static bool ParseArchiveCommand(const UString &commandString, CArcCommand &command)
{

View file

@ -17,14 +17,14 @@ using namespace NWindows;
using namespace NFile;
static const char *g_ArcExts =
static const char * const g_ArcExts =
"7z"
"\0" "zip"
"\0" "tar"
"\0" "wim"
"\0";
static const char *g_HashExts =
static const char * const g_HashExts =
"sha256"
"\0";

View file

@ -3038,7 +3038,7 @@ AString GetProcessThreadsInfo(const NSystem::CProcessAffinity &ti)
FOR_VECTOR (i, ti.Groups.GroupSizes)
{
if (i != 0)
s.Add_Char(' ');
s.Add_Space();
s.Add_UInt32(ti.Groups.GroupSizes[i]);
}
}
@ -3773,10 +3773,11 @@ HRESULT Bench(
#ifndef Z7_ST
if (threadsInfo.Get() && threadsInfo.GetNumProcessThreads() != 0)
numCPUs = threadsInfo.GetNumProcessThreads();
else
if (!threadsInfo.Get()
|| (numCPUs = threadsInfo.GetNumProcessThreads()) == 0)
numCPUs = NSystem::GetNumberOfProcessors();
// numCPUs : is number of threads assigned to process with affinity,
// or it's total number of threads in all groups, if IsGroupMode == true, and there is default affinity.
#endif

View file

@ -201,8 +201,8 @@ static const CFieldInfoInit kStandardFieldTable[] =
{ kpidPath, "Name", kLeft, kLeft, 2, 24 }
};
const unsigned kNumSpacesMax = 32; // it must be larger than max CFieldInfoInit.Width
static const char *g_Spaces =
static const unsigned kNumSpacesMax = 32; // it must be larger than max CFieldInfoInit.Width
static const char * const g_Spaces =
" " ;
static void PrintSpaces(unsigned numSpaces)

View file

@ -9,6 +9,7 @@
#include <windowsx.h>
#include "../../../Common/IntToString.h"
#include "../../../Common/MyCom.h"
#include "../../../Common/StringConvert.h"
#include "../../../Common/Wildcard.h"
@ -19,6 +20,7 @@
#include "../../../Windows/Menu.h"
#include "../../../Windows/ProcessUtils.h"
#include "../../../Windows/PropVariantConv.h"
#include "../../../Windows/Shell.h"
#include "../../../Windows/Control/ComboBox.h"
#include "../../../Windows/Control/Dialog.h"
#include "../../../Windows/Control/Edit.h"
@ -57,7 +59,7 @@ static const int kParentIndex = -1;
// static const UINT k_Message_RefreshPathEdit = WM_APP + 1;
static const wchar_t *k_Message_Link_operation_was_Blocked =
static const wchar_t * const k_Message_Link_operation_was_Blocked =
L"link openning was blocked by 7-Zip";
extern UString HResultToMessage(HRESULT errorCode);
@ -978,35 +980,61 @@ void CBrowseDialog2::OnHelp()
#endif
HRESULT ShellFolder_ParseDisplayName(IShellFolder *shellFolder,
HWND hwnd, const UString &path, LPITEMIDLIST *ppidl);
HRESULT StartApplication(const UString &dir, const UString &path, HWND window, CProcess &process);
HRESULT StartApplication(const UString &dir, const UString &path, HWND window, CProcess &process)
{
UString path2 = path;
#ifdef _WIN32
UINT32 result;
{
#ifdef _WIN32
NShell::CItemIDList pidl;
// SHELLEXECUTEINFO::pidl is more accurate way than SHELLEXECUTEINFO::lpFile
{
CMyComPtr<IShellFolder> desktop;
if (SHGetDesktopFolder(&desktop) == S_OK && desktop)
if (ShellFolder_ParseDisplayName(desktop,
NULL, // HWND : do we need (window) or NULL here?
path,
&pidl) != S_OK)
pidl.Detach();
}
{
const int dot = path2.ReverseFind_Dot();
const int separ = path2.ReverseFind_PathSepar();
if (dot < 0 || dot < separ)
path2.Add_Dot();
if (separ != (int)path2.Len() - 1)
if (dot < 0 || dot < separ)
path2.Add_Dot();
}
#endif
#endif // _WIN32
UINT32 result;
#ifndef _UNICODE
if (g_IsNT)
{
SHELLEXECUTEINFOW execInfo;
memset(&execInfo, 0, sizeof(execInfo));
// execInfo.hwnd = NULL;
// execInfo.lpVerb = NULL;
// execInfo.lpFile = NULL;
// execInfo.lpDirectory = NULL;
// execInfo.lpParameters = NULL;
// execInfo.hProcess = NULL;
execInfo.cbSize = sizeof(execInfo);
execInfo.fMask = SEE_MASK_NOCLOSEPROCESS | SEE_MASK_FLAG_DDEWAIT;
execInfo.hwnd = NULL;
execInfo.lpVerb = NULL;
execInfo.lpFile = path2;
execInfo.lpParameters = NULL;
execInfo.lpDirectory = dir.IsEmpty() ? NULL : (LPCWSTR)dir;
if (!dir.IsEmpty())
execInfo.lpDirectory = dir;
execInfo.nShow = SW_SHOWNORMAL;
execInfo.hProcess = NULL;
if ((LPCITEMIDLIST)pidl)
{
execInfo.lpIDList = pidl;
execInfo.fMask |= SEE_MASK_IDLIST;
}
else
execInfo.lpFile = path2;
typedef BOOL (WINAPI * Func_ShellExecuteExW)(LPSHELLEXECUTEINFOW lpExecInfo);
Z7_DIAGNOSTIC_IGNORE_CAST_FUNCTION
const
@ -1024,34 +1052,40 @@ Z7_DIAGNOSTIC_IGNORE_CAST_FUNCTION
#endif
{
SHELLEXECUTEINFO execInfo;
memset(&execInfo, 0, sizeof(execInfo));
// execInfo.hwnd = NULL;
// execInfo.lpVerb = NULL;
// execInfo.lpFile = NULL;
// execInfo.lpDirectory = NULL;
// execInfo.lpParameters = NULL;
// execInfo.hProcess = NULL;
execInfo.cbSize = sizeof(execInfo);
execInfo.fMask = SEE_MASK_NOCLOSEPROCESS
#ifndef UNDER_CE
| SEE_MASK_FLAG_DDEWAIT
#endif
;
execInfo.hwnd = NULL;
execInfo.lpVerb = NULL;
execInfo.nShow = SW_SHOWNORMAL;
const CSysString sysPath (GetSystemString(path2));
const CSysString sysDir (GetSystemString(dir));
execInfo.lpFile = sysPath;
execInfo.lpParameters = NULL;
execInfo.lpDirectory =
#ifdef UNDER_CE
NULL
#else
sysDir.IsEmpty() ? NULL : (LPCTSTR)sysDir
#endif
;
execInfo.nShow = SW_SHOWNORMAL;
execInfo.hProcess = NULL;
#ifndef UNDER_CE
if (!sysDir.IsEmpty())
execInfo.lpDirectory = sysDir;
#endif
if ((LPCITEMIDLIST)pidl)
{
execInfo.lpIDList = pidl;
execInfo.fMask |= SEE_MASK_IDLIST;
}
else
execInfo.lpFile = sysPath;
::ShellExecuteEx(&execInfo);
result = (UINT32)(UINT_PTR)execInfo.hInstApp;
process.Attach(execInfo.hProcess);
}
// DEBUG_PRINT_NUM("-- ShellExecuteEx -- execInfo.hInstApp = ", result)
}
if (result <= 32)
{
switch (result)
@ -1063,10 +1097,8 @@ Z7_DIAGNOSTIC_IGNORE_CAST_FUNCTION
// L"There is no application associated with the given file name extension",
);
}
return E_FAIL; // fixed in 15.13. Can we use it for any Windows version?
}
return S_OK;
}

View file

@ -748,8 +748,8 @@ Z7_COM7F_IMF2(Int32, CFSFolder::CompareItems(UInt32 index1, UInt32 index2, PROPI
case kpidMTime: return CompareFileTime(&fi1.MTime, &fi2.MTime);
case kpidIsDir:
{
bool isDir1 = /* ss1 ? false : */ fi1.IsDir();
bool isDir2 = /* ss2 ? false : */ fi2.IsDir();
const bool isDir1 = /* ss1 ? false : */ fi1.IsDir();
const bool isDir2 = /* ss2 ? false : */ fi2.IsDir();
if (isDir1 == isDir2)
return 0;
return isDir1 ? -1 : 1;
@ -798,7 +798,9 @@ Z7_COM7F_IMF2(Int32, CFSFolder::CompareItems(UInt32 index1, UInt32 index2, PROPI
return MyStringCompareNoCase(comment1, comment2);
}
case kpidPrefix:
if (fi1.Parent < 0) return (fi2.Parent < 0) ? 0 : -1;
if (fi1.Parent == fi2.Parent)
return 0;
if (fi1.Parent < 0) return -1;
if (fi2.Parent < 0) return 1;
return CompareFileNames_ForFolderList(
Folders[fi1.Parent],

View file

@ -253,8 +253,7 @@ bool CLangPage::OnInit()
temp += " ";
temp += rec.Mark;
}
const int index = (int)_langCombo.AddString(temp);
_langCombo.SetItemData(index, (LPARAM)rec.LangInfoIndex);
const int index = (int)_langCombo.AddString_SetItemData(temp, (LPARAM)rec.LangInfoIndex);
if (rec.IsSelected)
_langCombo.SetCurSel(index);
}

View file

@ -222,8 +222,7 @@ bool CMenuPage::OnInit()
s.Add_UInt32(val);
if (i == 0)
s.Insert(0, L"* ");
const int index = (int)_zoneCombo.AddString(s);
_zoneCombo.SetItemData(index, (LPARAM)val);
const int index = (int)_zoneCombo.AddString_SetItemData(s, (LPARAM)val);
if (val == wz)
_zoneCombo.SetCurSel(index);
}

View file

@ -825,7 +825,10 @@ void CPanel::EditItem(unsigned index, bool useEditor)
return;
}
CProcess process;
StartEditApplication(GetItemFullPath(index), useEditor, (HWND)*this, process);
StartEditApplication(GetItemFullPath(index), useEditor,
// (HWND)*this,
GetParent(),
process);
}
@ -854,7 +857,10 @@ void CPanel::OpenFolderExternal(unsigned index)
path.Add_PathSepar();
}
StartApplicationDontWait(prefix, path, (HWND)*this);
StartApplicationDontWait(prefix, path,
// (HWND)*this
GetParent()
);
}
@ -981,7 +987,10 @@ void CPanel::OpenItem(unsigned index, bool tryInternal, bool tryExternal, const
{
// SetCurrentDirectory opens HANDLE to folder!!!
// NDirectory::MySetCurrentDirectory(prefix);
StartApplicationDontWait(prefix, fullPath, (HWND)*this);
StartApplicationDontWait(prefix, fullPath,
// (HWND)*this
GetParent()
);
}
}
@ -1732,9 +1741,15 @@ void CPanel::OpenItemInArchive(unsigned index, bool tryInternal, bool tryExterna
CProcess process;
HRESULT res;
if (editMode)
res = StartEditApplication(fs2us(tempFilePath), useEditor, (HWND)*this, process);
res = StartEditApplication(fs2us(tempFilePath), useEditor,
// (HWND)*this,
GetParent(),
process);
else
res = StartApplication(fs2us(tempDirNorm), fs2us(tempFilePath), (HWND)*this, process);
res = StartApplication(fs2us(tempDirNorm), fs2us(tempFilePath),
// (HWND)*this,
GetParent(),
process);
if ((HANDLE)process == NULL)
{

View file

@ -488,7 +488,9 @@ struct CFolderPidls
};
static HRESULT ShellFolder_ParseDisplayName(IShellFolder *shellFolder,
HRESULT ShellFolder_ParseDisplayName(IShellFolder *shellFolder,
HWND hwnd, const UString &path, LPITEMIDLIST *ppidl);
HRESULT ShellFolder_ParseDisplayName(IShellFolder *shellFolder,
HWND hwnd, const UString &path, LPITEMIDLIST *ppidl)
{
ULONG eaten = 0;

View file

@ -82,7 +82,7 @@ static inline const wchar_t *GetExtensionPtr(const UString &name)
void CPanel::SetSortRawStatus()
{
_isRawSortProp = false;
_isRawSortProp = 0; // false;
FOR_VECTOR (i, _columns)
{
const CPropColumn &prop = _columns[i];
@ -95,21 +95,15 @@ void CPanel::SetSortRawStatus()
}
static int CALLBACK CompareItems2(LPARAM lParam1, LPARAM lParam2, LPARAM lpData)
static int CALLBACK CompareItems2(const LPARAM lParam1, const LPARAM lParam2,
const CPanel * const panel, const PROPID propID, const Int32 isRawProp)
{
if (lpData == 0)
return 0;
CPanel *panel = (CPanel*)lpData;
PROPID propID = panel->_sortID;
if (propID == kpidNoProperty)
return MyCompare(lParam1, lParam2);
if (panel->_isRawSortProp)
if (isRawProp)
{
// Sha1, NtSecurity, NtReparse
// Sha1, Checksum, NtSecurity, NtReparse
const void *data1;
const void *data2;
UInt32 dataSize1;
@ -135,7 +129,7 @@ static int CALLBACK CompareItems2(LPARAM lParam1, LPARAM lParam2, LPARAM lpData)
}
if (panel->_folderCompare)
return panel->_folderCompare->CompareItems((UInt32)lParam1, (UInt32)lParam2, propID, panel->_isRawSortProp);
return panel->_folderCompare->CompareItems((UInt32)lParam1, (UInt32)lParam2, propID, isRawProp);
switch (propID)
{
@ -189,16 +183,41 @@ int CALLBACK CompareItems(LPARAM lParam1, LPARAM lParam2, LPARAM lpData)
if (lParam1 == (int)kParentIndex) return -1;
if (lParam2 == (int)kParentIndex) return 1;
CPanel *panel = (CPanel*)lpData;
const CPanel *panel = (CPanel*)lpData;
const bool isDir1 = panel->IsItem_Folder((unsigned)lParam1);
const bool isDir2 = panel->IsItem_Folder((unsigned)lParam2);
if (isDir1 && !isDir2) return -1;
if (isDir2 && !isDir1) return 1;
if (isDir1 != isDir2)
return isDir1 ? -1 : 1;
const int result = CompareItems2(lParam1, lParam2, lpData);
return panel->_ascending ? result: (-result);
/*
we have up to 3 iterations:
1: prop,
2: kpidName, kpidPrefix
3: prop, kpidName, kpidPrefix
3: kpidPrefix, kpidName, kpidPrefix : is some rare case
*/
PROPID propID = panel->_sortID;
int res = 0;
for (unsigned iter = 0; iter < 3; iter++)
{
res = CompareItems2(lParam1, lParam2, panel, propID,
iter ? 0 : panel->_isRawSortProp);
if (res)
break;
if (propID == kpidName)
{
// if (!_flatMode.IsEmpty()) break; // !_flatMode ;
propID = kpidPrefix;
continue;
}
if (iter)
break;
propID = kpidName;
}
if (res == 0)
res = MyCompare(lParam1, lParam2); // order of LoadSubItems()
return panel->_ascending ? res: -res;
}

View file

@ -440,11 +440,9 @@ static const size_t kMaxDicSize = (size_t)1 << (22 + sizeof(size_t) / 4 * 5);
static int ComboBox_Add_UInt32(NWindows::NControl::CComboBox &cb, UInt32 v)
{
TCHAR s[16];
WCHAR s[16];
ConvertUInt32ToString(v, s);
const int index = (int)cb.AddString(s);
cb.SetItemData(index, (LPARAM)v);
return index;
return (int)cb.AddString_SetItemData(s, (LPARAM)v);
}
@ -481,21 +479,17 @@ bool CBenchmarkDialog::OnInit()
_consoleEdit.SendMsg(WM_SETFONT, (WPARAM)_font._font, TRUE);
}
UInt32 numCPUs = 1;
UInt32 numCPUs = 1; // process threads
UInt32 numCPUs_Sys = 1; // system threads
{
AString s ("/ ");
NSystem::CProcessAffinity threadsInfo;
threadsInfo.InitST();
#ifndef Z7_ST
threadsInfo.Get_and_return_NumProcessThreads_and_SysThreads(numCPUs, numCPUs_Sys);
#endif
#ifndef Z7_ST
if (threadsInfo.Get() && threadsInfo.processAffinityMask != 0)
numCPUs = threadsInfo.GetNumProcessThreads();
else
numCPUs = NSystem::GetNumberOfProcessors();
#endif
AString s ("/ ");
s.Add_UInt32(numCPUs);
s += GetProcessThreadsInfo(threadsInfo);
SetItemTextA(IDT_BENCH_HARDWARE_THREADS, s);
@ -506,10 +500,8 @@ bool CBenchmarkDialog::OnInit()
SetItemTextA(IDT_BENCH_SYS1, s);
if (s != s2 && !s2.IsEmpty())
SetItemTextA(IDT_BENCH_SYS2, s2);
}
{
AString registers;
GetCpuName_MultiLine(s, registers);
GetCpuName_MultiLine(s, s2); // s2==registers
SetItemTextA(IDT_BENCH_CPU, s);
}
{
@ -526,22 +518,18 @@ bool CBenchmarkDialog::OnInit()
// ----- Num Threads ----------
if (numCPUs < 1)
numCPUs = 1;
numCPUs = MyMin(numCPUs, (UInt32)(1 << 6)); // it's WIN32 limit
UInt32 numThreads = Sync.NumThreads;
if (numThreads == (UInt32)(Int32)-1)
numThreads = numCPUs;
if (numThreads > 1)
numThreads &= ~(UInt32)1;
const UInt32 kNumThreadsMax = (1 << 12);
if (numThreads > kNumThreadsMax)
numThreads = kNumThreadsMax;
numThreads &= ~(UInt32)1;
if (numThreads == 0)
numThreads = 1;
numThreads = MyMin(numThreads, (UInt32)(1u << 14));
m_NumThreads.Attach(GetItem(IDC_BENCH_NUM_THREADS));
const UInt32 numTheads_Combo = numCPUs * 2;
if (numCPUs_Sys == 0)
numCPUs_Sys = 1;
const UInt32 numTheads_Combo = numCPUs_Sys * 2;
UInt32 v = 1;
int cur = 0;
for (; v <= numTheads_Combo;)
@ -1069,16 +1057,17 @@ static void AddUsageString(UString &s, const CTotalBenchRes &info)
numIter = 1000000;
UInt64 usage = GetUsagePercents(info.Usage / numIter);
wchar_t w[64];
ConvertUInt64ToString(usage, w);
unsigned len = MyStringLen(w);
wchar_t w[32];
wchar_t *p = ConvertUInt64ToString(usage, w);
p[0] = '%';
p[1] = 0;
unsigned len = (unsigned)(size_t)(p - w);
while (len < 5)
{
s.Add_Space();
len++;
}
s += w;
s += "%";
}

View file

@ -506,8 +506,7 @@ bool CCompressDialog::OnInit()
{
const unsigned arcIndex = ArcIndices[i];
const CArcInfoEx &ai = (*ArcFormats)[arcIndex];
const int index = (int)m_Format.AddString(ai.Name);
m_Format.SetItemData(index, (LPARAM)arcIndex);
const int index = (int)m_Format.AddString_SetItemData(ai.Name, (LPARAM)arcIndex);
if (!needSetMain)
{
if (Info.FormatIndex == (int)arcIndex)
@ -540,11 +539,6 @@ bool CCompressDialog::OnInit()
AddComboItems(m_PathMode, k_PathMode_IDs, Z7_ARRAY_SIZE(k_PathMode_IDs),
k_PathMode_Vals, Info.PathMode);
TCHAR s[32] = { TEXT('/'), TEXT(' '), 0 };
ConvertUInt32ToString(NSystem::GetNumberOfProcessors(), s + 2);
SetItemText(IDT_COMPRESS_HARDWARE_THREADS, s);
CheckButton(IDX_COMPRESS_SHARED, Info.OpenShareForWrite);
CheckButton(IDX_COMPRESS_DEL, Info.DeleteAfterCompressing);
@ -653,7 +647,19 @@ void CCompressDialog::EnableMultiCombo(unsigned id)
EnableItem(id, enable);
}
static LRESULT ComboBox_AddStringAscii(NControl::CComboBox &cb, const char *s);
static LRESULT ComboBox_AddStringAscii(NControl::CComboBox &cb, const char *s)
{
return cb.AddString((CSysString)s);
}
static LRESULT ComboBox_AddStringAscii_SetItemData(NControl::CComboBox &cb,
const char *s, LPARAM lParam)
{
const LRESULT index = ComboBox_AddStringAscii(cb, s);
if (index >= 0) // optional check
cb.SetItemData((int)index, lParam);
return index;
}
static void Combine_Two_BoolPairs(const CBoolPair &b1, const CBoolPair &b2, CBool1 &res)
{
@ -1604,20 +1610,14 @@ void CCompressDialog::SetLevel2()
AddLangString(s, langID);
}
}
const int index = (int)m_Level.AddString(s);
m_Level.SetItemData(index, (LPARAM)i);
m_Level.AddString_SetItemData(s, (LPARAM)i);
}
}
SetNearestSelectComboBox(m_Level, level);
}
static LRESULT ComboBox_AddStringAscii(NControl::CComboBox &cb, const char *s)
{
return cb.AddString((CSysString)s);
}
static const char *k_Auto_Prefix = "* ";
static const char * const k_Auto_Prefix = "* ";
static void Modify_Auto(AString &s)
{
@ -1690,8 +1690,8 @@ void CCompressDialog::SetMethod2(int keepMethodId)
writtenMethodId = -1;
Modify_Auto(s);
}
const int itemIndex = (int)ComboBox_AddStringAscii(m_Method, s);
m_Method.SetItemData(itemIndex, writtenMethodId);
const int itemIndex = (int)ComboBox_AddStringAscii_SetItemData(m_Method,
s, writtenMethodId);
if (keepMethodId == methodID)
{
m_Method.SetCurSel(itemIndex);
@ -1731,7 +1731,7 @@ void CCompressDialog::SetEncryptionMethod()
}
else if (ai.Is_Zip())
{
int index = FindRegistryFormat(ai.Name);
const int index = FindRegistryFormat(ai.Name);
UString encryptionMethod;
if (index >= 0)
{
@ -1836,9 +1836,7 @@ static int Combo_AddDict2(NWindows::NControl::CComboBox &cb, size_t sizeReal, si
s.Add_Char('B');
if (sizeReal == k_Auto_Dict)
Modify_Auto(s);
const int index = (int)ComboBox_AddStringAscii(cb, s);
cb.SetItemData(index, (LPARAM)sizeReal);
return index;
return (int)ComboBox_AddStringAscii_SetItemData(cb, s, (LPARAM)sizeReal);
}
int CCompressDialog::AddDict2(size_t sizeReal, size_t sizeShow)
@ -2201,9 +2199,7 @@ int CCompressDialog::AddOrder(UInt32 size)
{
char s[32];
ConvertUInt32ToString(size, s);
const int index = (int)ComboBox_AddStringAscii(m_Order, s);
m_Order.SetItemData(index, (LPARAM)size);
return index;
return (int)ComboBox_AddStringAscii_SetItemData(m_Order, s, (LPARAM)size);
}
int CCompressDialog::AddOrder_Auto()
@ -2211,9 +2207,7 @@ int CCompressDialog::AddOrder_Auto()
AString s;
s.Add_UInt32(_auto_Order);
Modify_Auto(s);
int index = (int)ComboBox_AddStringAscii(m_Order, s);
m_Order.SetItemData(index, (LPARAM)(INT_PTR)(-1));
return index;
return (int)ComboBox_AddStringAscii_SetItemData(m_Order, s, (LPARAM)(INT_PTR)(-1));
}
void CCompressDialog::SetOrder2()
@ -2490,9 +2484,7 @@ void CCompressDialog::SetSolidBlockSize2()
AString s;
Add_Size(s, _auto_Solid);
Modify_Auto(s);
const int index = (int)ComboBox_AddStringAscii(m_Solid, s);
m_Solid.SetItemData(index, (LPARAM)(UInt32)(Int32)-1);
curSel = index;
curSel = (int)ComboBox_AddStringAscii_SetItemData(m_Solid, s, (LPARAM)(UInt32)(Int32)-1);
}
if (is7z)
@ -2501,8 +2493,7 @@ void CCompressDialog::SetSolidBlockSize2()
// kSolidLog_NoSolid = 0 for xz means default blockSize
if (is7z)
LangString(IDS_COMPRESS_NON_SOLID, s);
const int index = (int)m_Solid.AddString(s);
m_Solid.SetItemData(index, (LPARAM)(UInt32)kSolidLog_NoSolid);
const int index = (int)m_Solid.AddString_SetItemData(s, (LPARAM)(UInt32)kSolidLog_NoSolid);
if (defaultBlockSize == kSolidLog_NoSolid)
curSel = index;
}
@ -2511,16 +2502,15 @@ void CCompressDialog::SetSolidBlockSize2()
{
AString s;
Add_Size(s, (UInt64)1 << i);
const int index = (int)ComboBox_AddStringAscii(m_Solid, s);
m_Solid.SetItemData(index, (LPARAM)(UInt32)i);
const int index = (int)ComboBox_AddStringAscii_SetItemData(m_Solid, s, (LPARAM)(UInt32)i);
if (defaultBlockSize != (UInt32)(Int32)-1)
if (i <= defaultBlockSize || index <= 1)
curSel = index;
}
{
const int index = (int)m_Solid.AddString(LangString(IDS_COMPRESS_SOLID));
m_Solid.SetItemData(index, (LPARAM)kSolidLog_FullSolid);
const int index = (int)m_Solid.AddString_SetItemData(
LangString(IDS_COMPRESS_SOLID), (LPARAM)kSolidLog_FullSolid);
if (defaultBlockSize == kSolidLog_FullSolid)
curSel = index;
}
@ -2564,7 +2554,7 @@ static bool Is_Zstd_Mt_Supported()
}
*/
static const char *k_ST_Threads = " (ST)";
static const char * const k_ST_Threads = " (ST)";
void CCompressDialog::SetNumThreads2()
{
@ -2575,15 +2565,31 @@ void CCompressDialog::SetNumThreads2()
if (!fi.MultiThread_())
return;
const UInt32 numHardwareThreads = NSystem::GetNumberOfProcessors();
// 64; // for debug:
UInt32 numCPUs = 1; // process threads
UInt32 numHardwareThreads = 1; // system threads
NSystem::CProcessAffinity threadsInfo;
threadsInfo.InitST();
#ifndef Z7_ST
threadsInfo.Get_and_return_NumProcessThreads_and_SysThreads(numCPUs, numHardwareThreads);
#endif
UInt32 defaultValue = numHardwareThreads;
AString s ("/ ");
{
s.Add_UInt32(numCPUs);
if (numCPUs != numHardwareThreads)
{
s += " / ";
s.Add_UInt32(numHardwareThreads);
}
SetItemTextA(IDT_COMPRESS_HARDWARE_THREADS, s.Ptr());
}
UInt32 defaultValue = numCPUs;
bool useAutoThreads = true;
{
const CArcInfoEx &ai = Get_ArcInfoEx();
int index = FindRegistryFormat(ai.Name);
const int index = FindRegistryFormat(ai.Name);
if (index >= 0)
{
const NCompression::CFormatOptions &fo = m_RegistryInfo.Formats[index];
@ -2597,19 +2603,19 @@ void CCompressDialog::SetNumThreads2()
// const UInt32 num_ZSTD_threads_MAX = Is_Zstd_Mt_Supported() ? MY_ZSTDMT_NBWORKERS_MAX : 0;
UInt32 numAlgoThreadsMax = numHardwareThreads * 2;
const int methodID = GetMethodID();
const bool isZip = IsZipFormat();
UInt32 numAlgoThreadsMax = numHardwareThreads * 2; // for unknow methods
if (isZip)
numAlgoThreadsMax =
8 << (sizeof(size_t) / 2); // 32 threads for 32-bit : 128 threads for 64-bit
else if (IsXzFormat())
numAlgoThreadsMax = 256 * 2;
numAlgoThreadsMax = 256 * 2; // MTCODER_THREADS_MAX * 2
else switch (methodID)
{
case kLZMA: numAlgoThreadsMax = 2; break;
case kLZMA2: numAlgoThreadsMax = 256; break;
case kLZMA2: numAlgoThreadsMax = 256 * 2; break; // MTCODER_THREADS_MAX * 2
case kBZip2: numAlgoThreadsMax = 64; break;
// case kZSTD: numAlgoThreadsMax = num_ZSTD_threads_MAX; break;
case kCopy:
@ -2619,9 +2625,9 @@ void CCompressDialog::SetNumThreads2()
case kPPMdZip:
numAlgoThreadsMax = 1;
}
UInt32 autoThreads = numHardwareThreads;
UInt32 autoThreads = numCPUs;
if (autoThreads > numAlgoThreadsMax)
autoThreads = numAlgoThreadsMax;
autoThreads = numAlgoThreadsMax;
const UInt64 memUse_Limit = Get_MemUse_Bytes();
@ -2676,13 +2682,12 @@ void CCompressDialog::SetNumThreads2()
int curSel = -1;
{
AString s;
s.Empty();
s.Add_UInt32(autoThreads);
if (autoThreads == 0) s += k_ST_Threads;
Modify_Auto(s);
const int index = (int)ComboBox_AddStringAscii(m_NumThreads, s);
m_NumThreads.SetItemData(index, (LPARAM)(INT_PTR)(-1));
// m_NumThreads.SetItemData(index, autoThreads);
const int index = (int)ComboBox_AddStringAscii_SetItemData(m_NumThreads,
s, (LPARAM)(INT_PTR)(-1));
if (useAutoThreads)
curSel = index;
}
@ -2693,11 +2698,11 @@ void CCompressDialog::SetNumThreads2()
1;
i <= numHardwareThreads * 2 && i <= numAlgoThreadsMax; i++)
{
AString s;
s.Empty();
s.Add_UInt32(i);
if (i == 0) s += k_ST_Threads;
const int index = (int)ComboBox_AddStringAscii(m_NumThreads, s);
m_NumThreads.SetItemData(index, (LPARAM)(UInt32)i);
const int index = (int)ComboBox_AddStringAscii_SetItemData(m_NumThreads,
s, (LPARAM)(UInt32)i);
if (!useAutoThreads && i == defaultValue)
curSel = index;
}
@ -2754,9 +2759,7 @@ int CCompressDialog::AddMemComboItem(UInt64 val, bool isPercent, bool isDefault)
sRegistry.DeleteBack();
}
const unsigned dataIndex = _memUse_Strings.Add(sRegistry);
const int index = (int)m_MemUse.AddString(sUser);
m_MemUse.SetItemData(index, (LPARAM)dataIndex);
return index;
return (int)m_MemUse.AddString_SetItemData(sUser, (LPARAM)dataIndex);
}
@ -3439,11 +3442,7 @@ static const unsigned kTimePrec_1ns = 3;
static void AddTimeOption(UString &s, UInt32 val, const UString &unit, const char *sys = NULL)
{
// s += " : ";
{
AString s2;
s2.Add_UInt32(val);
s += s2;
}
s.Add_UInt32(val);
s.Add_Space();
s += unit;
if (sys)
@ -3476,9 +3475,7 @@ int COptionsDialog::AddPrec(unsigned prec, bool isDefault)
}
else
s.Add_UInt32(prec);
const int index = (int)m_Prec.AddString(s);
m_Prec.SetItemData(index, (LPARAM)writePrec);
return index;
return (int)m_Prec.AddString_SetItemData(s, (LPARAM)writePrec);
}

View file

@ -87,8 +87,8 @@ BEGIN
COMBOBOX IDC_COMPRESS_SOLID, g1x, 144, g1xs, 140, MY_COMBO
LTEXT "Number of CPU &threads:", IDT_COMPRESS_THREADS, m, 167, g0xs, 8
COMBOBOX IDC_COMPRESS_THREADS, g1x, 165, g1xs - 35, 140, MY_COMBO
RTEXT "", IDT_COMPRESS_HARDWARE_THREADS, g1x + g1xs - 35 + 10, 167, 25, MY_TEXT_NOPREFIX
COMBOBOX IDC_COMPRESS_THREADS, g1x, 165, g1xs - 40, 140, MY_COMBO
RTEXT "", IDT_COMPRESS_HARDWARE_THREADS, g1x + g1xs - 40, 167, 40, 16, SS_NOPREFIX
LTEXT "Memory usage for Compressing:", IDT_COMPRESS_MEMORY, m, 184, g2xs, 8

View file

@ -102,8 +102,7 @@ void AddComboItems(NControl::CComboBox &combo, const UInt32 *langIDs, unsigned n
{
UString s = LangString(langIDs[i]);
s.RemoveChar(L'&');
const int index = (int)combo.AddString(s);
combo.SetItemData(index, (LPARAM)i);
combo.AddString_SetItemData(s, (LPARAM)i);
if (values[i] == curVal)
curSel = i;
}

View file

@ -126,8 +126,9 @@ if compiled with new GCC libstdc++, GCC libstdc++ can use:
#pragma GCC diagnostic ignored "-Wglobal-constructors"
#pragma GCC diagnostic ignored "-Wexit-time-destructors"
#if defined(Z7_LLVM_CLANG_VERSION) && __clang_major__ >= 18 // 18.1.0RC
#pragma GCC diagnostic ignored "-Wswitch-default"
#if defined(Z7_LLVM_CLANG_VERSION) && __clang_major__ >= 18 /* 18.1.0RC */ \
|| defined(Z7_APPLE_CLANG_VERSION) && __clang_major__ >= 16 // for APPLE=17 (LLVM=19)
#pragma GCC diagnostic ignored "-Wswitch-default"
#endif
// #pragma GCC diagnostic ignored "-Wunused-private-field"
// #pragma GCC diagnostic ignored "-Wnonportable-system-include-path"

View file

@ -202,7 +202,53 @@ public:
}
};
typedef CObjArray<Byte> CByteArr;
/* CSmallObjArray can be used for Byte arrays
or for arrays whose total size in bytes does not exceed size_t ranges.
So there is no need to use Z7_ARRAY_NEW macro in CSmallObjArray code. */
template <class T> class CSmallObjArray
{
protected:
T *_items;
private:
// we disable copy
CSmallObjArray(const CSmallObjArray &buffer);
void operator=(const CSmallObjArray &buffer);
public:
void Free()
{
delete []_items;
_items = NULL;
}
CSmallObjArray(size_t size): _items(NULL)
{
if (size != 0)
{
// Z7_ARRAY_NEW(_items, T, size)
_items = new T[size];
}
}
CSmallObjArray(): _items(NULL) {}
~CSmallObjArray() { delete []_items; }
operator T *() { return _items; }
operator const T *() const { return _items; }
const T* ConstData() const { return _items; }
T* NonConstData() const { return _items; }
T* NonConstData() { return _items; }
// const T* Data() const { return _items; }
// T* Data() { return _items; }
void Alloc(size_t newSize)
{
delete []_items;
_items = NULL;
// Z7_ARRAY_NEW(_items, T, newSize)
_items = new T[newSize];
}
};
typedef CSmallObjArray<Byte> CByteArr;
typedef CObjArray<bool> CBoolArr;
typedef CObjArray<int> CIntArr;
typedef CObjArray<unsigned> CUIntArr;

View file

@ -63,4 +63,13 @@ LRESULT CComboBox::GetLBText(int index, UString &s)
}
#endif
LRESULT CComboBox::AddString_SetItemData(LPCWSTR s, LPARAM lParam)
{
const LRESULT index = AddString(s);
// NOTE: SetItemData((int)-1, lParam) works as unexpected.
if (index >= 0) // optional check, because (index < 0) is not expected for normal inputs
SetItemData((int)index, lParam);
return index;
}
}}

View file

@ -21,6 +21,8 @@ public:
LRESULT AddString(LPCWSTR s);
#endif
LRESULT AddString_SetItemData(LPCWSTR s, LPARAM lParam);
/* If this parameter is -1, any current selection in the list is removed and the edit control is cleared.*/
LRESULT SetCurSel(int index) { return SendMsg(CB_SETCURSEL, MY_int_TO_WPARAM(index), 0); }
LRESULT SetCurSel(unsigned index) { return SendMsg(CB_SETCURSEL, index, 0); }

View file

@ -1162,6 +1162,15 @@ void CFileInfoBase::SetFrom_stat(const struct stat &st)
MTime = st.st_mtimespec;
ATime = st.st_atimespec;
#elif defined(__QNXNTO__) && defined(__ARM__) && !defined(__aarch64__)
// CTime = ST_CTIME(st);
// MTime = ST_MTIME(st);
// ATime = ST_ATIME(st);
CTime.tv_sec = st.st_ctime; CTime.tv_nsec = 0;
MTime.tv_sec = st.st_mtime; MTime.tv_nsec = 0;
ATime.tv_sec = st.st_atime; ATime.tv_nsec = 0;
#else
// timespec_To_FILETIME(st.st_ctim, CTime, &CTime_ns100);
// timespec_To_FILETIME(st.st_mtim, MTime, &MTime_ns100);
@ -1312,7 +1321,7 @@ bool CDirEntry::IsDots() const throw()
/* some systems (like CentOS 7.x on XFS) have (Type == DT_UNKNOWN)
we can call fstatat() for that case, but we use only (Name) check here */
#if !defined(_AIX) && !defined(__sun)
#if !defined(_AIX) && !defined(__sun) && !defined(__QNXNTO__)
if (Type != DT_DIR && Type != DT_UNKNOWN)
return false;
#endif
@ -1352,7 +1361,7 @@ bool CEnumerator::NextAny(CDirEntry &fi, bool &found)
fi.iNode = de->d_ino;
#if !defined(_AIX) && !defined(__sun)
#if !defined(_AIX) && !defined(__sun) && !defined(__QNXNTO__)
fi.Type = de->d_type;
/* some systems (like CentOS 7.x on XFS) have (Type == DT_UNKNOWN)
we can set (Type) from fstatat() in that case.

View file

@ -277,13 +277,13 @@ typedef CFileInfo CDirEntry;
struct CDirEntry
{
ino_t iNode;
#if !defined(_AIX) && !defined(__sun)
#if !defined(_AIX) && !defined(__sun) && !defined(__QNXNTO__)
Byte Type;
#endif
FString Name;
/*
#if !defined(_AIX) && !defined(__sun)
#if !defined(_AIX) && !defined(__sun) && !defined(__QNXNTO__)
bool IsDir() const
{
// (Type == DT_UNKNOWN) on some systems
@ -310,7 +310,7 @@ public:
bool Fill_FileInfo(const CDirEntry &de, CFileInfo &fileInfo, bool followLink) const;
bool DirEntry_IsDir(const CDirEntry &de, bool followLink) const
{
#if !defined(_AIX) && !defined(__sun)
#if !defined(_AIX) && !defined(__sun) && !defined(__QNXNTO__)
if (de.Type == DT_DIR)
return true;
if (de.Type != DT_UNKNOWN)

View file

@ -3,7 +3,11 @@
#ifndef ZIP7_INC_WINDOWS_SECURITY_UTILS_H
#define ZIP7_INC_WINDOWS_SECURITY_UTILS_H
#if defined(__MINGW32__) || defined(__MINGW64__)
#include <ntsecapi.h>
#else
#include <NTSecAPI.h>
#endif
#include "Defs.h"

View file

@ -5,8 +5,9 @@
#ifndef _WIN32
#include <unistd.h>
#include <limits.h>
#if defined(__APPLE__) || defined(__DragonFly__) || \
defined(BSD) || defined(__FreeBSD__) || defined(__NetBSD__) || defined(__OpenBSD__)
#if defined(__APPLE__) || defined(__DragonFly__) \
|| defined(BSD) || defined(__FreeBSD__) || defined(__NetBSD__) || defined(__OpenBSD__) \
|| defined(__QNXNTO__)
#include <sys/sysctl.h>
#else
#include <sys/sysinfo.h>
@ -299,8 +300,9 @@ bool GetRamSize(size_t &size)
size = (size_t)sizeof(size_t) << 29;
size64 = size;
#if defined(__APPLE__) || defined(__DragonFly__) || \
defined(BSD) || defined(__FreeBSD__) || defined(__NetBSD__) || defined(__OpenBSD__)
#if defined(__APPLE__) || defined(__DragonFly__) \
|| defined(BSD) || defined(__FreeBSD__) || defined(__NetBSD__) || defined(__OpenBSD__) \
|| defined(__QNXNTO__)
uint64_t val = 0;
int mib[2];

View file

@ -15,6 +15,8 @@
namespace NWindows {
namespace NSystem {
UInt32 GetNumberOfProcessors();
#ifdef _WIN32
struct CCpuGroups
@ -103,6 +105,25 @@ struct CProcessAffinity
return CountAffinity(systemAffinityMask);
}
// it returns normilized number of threads
void Get_and_return_NumProcessThreads_and_SysThreads(UInt32 &numProcessThreads, UInt32 &numSysThreads)
{
UInt32 num1 = 0, num2 = 0;
if (Get())
{
num1 = GetNumProcessThreads();
num2 = GetNumSystemThreads();
}
if (num1 == 0)
num1 = NSystem::GetNumberOfProcessors();
if (num1 == 0)
num1 = 1;
if (num2 < num1)
num2 = num1;
numProcessThreads = num1;
numSysThreads = num2;
}
BOOL Get();
BOOL SetProcAffinity() const
@ -177,8 +198,6 @@ struct CProcessAffinity
#endif // _WIN32
UInt32 GetNumberOfProcessors();
bool GetRamSize(size_t &size); // returns false, if unknown ram size
unsigned long Get_File_OPEN_MAX();

View file

@ -22,7 +22,7 @@
#if defined(__GLIBC__) && (__GLIBC__ * 100 + __GLIBC_MINOR__ >= 216)
#define Z7_GETAUXV_AVAILABLE
#else
#elif !defined(__QNXNTO__)
// #pragma message("=== is not NEW GLIBC === ")
#if defined __has_include
#if __has_include (<sys/auxv.h>)
@ -58,7 +58,7 @@
#ifdef USE_HWCAP
#if defined(__FreeBSD__)
#if defined(__FreeBSD__) || defined(__OpenBSD__)
// #if (__FreeBSD__ >= 13) // (FreeBSD 12.01 is required for elf_aux_info() ???)
static unsigned long MY_getauxval(int aux)

View file

@ -65,6 +65,14 @@ inline bool FILETIME_IsZero(const FILETIME &ft)
#define ST_MTIME(st) st.st_mtimespec
#define ST_ATIME(st) st.st_atimespec
#define ST_CTIME(st) st.st_ctimespec
#elif defined(__QNXNTO__) && defined(__ARM__) && !defined(__aarch64__)
// QNX armv7le (32-bit) for "struct stat" timestamps uses time_t instead of timespec
inline CFiTime ST_MTIME(const struct stat &st)
{ timespec ts; ts.tv_sec = st.st_mtime; ts.tv_nsec = 0; return ts; }
inline CFiTime ST_ATIME(const struct stat &st)
{ timespec ts; ts.tv_sec = st.st_atime; ts.tv_nsec = 0; return ts; }
inline CFiTime ST_CTIME(const struct stat &st)
{ timespec ts; ts.tv_sec = st.st_ctime; ts.tv_nsec = 0; return ts; }
#else
#define ST_MTIME(st) st.st_mtim
#define ST_ATIME(st) st.st_atim

View file

@ -1,7 +1,7 @@
<?xml version="1.0"?>
<?define VerMajor = "25" ?>
<?define VerMinor = "01" ?>
<?define VerMajor = "26" ?>
<?define VerMinor = "00" ?>
<?define VerBuild = "00" ?>
<?define MmVer = "$(var.VerMajor).$(var.VerMinor)" ?>
<?define MmHex = "$(var.VerMajor)$(var.VerMinor)" ?>

View file

@ -3,7 +3,7 @@
License for use and distribution
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
7-Zip Copyright (C) 1999-2025 Igor Pavlov.
7-Zip Copyright (C) 1999-2026 Igor Pavlov.
The licenses for files are:
@ -58,7 +58,7 @@ BSD 3-clause License in 7-Zip code
Copyright (c) 2015-2016, Apple Inc. All rights reserved.
Copyright (c) Facebook, Inc. All rights reserved.
Copyright (c) 2023-2025 Igor Pavlov.
Copyright (c) 2023-2026 Igor Pavlov.
Text of the "BSD 3-clause License"
----------------------------------
@ -102,7 +102,7 @@ BSD 2-clause License in 7-Zip code
XXH64 code in 7-Zip was derived from the original XXH64 code developed by Yann Collet.
Copyright (c) 2012-2021 Yann Collet.
Copyright (c) 2023-2025 Igor Pavlov.
Copyright (c) 2023-2026 Igor Pavlov.
Text of the "BSD 2-clause License"
----------------------------------

View file

@ -1,15 +1,15 @@
7-Zip 25.01 Sources
7-Zip 26.00 Sources
-------------------
7-Zip is a file archiver for Windows.
7-Zip is a file archiver for Windows.
7-Zip Copyright (C) 1999-2025 Igor Pavlov.
7-Zip Copyright (C) 1999-2026 Igor Pavlov.
License Info
------------
7-Zip is free software distributed under the GNU LGPL
7-Zip is free software distributed under the GNU LGPL
(except for unRar code). Also some code
is licensed under the "BSD 3-clause License".
Read "License.txt" for more infomation about license.
@ -27,7 +27,7 @@ Please check main restriction from unRar license:
not be used to develop a RAR (WinRAR) compatible archiver.
In brief it means:
1) You can compile and use compiled files under GNU LGPL rules, since
1) You can compile and use compiled files under GNU LGPL rules, since
unRAR license almost has no restrictions for compiled files.
You can link these compiled files to LGPL programs.
2) You can fix bugs in source code and use compiled fixed version.
@ -60,7 +60,7 @@ Tools / Options / Directories
- Library files
Also you need Microsoft Macro Assembler:
- ml.exe for x86
- ml.exe for x86
- ml64.exe for x64
You can use ml.exe from Windows SDK for Windows Vista or some later versions.
@ -85,7 +85,7 @@ OLD_COMPILER
for old VC compiler, like MSCV 6.0.
MY_DYNAMIC_LINK
for dynamic linking to the run-time library (msvcrt.dll).
for dynamic linking to the run-time library (msvcrt.dll).
The default makefile option is static linking to the run-time library.
To compile all 7-Zip files for x64 with Visual Studio 2022,
@ -116,23 +116,23 @@ So if you compile the version with Assembeler code, you will get faster 7-Zip bi
7-Zip's assembler code uses the following syntax for different platforms:
1) x86 and x86-64 (AMD64): MASM syntax.
1) x86 and x86-64 (AMD64): MASM syntax.
Now there are 3 programs that supports MASM syntax in Linux.
' 'Asmc Macro Assembler, JWasm, and UASM. Note that JWasm now doesn't support some
' 'Asmc Macro Assembler, JWasm, and UASM. Note that JWasm now doesn't support some
cpu instructions used in 7-Zip.
So you must install Asmc Macro Assembler in Linux or UASM, if you want to compile
So you must install Asmc Macro Assembler in Linux or UASM, if you want to compile
fastest version of 7-Zip x86 and x86-64:
https://github.com/nidud/asmc
https://github.com/Terraspace/UASM
2) arm64: GNU assembler for ARM64 with preprocessor.
2) arm64: GNU assembler for ARM64 with preprocessor.
That systax is supported by GCC and CLANG for ARM64.
There are different binaries that can be compiled from 7-Zip source.
There are 2 main files in folder for compiling:
makefile - that can be used for compiling Windows version of 7-Zip with nmake command
makefile.gcc - that can be used for compiling Linux/macOS versions of 7-Zip or Windows version
makefile.gcc - that can be used for compiling Linux/macOS versions of 7-Zip or Windows version
with MINGW (GCC) with make command.
At first you must change the current folder to folder that contains `makefile.gcc`:
@ -143,7 +143,7 @@ Then you can compile `makefile.gcc` with the command:
make -j -f makefile.gcc
Also there are additional "*.mak" files in folder "CPP/7zip/" that can be used to compile
Also there are additional "*.mak" files in folder "CPP/7zip/" that can be used to compile
7-Zip binaries with optimized code and optimzing options.
To compile with GCC without assembler:
@ -171,10 +171,10 @@ makefile.gcc supports some variables that can change compile options
USE_JWASM=1
use JWasm assembler instead of Asmc.
Note that JWasm doesn't support AES instructions. So AES code from C version AesOpt.c
Note that JWasm doesn't support AES instructions. So AES code from C version AesOpt.c
will be used instead of assembler code from AesOpt.asm.
If you want to use UASM for x86-64 compiling, you can change 7zip_gcc.mak,
If you want to use UASM for x86-64 compiling, you can change 7zip_gcc.mak,
or send IS_X64=1 USE_ASM=1 MY_ASM="$UASM" to make command calling:
UASM="$PWD/GccUnixR/uasm"
cd "7zip-src/CPP/7zip/Bundles/Alone2"
@ -187,11 +187,11 @@ DISABLE_RAR=1
DISABLE_RAR_COMPRESS=1
removes "not fully free" code of RAR decompression codecs from compilation.
RAR decompression codecs in 7-Zip code has some additional license restrictions,
RAR decompression codecs in 7-Zip code has some additional license restrictions,
that can be treated as not fully compatible with free-software licenses.
DISABLE_RAR_COMPRESS=1 allows to exclude such "not-fully-free" RAR code from compilation.
if DISABLE_RAR_COMPRESS=1 is specified, 7-zip will not be able to decompress files
from rar archives, but 7-zip still will be able to open rar archives to get list of
if DISABLE_RAR_COMPRESS=1 is specified, 7-zip will not be able to decompress files
from rar archives, but 7-zip still will be able to open rar archives to get list of
files or to extract files that are stored without compression.
if DISABLE_RAR=1 is specified, 7-zip will not be able to work with RAR archives.
@ -203,11 +203,11 @@ Now there are two different ports of 7-Zip for Linux/macOS:
1) p7zip - another port of 7-Zip for Linux, made by an independent developer.
The latest version of p7zip now is 16.02, and that p7zip 16.02 is outdated now.
http://sourceforge.net/projects/p7zip/
http://sourceforge.net/projects/p7zip/
2) 7-Zip for Linux/macOS - this package - it's new code with all changes from latest 7-Zip for Windows.
These two ports are not identical.
These two ports are not identical.
Note also that some Linux specific things can be implemented better in p7zip than in new 7-Zip for Linux.
@ -218,13 +218,13 @@ Notes:
7-Zip consists of COM modules (DLL files).
But 7-Zip doesn't use standard COM interfaces for creating objects.
Look at
7zip\UI\Client7z folder for example of using DLL files of 7-Zip.
7zip\UI\Client7z folder for example of using DLL files of 7-Zip.
Some DLL files can use other DLL files from 7-Zip.
If you don't like it, you must use standalone version of DLL.
To compile standalone version of DLL you must include all used parts
to project and define some defs.
For example, 7zip\Bundles\Format7z is a standalone version of 7z.dll
that works with 7z format. So you can use such DLL in your project
to project and define some defs.
For example, 7zip\Bundles\Format7z is a standalone version of 7z.dll
that works with 7z format. So you can use such DLL in your project
without additional DLL files.
@ -284,7 +284,7 @@ Windows common files for Windows related code
UI
Agent Intermediary modules for FAR plugin and Explorer plugin
Client7z Test application for 7za.dll
Client7z Test application for 7za.dll
Common Common UI files
Console 7z.exe : Console version
Explorer 7-zip.dll: 7-Zip Shell extension

View file

@ -1,11 +1,20 @@
HISTORY of the 7-Zip source code
--------------------------------
26.00 2026-02-12
-------------------------
- improved code for ZIP, CPIO, RAR, UFD, QCOW, Compound.
- 7-Zip File Manager: improved sorting order of the file list. It uses file name as secondary sorting key.
- 7-Zip File Manager: improved Benchmark to support systems with more than 64 CPU threads.
- the bug was fixed: 7-Zip could not correctly extract TAR archives containing sparse files.
- some bugs were fixed.
25.01 2025-08-03
-------------------------
- The code for handling symbolic links has been changed
- CVE-2025-55188 : The code for handling symbolic links has been changed
to provide greater security when extracting files from archives.
Command line switch -snld20 can be used to bypass default security
Command line switch -snld20 can be used to bypass default security
checks when creating symbolic links.
@ -18,17 +27,19 @@ HISTORY of the 7-Zip source code
- bzip2 compression speed was increased by 15-40%.
- deflate (zip/gz) compression speed was increased by 1-3%.
- improved support for zip, cpio and fat archives.
- fixed some bugs and vulnerabilities.
- the bug was fixed : CVE-2025-53816 : 7-Zip could work incorrectly for some incorrect RAR archives.
- the bug was fixed : CVE-2025-53817 : 7-Zip could crash for some incorrect COM (Compound File) archives.
- fixed some bugs.
- CVE-2025-11001 and CVE-2025-11002 : A vulnerability was fixed for symbolic links processing,
when extracting files from archives.
- the bug was fixed : CVE-2025-53816 : 7-Zip could work incorrectly for some incorrect RAR archives.
- the bug was fixed : CVE-2025-53817 : 7-Zip could crash for some incorrect COM (Compound File) archives.
24.09 2024-11-29
-------------------------
- The default dictionary size values for LZMA/LZMA2 compression methods were increased:
dictionary size compression level
v24.08 v24.09 v24.09
32-bit 64-bit
v24.08 v24.09 v24.09
32-bit 64-bit
8 MB 16 MB 16 MB -mx4
16 MB 32 MB 32 MB -mx5 : Normal
32 MB 64 MB 64 MB -mx6
@ -38,11 +49,11 @@ HISTORY of the 7-Zip source code
The default dictionary size values for 32-bit versions of LZMA/LZMA2 don't exceed 64 MB.
- 7-Zip now can calculate the following hash checksums: SHA-512, SHA-384, SHA3-256 and MD5.
- APM and HFS support was improved.
- If an archive update operation uses a temporary archive folder and
the archive is moved to the destination folder, 7-Zip shows the progress of moving
- If an archive update operation uses a temporary archive folder and
the archive is moved to the destination folder, 7-Zip shows the progress of moving
the archive file, as this operation can take a long time if the archive is large.
- The bug was fixed: 7-Zip File Manager didn't propagate Zone.Identifier stream
for extacted files from nested archives (if there is open archive inside another open archive).
for extracted files from nested archives (if there is open archive inside another open archive).
- Some bugs were fixed.
@ -76,7 +87,7 @@ HISTORY of the 7-Zip source code
-------------------------
- New switch -myv={MMNN} to set decoder compatibility version for 7z archive creating.
{MMNN} is 4-digit number that represents the version of 7-Zip without a dot.
If -myv={MMNN} switch is specified, 7-Zip will only use compression methods that can
If -myv={MMNN} switch is specified, 7-Zip will only use compression methods that can
be decoded by the specified version {MMNN} of 7-Zip and newer versions.
If -myv={MMNN} switch is not specified, -myv=2300 is used, and 7-Zip will only
use compression methods that can be decoded by 7-Zip 23.00 and newer versions.
@ -127,15 +138,15 @@ HISTORY of the 7-Zip source code
And some warning types are disabled in 2 files:
- C/Compiler.h for C/C++ code warnings.
- CPP/Common/Common.h for C++ code warnings.
- Linux/macOS versions of 7-Zip: IUnknown interface in new code doesn't use
- Linux/macOS versions of 7-Zip: IUnknown interface in new code doesn't use
virtual destructor that was used in previous 7-Zip and p7zip:
// virtual ~IUnknown() {}
So 7-Zip's dynamically linked shared libraries (codecs) are not compatible
So 7-Zip's dynamically linked shared libraries (codecs) are not compatible
between new 7-Zip for Linux/macOS and old 7-Zip (and p7zip).
- Some optimizations in filters code: BCJ, BCJ2, Swap* and opthers.
- If 7-Zip uses BCJ2 filter for big datasets compressing, it can use additional temp
files in system's TEMP folder. 7-Zip uses temp file for additional compressed
data stream, if size of such compressed stream is larger than predefined limit:
- If 7-Zip uses BCJ2 filter for big datasets compressing, it can use additional temp
files in system's TEMP folder. 7-Zip uses temp file for additional compressed
data stream, if size of such compressed stream is larger than predefined limit:
16 MiB in 32-bit version, 4 GiB in 64-bit version.
- Some bugs were fixed.
@ -157,7 +168,7 @@ HISTORY of the 7-Zip source code
21.06 2021-11-24
-------------------------
- Bug in LZMA encoder in file LzmaEnc.c was fixed:
LzmaEnc_MemEncode(), LzmaEncode() and LzmaCompress() could work incorrectly,
LzmaEnc_MemEncode(), LzmaEncode() and LzmaCompress() could work incorrectly,
if size value for output buffer is smaller than size required for all compressed data.
LzmaEnc_Encode() could work incorrectly,
if callback ISeqOutStream::Write() doesn't write all compressed data.
@ -171,8 +182,8 @@ HISTORY of the 7-Zip source code
-------------------------
- 7-Zip now reduces the number of working CPU threads for compression,
if RAM size is not enough for compression with big LZMA2 dictionary.
- 7-Zip now can create and check "file.sha256" and "file.sha1" text files
that contain the list of file names and SHA-1 / SHA-256 checksums in format
- 7-Zip now can create and check "file.sha256" and "file.sha1" text files
that contain the list of file names and SHA-1 / SHA-256 checksums in format
compatible with sha1sum/sha256sum programs.
@ -187,7 +198,7 @@ HISTORY of the 7-Zip source code
- 7-Zip now writes additional field for filename in UTF-8 encoding to zip archives.
It allows to extract correct file name from zip archives on different systems.
- The command line version of 7-Zip for macOS was released.
- The speed for LZMA and LZMA2 decompression in arm64 versions for macOS and Linux
- The speed for LZMA and LZMA2 decompression in arm64 versions for macOS and Linux
was increased by 20%-60%.
- Some changes and improvements in ZIP, TAR and NSIS code.
@ -195,7 +206,7 @@ HISTORY of the 7-Zip source code
21.01 alpha 2021-03-09
-------------------------
- The command line version of 7-Zip for Linux was released.
- The improvements for speed of ARM64 version using hardware CPU instructions
- The improvements for speed of ARM64 version using hardware CPU instructions
for AES, CRC-32, SHA-1 and SHA-256.
- The bug in versions 18.02 - 21.00 was fixed:
7-Zip could not correctly extract some ZIP archives created with xz compression method.
@ -205,30 +216,30 @@ HISTORY of the 7-Zip source code
20.02 alpha 2020-08-08
-------------------------
- The default number of LZMA2 chunks per solid block in 7z archive was increased to 64.
It allows to increase the compression speed for big 7z archives, if there is a big number
It allows to increase the compression speed for big 7z archives, if there is a big number
of CPU cores and threads.
- The speed of PPMd compressing/decompressing was increased for 7z/ZIP/RAR archives.
- The new -ssp switch. If the switch -ssp is specified, 7-Zip doesn't allow the system
to modify "Last Access Time" property of source files for archiving and hashing operations.
- The new -ssp switch. If the switch -ssp is specified, 7-Zip doesn't allow the system
to modify "Last Access Time" property of source files for archiving and hashing operations.
- Some bugs were fixed.
20.00 alpha 2020-02-06
-------------------------
- 7-Zip now supports new optional match finders for LZMA/LZMA2 compression: bt5 and hc5,
- 7-Zip now supports new optional match finders for LZMA/LZMA2 compression: bt5 and hc5,
that can work faster than bt4 and hc4 match finders for the data with big redundancy.
- The compression ratio was improved for Fast and Fastest compression levels with the
- The compression ratio was improved for Fast and Fastest compression levels with the
following default settings:
- Fastest level (-mx1) : hc5 match finder with 256 KB dictionary.
- Fast level (-mx3) : hc5 match finder with 4 MB dictionary.
- Minor speed optimizations in multithreaded LZMA/LZMA2 compression for Normal/Maximum/Ultra
- Minor speed optimizations in multithreaded LZMA/LZMA2 compression for Normal/Maximum/Ultra
compression levels.
- bzip2 decoding code was updated to support bzip2 archives, created by lbzip2 program.
19.02 2019-09-05
-------------------------
- Support for SHA-1/SHA-256 optimized code in
- Support for SHA-1/SHA-256 optimized code in
Sha1Opt.c, Sha256Opt.c, Sha256Opt.asm, Sha1Opt.asm.
@ -249,7 +260,7 @@ HISTORY of the 7-Zip source code
There was memory leak in multithreading xz decoder - XzDecMt_Decode(),
if xz stream contains only one block.
- 7-Zip 18.02-18.05 used only one CPU thread for bz2 archive creation.
- The changes for MSVS compiler makefiles:
- The changes for MSVS compiler makefiles:
- the makefiles now use "PLATFORM" macroname with values (x64, x86, arm64)
instead of "CPU" macroname with values (AMD64, ARM64).
- the makefiles by default now use static version of the run-time library.
@ -257,17 +268,17 @@ HISTORY of the 7-Zip source code
18.05 2018-04-30
-------------------------
- The speed for LZMA/LZMA2 compressing was increased
by 8% for fastest/fast compression levels and
- The speed for LZMA/LZMA2 compressing was increased
by 8% for fastest/fast compression levels and
by 3% for normal/maximum compression levels.
- Previous versions of 7-Zip could work incorrectly in "Large memory pages" mode in
Windows 10 because of some BUG with "Large Pages" in Windows 10.
Windows 10 because of some BUG with "Large Pages" in Windows 10.
Now 7-Zip doesn't use "Large Pages" on Windows 10 up to revision 1709 (16299).
18.03 beta 2018-03-04
-------------------------
- Asm\x86\LzmaDecOpt.asm: new optimized LZMA decoder written in asm
- Asm\x86\LzmaDecOpt.asm: new optimized LZMA decoder written in asm
for x64 with about 30% higher speed than main version of LZMA decoder written in C.
- The speed for single-thread LZMA/LZMA2 decoder written in C was increased by 3%.
- 7-Zip now can use multi-threading for 7z/LZMA2 decoding,
@ -278,7 +289,7 @@ HISTORY of the 7-Zip source code
17.00 beta 2017-04-29
-------------------------
- NewHandler.h / NewHandler.cpp:
- NewHandler.h / NewHandler.cpp:
now it redefines operator new() only for old MSVC compilers (_MSC_VER < 1900).
- C/7zTypes.h : the names of variables in interface structures were changed (vt).
- Some bugs were fixed. 7-Zip could crash in some cases.
@ -288,53 +299,53 @@ HISTORY of the 7-Zip source code
16.02 2016-05-21
-------------------------
- The BUG in 16.00 - 16.01 was fixed:
Split Handler (SplitHandler.cpp) returned incorrect
Split Handler (SplitHandler.cpp) returned incorrect
total size value (kpidSize) for split archives.
16.01 2016-05-19
-------------------------
-------------------------
- Some bugs were fixed,
- Some internal changes to reduce the number of compiler warnings.
16.00 2016-05-10
-------------------------
-------------------------
- 7-Zip now can extract multivolume ZIP archives (z01, z02, ... , zip).
- Some bugs were fixed,
15.12 2015-11-19
-------------------------
-------------------------
- The BUG in C version of 7z decoder was fixed:
7zDec.c : SzDecodeLzma2()
7z decoder could mistakenly report about decoding error for some 7z archives
that use LZMA2 compression method.
The probability to get that mistaken decoding error report was about
one error per 16384 solid blocks for solid blocks larger than 16 KB (compressed size).
The probability to get that mistaken decoding error report was about
one error per 16384 solid blocks for solid blocks larger than 16 KB (compressed size).
- The BUG (in 9.26-15.11) in C version of 7z decoder was fixed:
7zArcIn.c : SzReadHeader2()
7z decoder worked incorrectly for 7z archives that contain
empty solid blocks, that can be placed to 7z archive, if some file is
7z decoder worked incorrectly for 7z archives that contain
empty solid blocks, that can be placed to 7z archive, if some file is
unavailable for reading during archive creation.
15.09 beta 2015-10-16
-------------------------
-------------------------
- The BUG in LZMA / LZMA2 encoding code was fixed.
The BUG in LzFind.c::MatchFinder_ReadBlock() function.
If input data size is larger than (4 GiB - dictionary_size),
the following code worked incorrectly:
- LZMA : LzmaEnc_MemEncode(), LzmaEncode() : LZMA encoding functions
for compressing from memory to memory.
- LZMA : LzmaEnc_MemEncode(), LzmaEncode() : LZMA encoding functions
for compressing from memory to memory.
That BUG is not related to LZMA encoder version that works via streams.
- LZMA2 : multi-threaded version of LZMA2 encoder worked incorrectly, if
default value of chunk size (CLzma2EncProps::blockSize) is changed
- LZMA2 : multi-threaded version of LZMA2 encoder worked incorrectly, if
default value of chunk size (CLzma2EncProps::blockSize) is changed
to value larger than (4 GiB - dictionary_size).
9.38 beta 2015-01-03
-------------------------
-------------------------
- The BUG in 9.31-9.37 was fixed:
IArchiveGetRawProps interface was disabled for 7z archives.
- The BUG in 9.26-9.36 was fixed:
@ -342,10 +353,10 @@ HISTORY of the 7-Zip source code
9.36 beta 2014-12-26
-------------------------
-------------------------
- The BUG in command line version was fixed:
7-Zip created temporary archive in current folder during update archive
operation, if -w{Path} switch was not specified.
operation, if -w{Path} switch was not specified.
The fixed 7-Zip creates temporary archive in folder that contains updated archive.
- The BUG in 9.33-9.35 was fixed:
7-Zip silently ignored file reading errors during 7z or gz archive creation,
@ -355,8 +366,8 @@ HISTORY of the 7-Zip source code
9.31 2012-10-31
-------------------------
- InBuffer.h : CInBuffer uses ISequentialInStream *_stream; instead of CMyComPtr<ISequentialInStream>
OutBuffer.h: COutBuffer uses ISequentialOutStream *_stream; instead of CMyComPtr<ISequentialOutStream>
- InBuffer.h : CInBuffer uses ISequentialInStream *_stream; instead of CMyComPtr<ISequentialInStream>
OutBuffer.h: COutBuffer uses ISequentialOutStream *_stream; instead of CMyComPtr<ISequentialOutStream>
9.26 2011-04-11
@ -366,13 +377,13 @@ HISTORY of the 7-Zip source code
9.21 2011-04-11
-------------------------
-------------------------
- New class FString for file names at file systems.
- Speed optimization in CRC code for big-endian CPUs.
9.18 2010-11-02
-------------------------
-------------------------
- New small SFX module for installers (C/Util/SfxSetup).
@ -409,7 +420,7 @@ HISTORY of the 7-Zip source code
4.61 2008-11-23
-------------------------
- Bug in ver. 4.58+ was fixed:
7-Zip didn't use any -m* switch after -mtc, -mcl or -mcu for .zip archives.
7-Zip didn't use any -m* switch after -mtc, -mcl or -mcu for .zip archives.
- Bug in .CAB code was fixed. 7-Zip didn't show some empty files,
if .CAB archive contains more than one empty file.
@ -417,13 +428,13 @@ HISTORY of the 7-Zip source code
4.59 2008-07-27
-------------------------
- Bug was fixed:
LZMA Encoder in fast compression mode could access memory outside of
LZMA Encoder in fast compression mode could access memory outside of
allocated range in some rare cases.
4.59 alpha 2008-05-30
-------------------------
- BUGS was fixed:
- BUGS was fixed:
7zOut.cpp: 7-Zip incorrectly wrote size of property records in some cases.
7zIn.cpp: 7-Zip incorrectly work with archive, containg archive properties.
@ -440,13 +451,13 @@ HISTORY of the 7-Zip source code
1) Default mode: 7-Zip uses UTF-8, if the local code page doesn't contain required symbols.
2) -mcu switch: 7-Zip uses UTF-8, if there are non-ASCII symbols.
3) -mcl switch: 7-Zip uses local code page.
- Now it's possible to use -mSW- and -mSW+ switches instead of -mSW=off and -mSW=on
- Now it's possible to use -mSW- and -mSW+ switches instead of -mSW=off and -mSW=on
4.58 alpha 7 2008-04-08
-------------------------
- BUG was fixed: BZip2Encoder and BZip2Decoder used CEvent objects without
creating, when BZip2 code was called with one thread (with -mmt1 switch or with
- BUG was fixed: BZip2Encoder and BZip2Decoder used CEvent objects without
creating, when BZip2 code was called with one thread (with -mmt1 switch or with
default switches on single thread CPU).
- .lzma support.
- RPM and NSIS support was improved.
@ -472,7 +483,7 @@ HISTORY of the 7-Zip source code
- 7-Zip now has 128 MB dictionary limit for 32-bit version:
It's for speed optimization: kNumLogBits = 9 + sizeof(size_t) / 2;
- TAR: 'D' link flag support.
- 7-Zip now can unpack multivolume RAR archives created with
- 7-Zip now can unpack multivolume RAR archives created with
"old style volume names" scheme (-vn switch) and names *.001, *.002, ...
- Fixed bugs:
- 7-Zip FM could not copy / move files to root network folders like \\COMPNAME\FOLDERNAME\
@ -484,7 +495,7 @@ HISTORY of the 7-Zip source code
7-zip tries to delete all extra fileds (except for WzAES).
And that code could hang.
- 7-Zip GUI didn't suggest BZip2 dictionary size used in previous run.
- If creation time stamp was included in .RAR archive, 7-zip used creation time stamp
- If creation time stamp was included in .RAR archive, 7-zip used creation time stamp
as modification time stamp.
4.58 alpha 2 2007-12-31
@ -531,7 +542,7 @@ HISTORY of the 7-Zip source code
4.45 beta 2007-04-16
-------------------------
- 7-Zip now uses C version of CRC, so you must call CrcGenerateTable at
- 7-Zip now uses C version of CRC, so you must call CrcGenerateTable at
stratup code, or you must add CPP/Common/CRC.cpp to your project.
- Method ID in .7z now is 63-bit integer (UInt64).
- Open error messages
@ -606,7 +617,7 @@ HISTORY of the 7-Zip source code
4.07 beta 2004-10-03
-------------------------
- some interfaces were changed slightly to support
- some interfaces were changed slightly to support
-stdin -stdout mode.
- FilterCoder for simple filters
- Wildcard censor class was changed.
@ -682,7 +693,7 @@ HISTORY of the 7-Zip source code
2.30 Beta 24 2002-11-01
-------------------------
SDK/Windows/Synchronization.h
SDK/Windows/Synchronization.h
SDK/Windows/Synchronization.cpp
- some changes.
@ -711,9 +722,9 @@ HISTORY of the 7-Zip source code
2.30 Beta 20 2002-07-01
-------------------------
- SDK/Stream/WindowOut.h
- SDK/Stream/WindowOut.h
now it uses only required memory (dictionary size).
- Project/Archiver/Resource
- Project/Archiver/Resource
contains common resurces
@ -727,8 +738,8 @@ HISTORY of the 7-Zip source code
- SDK/Archive/Cab/MSZipDecoder.cpp
SDK/Archive/Cab/LZXDecoder.cpp:
bug with corrupted archives was fixed
- Project/Compress/LZ/MatchFinder/BinTree/BinTree.h
- Project/Compress/LZ/MatchFinder/BinTree/BinTreeMain.h
- Project/Compress/LZ/MatchFinder/BinTree/BinTree.h
- Project/Compress/LZ/MatchFinder/BinTree/BinTreeMain.h
some speed optimization (using prefetching)
@ -743,7 +754,7 @@ HISTORY of the 7-Zip source code
Bug was fixed: LZMA could not extract more than 4 GB.
- RPM and CPIO formats.
- Project/Compress/LZ/LZMA/Encoder.*
Project/Archiver/Format/7z/OutHandler.cpp
Project/Archiver/Format/7z/OutHandler.cpp
New fast compression mode for LZMA: -m0a=0.
- New match finders for LZMA: bt4b, hc3, hc4.
@ -752,23 +763,23 @@ HISTORY of the 7-Zip source code
-------------------------
- Compression ratio in LZMA was slightly improved:
Project/Compress/LZ/LZMA/Encoder.*
Project/Archiver/Format/7z/OutHandler.cpp
Project/Archiver/Format/7z/OutHandler.cpp
2.30 Beta 14 2002-02-10
-------------------------
- Supporting multithreading for LZMA:
Project/Compress/LZ/MatchFinder/MT
Project/Compress/LZ/MatchFinder/MT
- Common/String.h:
CStringBase::Replace function was fixed.
2.30 Beta 13 2002-01-27
-------------------------
- Compress/LZ/MatchFinder/BinTree3.h:
- Compress/LZ/MatchFinder/BinTree3.h:
method
- Compress/LZ/MatchFinder/BinTreemain.h:
- one VirtualAlloc array was splitted to
- Compress/LZ/MatchFinder/BinTreemain.h:
- one VirtualAlloc array was splitted to
the for 3 arrays.
- Hash-functions were changed.
@ -776,23 +787,23 @@ HISTORY of the 7-Zip source code
2.30 Beta 12 2002-01-16
-------------------------
- Compress/LZ/MatchFinder/BinTreemain.h:
Compress/LZ/MatchFinder/Patricia.h:
Compress/PPM/PPMd/SubAlloc.h:
- Compress/LZ/MatchFinder/BinTreemain.h:
Compress/LZ/MatchFinder/Patricia.h:
Compress/PPM/PPMd/SubAlloc.h:
Beta 11 bugs were fixed:
- VirtualFree was used incorrectly
- checking WIN32 instead _WINDOWS.
Compress/LZ/MatchFinder/Patricia.h:
Compress/LZ/MatchFinder/Patricia.h:
Beta 11 bug with deleting m_Hash2Descendants was fixed.
2.30 Beta 11 2002-01-15
-------------------------
- Compress/LZ/MatchFinder/BinTreemain.h:
Compress/LZ/MatchFinder/Patricia.h:
Compress/PPM/PPMd/SubAlloc.h:
- Compress/LZ/MatchFinder/BinTreemain.h:
Compress/LZ/MatchFinder/Patricia.h:
Compress/PPM/PPMd/SubAlloc.h:
using VirtualAlloc for memory allocating
- Exlorer/ContextMenu.cpp:
- Exlorer/ContextMenu.cpp:
Testing supporting.
CreateProcess instead WinExec
- Format/Common/IArchiveHandler.h:
@ -808,9 +819,9 @@ HISTORY of the 7-Zip source code
2.30 Beta 10 2002-01-11
-------------------------
- Exlorer/ContextMenu.cpp: bug with context menu on
- Exlorer/ContextMenu.cpp: bug with context menu on
Windows NT4 in Unicode version was fixed.
- Format/7z/UpdateArchiveEngine.cpp: bug was fixed -
- Format/7z/UpdateArchiveEngine.cpp: bug was fixed -
Updating in Beta 8 and 9 didn't work.
- Exlorer/CCompressDialog.cpp: history growing bug was fixed.
@ -823,4 +834,3 @@ HISTORY of the 7-Zip source code
- SDK/Archive/Zip/InEngine.cpp: bug was fixed.
- SDK/Windows/FileDir.cpp: function CreateComplexDirectory
was changed.