diff options
| author | Igor Pavlov <87184205+ip7z@users.noreply.github.com> | 2026-02-12 00:00:00 +0000 |
|---|---|---|
| committer | Igor Pavlov <87184205+ip7z@users.noreply.github.com> | 2026-02-12 17:38:49 +0500 |
| commit | 839151eaaad24771892afaae6bac690e31e58384 (patch) | |
| tree | e292449d621f7a1d503b975984a2aca240dd2d8f | |
| parent | 5e96a8279489832924056b1fa82f29d5837c9469 (diff) | |
| download | 7zip-26.00.tar.gz 7zip-26.00.tar.bz2 7zip-26.00.zip | |
56 files changed, 1740 insertions, 960 deletions
diff --git a/C/7zVersion.h b/C/7zVersion.h index b6142e9..770370a 100644 --- a/C/7zVersion.h +++ b/C/7zVersion.h | |||
| @@ -1,7 +1,7 @@ | |||
| 1 | #define MY_VER_MAJOR 25 | 1 | #define MY_VER_MAJOR 26 |
| 2 | #define MY_VER_MINOR 1 | 2 | #define MY_VER_MINOR 0 |
| 3 | #define MY_VER_BUILD 0 | 3 | #define MY_VER_BUILD 0 |
| 4 | #define MY_VERSION_NUMBERS "25.01" | 4 | #define MY_VERSION_NUMBERS "26.00" |
| 5 | #define MY_VERSION MY_VERSION_NUMBERS | 5 | #define MY_VERSION MY_VERSION_NUMBERS |
| 6 | 6 | ||
| 7 | #ifdef MY_CPU_NAME | 7 | #ifdef MY_CPU_NAME |
| @@ -10,12 +10,12 @@ | |||
| 10 | #define MY_VERSION_CPU MY_VERSION | 10 | #define MY_VERSION_CPU MY_VERSION |
| 11 | #endif | 11 | #endif |
| 12 | 12 | ||
| 13 | #define MY_DATE "2025-08-03" | 13 | #define MY_DATE "2026-02-12" |
| 14 | #undef MY_COPYRIGHT | 14 | #undef MY_COPYRIGHT |
| 15 | #undef MY_VERSION_COPYRIGHT_DATE | 15 | #undef MY_VERSION_COPYRIGHT_DATE |
| 16 | #define MY_AUTHOR_NAME "Igor Pavlov" | 16 | #define MY_AUTHOR_NAME "Igor Pavlov" |
| 17 | #define MY_COPYRIGHT_PD "Igor Pavlov : Public domain" | 17 | #define MY_COPYRIGHT_PD "Igor Pavlov : Public domain" |
| 18 | #define MY_COPYRIGHT_CR "Copyright (c) 1999-2025 Igor Pavlov" | 18 | #define MY_COPYRIGHT_CR "Copyright (c) 1999-2026 Igor Pavlov" |
| 19 | 19 | ||
| 20 | #ifdef USE_COPYRIGHT_CR | 20 | #ifdef USE_COPYRIGHT_CR |
| 21 | #define MY_COPYRIGHT MY_COPYRIGHT_CR | 21 | #define MY_COPYRIGHT MY_COPYRIGHT_CR |
diff --git a/C/7zWindows.h b/C/7zWindows.h index 42c6db8..381159e 100644 --- a/C/7zWindows.h +++ b/C/7zWindows.h | |||
| @@ -1,11 +1,17 @@ | |||
| 1 | /* 7zWindows.h -- StdAfx | 1 | /* 7zWindows.h -- Windows.h and related code |
| 2 | 2023-04-02 : Igor Pavlov : Public domain */ | 2 | Igor Pavlov : Public domain */ |
| 3 | 3 | ||
| 4 | #ifndef ZIP7_INC_7Z_WINDOWS_H | 4 | #ifndef ZIP7_INC_7Z_WINDOWS_H |
| 5 | #define ZIP7_INC_7Z_WINDOWS_H | 5 | #define ZIP7_INC_7Z_WINDOWS_H |
| 6 | 6 | ||
| 7 | #ifdef _WIN32 | 7 | #ifdef _WIN32 |
| 8 | 8 | ||
| 9 | #if defined(_MSC_VER) && _MSC_VER >= 1950 && !defined(__clang__) // VS2026 | ||
| 10 | // <Windows.h> and some another windows files need that option | ||
| 11 | // 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 | ||
| 12 | #pragma warning(disable : 4865) | ||
| 13 | #endif | ||
| 14 | |||
| 9 | #if defined(__clang__) | 15 | #if defined(__clang__) |
| 10 | # pragma clang diagnostic push | 16 | # pragma clang diagnostic push |
| 11 | #endif | 17 | #endif |
diff --git a/C/7zip_gcc_c.mak b/C/7zip_gcc_c.mak index 195d23d..006cfe0 100644 --- a/C/7zip_gcc_c.mak +++ b/C/7zip_gcc_c.mak | |||
| @@ -106,7 +106,7 @@ DEL_OBJ_EXE = -$(RM) $(O)\*.o $(O)\$(PROG).exe $(O)\$(PROG).dll | |||
| 106 | endif | 106 | endif |
| 107 | 107 | ||
| 108 | 108 | ||
| 109 | LIB2 = -lOle32 -loleaut32 -luuid -ladvapi32 -lUser32 -lShell32 | 109 | LIB2 = -lole32 -loleaut32 -luuid -ladvapi32 -luser32 -lshell32 |
| 110 | 110 | ||
| 111 | CFLAGS_EXTRA = -DUNICODE -D_UNICODE | 111 | CFLAGS_EXTRA = -DUNICODE -D_UNICODE |
| 112 | # -Wno-delete-non-virtual-dtor | 112 | # -Wno-delete-non-virtual-dtor |
diff --git a/C/CpuArch.c b/C/CpuArch.c index 6e02551..342280d 100644 --- a/C/CpuArch.c +++ b/C/CpuArch.c | |||
| @@ -859,7 +859,7 @@ BoolInt CPU_IsSupported_AES (void) { return APPLE_CRYPTO_SUPPORT_VAL; } | |||
| 859 | 859 | ||
| 860 | #if defined(__GLIBC__) && (__GLIBC__ * 100 + __GLIBC_MINOR__ >= 216) | 860 | #if defined(__GLIBC__) && (__GLIBC__ * 100 + __GLIBC_MINOR__ >= 216) |
| 861 | #define Z7_GETAUXV_AVAILABLE | 861 | #define Z7_GETAUXV_AVAILABLE |
| 862 | #else | 862 | #elif !defined(__QNXNTO__) |
| 863 | // #pragma message("=== is not NEW GLIBC === ") | 863 | // #pragma message("=== is not NEW GLIBC === ") |
| 864 | #if defined __has_include | 864 | #if defined __has_include |
| 865 | #if __has_include (<sys/auxv.h>) | 865 | #if __has_include (<sys/auxv.h>) |
| @@ -877,7 +877,7 @@ BoolInt CPU_IsSupported_AES (void) { return APPLE_CRYPTO_SUPPORT_VAL; } | |||
| 877 | 877 | ||
| 878 | #ifdef USE_HWCAP | 878 | #ifdef USE_HWCAP |
| 879 | 879 | ||
| 880 | #if defined(__FreeBSD__) | 880 | #if defined(__FreeBSD__) || defined(__OpenBSD__) |
| 881 | static unsigned long MY_getauxval(int aux) | 881 | static unsigned long MY_getauxval(int aux) |
| 882 | { | 882 | { |
| 883 | unsigned long val; | 883 | unsigned long val; |
diff --git a/C/CpuArch.h b/C/CpuArch.h index 1690a5b..c682720 100644 --- a/C/CpuArch.h +++ b/C/CpuArch.h | |||
| @@ -31,7 +31,12 @@ MY_CPU_64BIT means that processor can work with 64-bit registers. | |||
| 31 | #define MY_CPU_NAME "x32" | 31 | #define MY_CPU_NAME "x32" |
| 32 | #define MY_CPU_SIZEOF_POINTER 4 | 32 | #define MY_CPU_SIZEOF_POINTER 4 |
| 33 | #else | 33 | #else |
| 34 | #define MY_CPU_NAME "x64" | 34 | #if defined(__APX_EGPR__) || defined(__EGPR__) |
| 35 | #define MY_CPU_NAME "x64-apx" | ||
| 36 | #define MY_CPU_AMD64_APX | ||
| 37 | #else | ||
| 38 | #define MY_CPU_NAME "x64" | ||
| 39 | #endif | ||
| 35 | #define MY_CPU_SIZEOF_POINTER 8 | 40 | #define MY_CPU_SIZEOF_POINTER 8 |
| 36 | #endif | 41 | #endif |
| 37 | #define MY_CPU_64BIT | 42 | #define MY_CPU_64BIT |
| @@ -596,8 +601,20 @@ problem-4 : performace: | |||
| 596 | #define SetBe32a(p, v) { *(UInt32 *)(void *)(p) = (v); } | 601 | #define SetBe32a(p, v) { *(UInt32 *)(void *)(p) = (v); } |
| 597 | #define SetBe16a(p, v) { *(UInt16 *)(void *)(p) = (v); } | 602 | #define SetBe16a(p, v) { *(UInt16 *)(void *)(p) = (v); } |
| 598 | 603 | ||
| 604 | // gcc and clang for powerpc can transform load byte access to load reverse word access. | ||
| 605 | // sp we can use byte access instead of word access. Z7_BSWAP64 cab be slow | ||
| 606 | #if 1 && defined(Z7_CPU_FAST_BSWAP_SUPPORTED) && defined(MY_CPU_64BIT) | ||
| 607 | #define GetUi64a(p) Z7_BSWAP64 (*(const UInt64 *)(const void *)(p)) | ||
| 608 | #else | ||
| 599 | #define GetUi64a(p) GetUi64(p) | 609 | #define GetUi64a(p) GetUi64(p) |
| 610 | #endif | ||
| 611 | |||
| 612 | #if 1 && defined(Z7_CPU_FAST_BSWAP_SUPPORTED) | ||
| 613 | #define GetUi32a(p) Z7_BSWAP32 (*(const UInt32 *)(const void *)(p)) | ||
| 614 | #else | ||
| 600 | #define GetUi32a(p) GetUi32(p) | 615 | #define GetUi32a(p) GetUi32(p) |
| 616 | #endif | ||
| 617 | |||
| 601 | #define GetUi16a(p) GetUi16(p) | 618 | #define GetUi16a(p) GetUi16(p) |
| 602 | #define SetUi32a(p, v) SetUi32(p, v) | 619 | #define SetUi32a(p, v) SetUi32(p, v) |
| 603 | #define SetUi16a(p, v) SetUi16(p, v) | 620 | #define SetUi16a(p, v) SetUi16(p, v) |
diff --git a/C/HuffEnc.c b/C/HuffEnc.c index cbf8c22..297b41a 100644 --- a/C/HuffEnc.c +++ b/C/HuffEnc.c | |||
| @@ -13,7 +13,7 @@ Igor Pavlov : Public domain */ | |||
| 13 | #define NUM_BITS 10 | 13 | #define NUM_BITS 10 |
| 14 | #define MASK ((1u << NUM_BITS) - 1) | 14 | #define MASK ((1u << NUM_BITS) - 1) |
| 15 | #define FREQ_MASK (~(UInt32)MASK) | 15 | #define FREQ_MASK (~(UInt32)MASK) |
| 16 | #define NUM_COUNTERS (48 * 2) | 16 | #define NUM_COUNTERS (104 * 2) // (80 * 2) or (128 * 2) : ((prime_number + 1) * 2) for smaller code. |
| 17 | 17 | ||
| 18 | #if 1 && (defined(MY_CPU_LE) || defined(MY_CPU_BE)) | 18 | #if 1 && (defined(MY_CPU_LE) || defined(MY_CPU_BE)) |
| 19 | #if defined(MY_CPU_LE) | 19 | #if defined(MY_CPU_LE) |
| @@ -95,9 +95,10 @@ void Huffman_Generate(const UInt32 *freqs, UInt32 *p, Byte *lens, unsigned numSy | |||
| 95 | counters[1] = 0; | 95 | counters[1] = 0; |
| 96 | for (i = 2; i != NUM_COUNTERS; i += 2) | 96 | for (i = 2; i != NUM_COUNTERS; i += 2) |
| 97 | { | 97 | { |
| 98 | unsigned c; | 98 | const unsigned c0 = (counters )[i]; |
| 99 | c = (counters )[i]; (counters )[i] = num; num += c; | 99 | const unsigned c1 = (counters + 1)[i]; |
| 100 | c = (counters + 1)[i]; (counters + 1)[i] = num; num += c; | 100 | (counters )[i] = num; num += c0; |
| 101 | (counters + 1)[i] = num; num += c1; | ||
| 101 | } | 102 | } |
| 102 | counters[0] = num; // we want to write (freq==0) symbols to the end of (p) array | 103 | counters[0] = num; // we want to write (freq==0) symbols to the end of (p) array |
| 103 | { | 104 | { |
diff --git a/C/HuffEnc.h b/C/HuffEnc.h index 2217f55..45567d0 100644 --- a/C/HuffEnc.h +++ b/C/HuffEnc.h | |||
| @@ -16,7 +16,7 @@ Conditions: | |||
| 16 | 1 <= maxLen <= 16 = Z7_HUFFMAN_LEN_MAX | 16 | 1 <= maxLen <= 16 = Z7_HUFFMAN_LEN_MAX |
| 17 | Num_Items(p) >= HUFFMAN_TEMP_SIZE(num) | 17 | Num_Items(p) >= HUFFMAN_TEMP_SIZE(num) |
| 18 | */ | 18 | */ |
| 19 | void Huffman_Generate(const UInt32 *freqs, UInt32 *p, Byte *lens, UInt32 num, UInt32 maxLen); | 19 | void Huffman_Generate(const UInt32 *freqs, UInt32 *p, Byte *lens, unsigned num, unsigned maxLen); |
| 20 | 20 | ||
| 21 | EXTERN_C_END | 21 | EXTERN_C_END |
| 22 | 22 | ||
| @@ -1,6 +1,6 @@ | |||
| 1 | /* Xxh64.c -- XXH64 hash calculation | 1 | /* Xxh64.c -- XXH64 hash calculation |
| 2 | original code: Copyright (c) Yann Collet. | 2 | original code: Copyright (c) Yann Collet. |
| 3 | 2023-08-18 : modified by Igor Pavlov. | 3 | modified by Igor Pavlov. |
| 4 | This source code is licensed under BSD 2-Clause License. | 4 | This source code is licensed under BSD 2-Clause License. |
| 5 | */ | 5 | */ |
| 6 | 6 | ||
| @@ -27,6 +27,14 @@ void Xxh64State_Init(CXxh64State *p) | |||
| 27 | 27 | ||
| 28 | #if !defined(MY_CPU_64BIT) && defined(MY_CPU_X86) && defined(_MSC_VER) | 28 | #if !defined(MY_CPU_64BIT) && defined(MY_CPU_X86) && defined(_MSC_VER) |
| 29 | #define Z7_XXH64_USE_ASM | 29 | #define Z7_XXH64_USE_ASM |
| 30 | #elif !defined(MY_CPU_LE_UNALIGN_64) // && defined (MY_CPU_LE) | ||
| 31 | #define Z7_XXH64_USE_ALIGNED | ||
| 32 | #endif | ||
| 33 | |||
| 34 | #ifdef Z7_XXH64_USE_ALIGNED | ||
| 35 | #define Xxh64State_UpdateBlocks_Unaligned_Select Xxh64State_UpdateBlocks_Unaligned | ||
| 36 | #else | ||
| 37 | #define Xxh64State_UpdateBlocks_Unaligned_Select Xxh64State_UpdateBlocks | ||
| 30 | #endif | 38 | #endif |
| 31 | 39 | ||
| 32 | #if !defined(MY_CPU_64BIT) && defined(MY_CPU_X86) \ | 40 | #if !defined(MY_CPU_64BIT) && defined(MY_CPU_X86) \ |
| @@ -188,32 +196,76 @@ Xxh64State_UpdateBlocks(CXxh64State *p, const void *data, const void *end) | |||
| 188 | 196 | ||
| 189 | #else | 197 | #else |
| 190 | 198 | ||
| 199 | #ifdef Z7_XXH64_USE_ALIGNED | ||
| 200 | static | ||
| 201 | #endif | ||
| 191 | void | 202 | void |
| 192 | Z7_NO_INLINE | 203 | Z7_NO_INLINE |
| 193 | Z7_FASTCALL | 204 | Z7_FASTCALL |
| 194 | Xxh64State_UpdateBlocks(CXxh64State *p, const void *_data, const void *end) | 205 | Xxh64State_UpdateBlocks_Unaligned_Select(CXxh64State *p, const void *_data, const void *end) |
| 195 | { | 206 | { |
| 196 | const Byte *data = (const Byte *)_data; | 207 | const Byte *data = (const Byte *)_data; |
| 197 | UInt64 v[4]; | 208 | UInt64 v0, v1, v2, v3; |
| 198 | v[0] = p->v[0]; | 209 | v0 = p->v[0]; |
| 199 | v[1] = p->v[1]; | 210 | v1 = p->v[1]; |
| 200 | v[2] = p->v[2]; | 211 | v2 = p->v[2]; |
| 201 | v[3] = p->v[3]; | 212 | v3 = p->v[3]; |
| 202 | do | 213 | do |
| 203 | { | 214 | { |
| 204 | v[0] = Xxh64_Round(v[0], GetUi64(data)); data += 8; | 215 | v0 = Xxh64_Round(v0, GetUi64(data)); data += 8; |
| 205 | v[1] = Xxh64_Round(v[1], GetUi64(data)); data += 8; | 216 | v1 = Xxh64_Round(v1, GetUi64(data)); data += 8; |
| 206 | v[2] = Xxh64_Round(v[2], GetUi64(data)); data += 8; | 217 | v2 = Xxh64_Round(v2, GetUi64(data)); data += 8; |
| 207 | v[3] = Xxh64_Round(v[3], GetUi64(data)); data += 8; | 218 | v3 = Xxh64_Round(v3, GetUi64(data)); data += 8; |
| 208 | } | 219 | } |
| 209 | while (data != end); | 220 | while (data != end); |
| 210 | p->v[0] = v[0]; | 221 | p->v[0] = v0; |
| 211 | p->v[1] = v[1]; | 222 | p->v[1] = v1; |
| 212 | p->v[2] = v[2]; | 223 | p->v[2] = v2; |
| 213 | p->v[3] = v[3]; | 224 | p->v[3] = v3; |
| 214 | } | 225 | } |
| 215 | 226 | ||
| 216 | #endif | 227 | |
| 228 | #ifdef Z7_XXH64_USE_ALIGNED | ||
| 229 | |||
| 230 | static | ||
| 231 | void | ||
| 232 | Z7_NO_INLINE | ||
| 233 | Z7_FASTCALL | ||
| 234 | Xxh64State_UpdateBlocks_Aligned(CXxh64State *p, const void *_data, const void *end) | ||
| 235 | { | ||
| 236 | const Byte *data = (const Byte *)_data; | ||
| 237 | UInt64 v0, v1, v2, v3; | ||
| 238 | v0 = p->v[0]; | ||
| 239 | v1 = p->v[1]; | ||
| 240 | v2 = p->v[2]; | ||
| 241 | v3 = p->v[3]; | ||
| 242 | do | ||
| 243 | { | ||
| 244 | v0 = Xxh64_Round(v0, GetUi64a(data)); data += 8; | ||
| 245 | v1 = Xxh64_Round(v1, GetUi64a(data)); data += 8; | ||
| 246 | v2 = Xxh64_Round(v2, GetUi64a(data)); data += 8; | ||
| 247 | v3 = Xxh64_Round(v3, GetUi64a(data)); data += 8; | ||
| 248 | } | ||
| 249 | while (data != end); | ||
| 250 | p->v[0] = v0; | ||
| 251 | p->v[1] = v1; | ||
| 252 | p->v[2] = v2; | ||
| 253 | p->v[3] = v3; | ||
| 254 | } | ||
| 255 | |||
| 256 | void | ||
| 257 | Z7_NO_INLINE | ||
| 258 | Z7_FASTCALL | ||
| 259 | Xxh64State_UpdateBlocks(CXxh64State *p, const void *data, const void *end) | ||
| 260 | { | ||
| 261 | if (((unsigned)(ptrdiff_t)data & 7) == 0) | ||
| 262 | Xxh64State_UpdateBlocks_Aligned(p, data, end); | ||
| 263 | else | ||
| 264 | Xxh64State_UpdateBlocks_Unaligned(p, data, end); | ||
| 265 | } | ||
| 266 | |||
| 267 | #endif // Z7_XXH64_USE_ALIGNED | ||
| 268 | #endif // Z7_XXH64_USE_ASM | ||
| 217 | 269 | ||
| 218 | UInt64 Xxh64State_Digest(const CXxh64State *p, const void *_data, UInt64 count) | 270 | UInt64 Xxh64State_Digest(const CXxh64State *p, const void *_data, UInt64 count) |
| 219 | { | 271 | { |
| @@ -306,12 +358,22 @@ void Xxh64_Update(CXxh64 *p, const void *_data, size_t size) | |||
| 306 | while (--rem); | 358 | while (--rem); |
| 307 | if (cnt != 32) | 359 | if (cnt != 32) |
| 308 | return; | 360 | return; |
| 309 | Xxh64State_UpdateBlocks(&p->state, p->buf64, &p->buf64[4]); | 361 | #ifdef Z7_XXH64_USE_ALIGNED |
| 362 | Xxh64State_UpdateBlocks_Aligned | ||
| 363 | #else | ||
| 364 | Xxh64State_UpdateBlocks_Unaligned_Select | ||
| 365 | #endif | ||
| 366 | (&p->state, p->buf64, &p->buf64[4]); | ||
| 310 | } | 367 | } |
| 311 | 368 | ||
| 312 | if (size &= ~(size_t)31) | 369 | if (size &= ~(size_t)31) |
| 313 | { | 370 | { |
| 314 | Xxh64State_UpdateBlocks(&p->state, data, data + size); | 371 | #ifdef Z7_XXH64_USE_ALIGNED |
| 372 | if (((unsigned)(ptrdiff_t)data & 7) == 0) | ||
| 373 | Xxh64State_UpdateBlocks_Aligned(&p->state, data, data + size); | ||
| 374 | else | ||
| 375 | #endif | ||
| 376 | Xxh64State_UpdateBlocks_Unaligned_Select(&p->state, data, data + size); | ||
| 315 | data += size; | 377 | data += size; |
| 316 | } | 378 | } |
| 317 | 379 | ||
diff --git a/CPP/7zip/7zip_gcc.mak b/CPP/7zip/7zip_gcc.mak index 12f1ef2..a78c0fa 100644 --- a/CPP/7zip/7zip_gcc.mak +++ b/CPP/7zip/7zip_gcc.mak | |||
| @@ -142,8 +142,8 @@ MY_MKDIR=mkdir | |||
| 142 | DEL_OBJ_EXE = -$(RM) $(O)\*.o $(O)\$(PROG).exe $(O)\$(PROG).dll | 142 | DEL_OBJ_EXE = -$(RM) $(O)\*.o $(O)\$(PROG).exe $(O)\$(PROG).dll |
| 143 | endif | 143 | endif |
| 144 | 144 | ||
| 145 | LIB2_GUI = -lOle32 -lGdi32 -lComctl32 -lComdlg32 -lShell32 $(LIB_HTMLHELP) | 145 | LIB2_GUI = -lole32 -lgdi32 -lcomctl32 -lcomdlg32 -lshell32 $(LIB_HTMLHELP) |
| 146 | LIB2 = -loleaut32 -luuid -ladvapi32 -lUser32 $(LIB2_GUI) | 146 | LIB2 = -loleaut32 -luuid -ladvapi32 -luser32 $(LIB2_GUI) |
| 147 | 147 | ||
| 148 | # v24.00: -DUNICODE and -D_UNICODE are defined in precompilation header files | 148 | # v24.00: -DUNICODE and -D_UNICODE are defined in precompilation header files |
| 149 | # CXXFLAGS_EXTRA = -DUNICODE -D_UNICODE | 149 | # CXXFLAGS_EXTRA = -DUNICODE -D_UNICODE |
diff --git a/CPP/7zip/Archive/7z/7zUpdate.cpp b/CPP/7zip/Archive/7z/7zUpdate.cpp index c8c5d26..6ba04a2 100644 --- a/CPP/7zip/Archive/7z/7zUpdate.cpp +++ b/CPP/7zip/Archive/7z/7zUpdate.cpp | |||
| @@ -721,7 +721,7 @@ static int CompareEmptyItems(const unsigned *p1, const unsigned *p2, void *param | |||
| 721 | return (u1.IsDir && u1.IsAnti) ? -n : n; | 721 | return (u1.IsDir && u1.IsAnti) ? -n : n; |
| 722 | } | 722 | } |
| 723 | 723 | ||
| 724 | static const char *g_Exts = | 724 | static const char * const g_Exts = |
| 725 | " 7z xz lzma ace arc arj bz tbz bz2 tbz2 cab deb gz tgz ha lha lzh lzo lzx pak rar rpm sit zoo" | 725 | " 7z xz lzma ace arc arj bz tbz bz2 tbz2 cab deb gz tgz ha lha lzh lzo lzx pak rar rpm sit zoo" |
| 726 | " zip jar ear war msi" | 726 | " zip jar ear war msi" |
| 727 | " 3gp avi mov mpeg mpg mpe wmv" | 727 | " 3gp avi mov mpeg mpg mpe wmv" |
diff --git a/CPP/7zip/Archive/ComHandler.cpp b/CPP/7zip/Archive/ComHandler.cpp index 144369e..40a5349 100644 --- a/CPP/7zip/Archive/ComHandler.cpp +++ b/CPP/7zip/Archive/ComHandler.cpp | |||
| @@ -2,41 +2,62 @@ | |||
| 2 | 2 | ||
| 3 | #include "StdAfx.h" | 3 | #include "StdAfx.h" |
| 4 | 4 | ||
| 5 | #include "../../../C/Alloc.h" | ||
| 6 | #include "../../../C/CpuArch.h" | 5 | #include "../../../C/CpuArch.h" |
| 7 | 6 | ||
| 8 | #include "../../Common/IntToString.h" | ||
| 9 | #include "../../Common/ComTry.h" | 7 | #include "../../Common/ComTry.h" |
| 10 | #include "../../Common/MyCom.h" | ||
| 11 | #include "../../Common/MyBuffer.h" | ||
| 12 | #include "../../Common/MyString.h" | ||
| 13 | 8 | ||
| 14 | #include "../../Windows/PropVariant.h" | 9 | #include "../../Windows/PropVariant.h" |
| 15 | 10 | ||
| 16 | #include "../Common/LimitedStreams.h" | 11 | #include "../Common/LimitedStreams.h" |
| 17 | #include "../Common/ProgressUtils.h" | 12 | #include "../Common/ProgressUtils.h" |
| 18 | #include "../Common/RegisterArc.h" | 13 | #include "../Common/RegisterArc.h" |
| 14 | #include "../Common/StreamObjects.h" | ||
| 19 | #include "../Common/StreamUtils.h" | 15 | #include "../Common/StreamUtils.h" |
| 20 | 16 | ||
| 21 | #include "../Compress/CopyCoder.h" | 17 | #include "../Compress/CopyCoder.h" |
| 22 | 18 | ||
| 23 | #define Get16(p) GetUi16(p) | 19 | #include "Common/ItemNameUtils.h" |
| 24 | #define Get32(p) GetUi32(p) | 20 | |
| 21 | #define Get16(p) GetUi16a(p) | ||
| 22 | #define Get32(p) GetUi32a(p) | ||
| 23 | |||
| 24 | // we don't expect to get deleted files in real files | ||
| 25 | // define Z7_COMPOUND_SHOW_DELETED for debug | ||
| 26 | // #define Z7_COMPOUND_SHOW_DELETED | ||
| 25 | 27 | ||
| 26 | namespace NArchive { | 28 | namespace NArchive { |
| 27 | namespace NCom { | 29 | namespace NCom { |
| 28 | 30 | ||
| 31 | static const unsigned k_Long_path_level_limit = 256; | ||
| 32 | |||
| 29 | static const Byte kSignature[] = | 33 | static const Byte kSignature[] = |
| 30 | { 0xD0, 0xCF, 0x11, 0xE0, 0xA1, 0xB1, 0x1A, 0xE1 }; | 34 | { 0xd0, 0xcf, 0x11, 0xe0, 0xa1, 0xb1, 0x1a, 0xe1 }; |
| 35 | |||
| 36 | // encoded "[!]MsiPatchSequence" name in "msp" file | ||
| 37 | static const Byte k_Sequence_msp[] = | ||
| 38 | { 0x40, 0x48, 0x96, 0x45, 0x6c, 0x3e, 0xe4, 0x45, | ||
| 39 | 0xe6, 0x42, 0x16, 0x42, 0x37, 0x41, 0x27, 0x41, | ||
| 40 | 0x37, 0x41, 0, 0 }; | ||
| 41 | |||
| 42 | // encoded "MergeModule.CABinet" name in "msm" file | ||
| 43 | static const Byte k_Sequence_msm[] = | ||
| 44 | { 0x16, 0x42, 0xb5, 0x42, 0xa8, 0x3d, 0xf2, 0x41, | ||
| 45 | 0xf8, 0x43, 0xa8, 0x47, 0x8c, 0x3a, 0x0b, 0x43, | ||
| 46 | 0x31, 0x42, 0x37, 0x48, 0, 0 }; | ||
| 47 | |||
| 48 | // static const Byte k_CLSID_AAF_V3[] = { 0x41, 0x41, 0x46, 0x42, 0x0d, 0x00, 0x4f, 0x4d, 0x06, 0x0e, 0x2b, 0x34, 0x01, 0x01, 0x01, 0xff }; | ||
| 49 | // static const Byte k_CLSID_AAF_V4[] = { 0x01, 0x02, 0x01, 0x0d, 0x00, 0x02, 0x00, 0x00, 0x06, 0x0e, 0x2b, 0x34, 0x03, 0x02, 0x01, 0x01 }; | ||
| 31 | 50 | ||
| 32 | enum EType | 51 | enum EArcType |
| 33 | { | 52 | { |
| 34 | k_Type_Common, | 53 | k_Type_Common, |
| 35 | k_Type_Msi, | 54 | k_Type_Msi, |
| 36 | k_Type_Msp, | 55 | k_Type_Msp, |
| 56 | k_Type_Msm, | ||
| 37 | k_Type_Doc, | 57 | k_Type_Doc, |
| 38 | k_Type_Ppt, | 58 | k_Type_Ppt, |
| 39 | k_Type_Xls | 59 | k_Type_Xls, |
| 60 | k_Type_Aaf | ||
| 40 | }; | 61 | }; |
| 41 | 62 | ||
| 42 | static const char * const kExtensions[] = | 63 | static const char * const kExtensions[] = |
| @@ -44,35 +65,63 @@ static const char * const kExtensions[] = | |||
| 44 | "compound" | 65 | "compound" |
| 45 | , "msi" | 66 | , "msi" |
| 46 | , "msp" | 67 | , "msp" |
| 68 | , "msm" | ||
| 47 | , "doc" | 69 | , "doc" |
| 48 | , "ppt" | 70 | , "ppt" |
| 49 | , "xls" | 71 | , "xls" |
| 72 | , "aaf" | ||
| 50 | }; | 73 | }; |
| 51 | 74 | ||
| 52 | namespace NFatID | 75 | namespace NFatID |
| 53 | { | 76 | { |
| 54 | // static const UInt32 kFree = 0xFFFFFFFF; | 77 | static const UInt32 kFree = 0xffffffff; |
| 55 | static const UInt32 kEndOfChain = 0xFFFFFFFE; | 78 | static const UInt32 kEndOfChain = 0xfffffffe; |
| 56 | // static const UInt32 kFatSector = 0xFFFFFFFD; | 79 | static const UInt32 kFatSector = 0xfffffffd; |
| 57 | // static const UInt32 kMatSector = 0xFFFFFFFC; | 80 | static const UInt32 k_DIF_SECT = 0xfffffffc; // double-indirect file allocation table (DIFAT) |
| 58 | static const UInt32 kMaxValue = 0xFFFFFFFA; | 81 | static const UInt32 kMaxValue = 0xfffffffa; |
| 59 | } | 82 | } |
| 60 | 83 | ||
| 61 | namespace NItemType | 84 | namespace NItemType |
| 62 | { | 85 | { |
| 63 | static const Byte kEmpty = 0; | 86 | static const unsigned kEmpty = 0; |
| 64 | static const Byte kStorage = 1; | 87 | static const unsigned kStorage = 1; |
| 65 | // static const Byte kStream = 2; | 88 | static const unsigned kStream = 2; |
| 66 | // static const Byte kLockBytes = 3; | 89 | // static const unsigned kLockBytes = 3; |
| 67 | // static const Byte kProperty = 4; | 90 | // static const unsigned kProperty = 4; |
| 68 | static const Byte kRootStorage = 5; | 91 | static const unsigned kRootStorage = 5; |
| 92 | } | ||
| 93 | |||
| 94 | static const unsigned k_MiniSectorSizeBits = 6; | ||
| 95 | static const UInt32 k_LongStreamMinSize = 1 << 12; | ||
| 96 | |||
| 97 | static const unsigned k_Msi_NumBits = 6; | ||
| 98 | static const unsigned k_Msi_NumChars = 1 << k_Msi_NumBits; | ||
| 99 | static const unsigned k_Msi_CharMask = k_Msi_NumChars - 1; | ||
| 100 | static const unsigned k_Msi_UnicodeRange = k_Msi_NumChars * (k_Msi_NumChars + 1); | ||
| 101 | static const unsigned k_Msi_StartUnicodeChar = 0x3800; | ||
| 102 | static const unsigned k_Msi_SpecUnicodeChar = k_Msi_StartUnicodeChar + k_Msi_UnicodeRange; | ||
| 103 | // (k_Msi_SpecUnicodeChar == 0x4840) is used as special symbol that is used | ||
| 104 | // as first character in some names in dir entries | ||
| 105 | /* | ||
| 106 | static bool IsMsiName(const Byte *p) | ||
| 107 | { | ||
| 108 | unsigned c = Get16(p); | ||
| 109 | c -= k_Msi_StartUnicodeChar; | ||
| 110 | return c <= k_Msi_UnicodeRange; | ||
| 111 | } | ||
| 112 | */ | ||
| 113 | |||
| 114 | Z7_FORCE_INLINE static bool IsLargeStream(UInt64 size) | ||
| 115 | { | ||
| 116 | return size >= k_LongStreamMinSize; | ||
| 69 | } | 117 | } |
| 70 | 118 | ||
| 71 | static const unsigned kNameSizeMax = 64; | 119 | static const unsigned kNameSizeMax = 64; |
| 120 | static const UInt32 k_Item_Level_Unused = (UInt32)0 - 1; | ||
| 72 | 121 | ||
| 73 | struct CItem | 122 | struct CItem |
| 74 | { | 123 | { |
| 75 | Byte Name[kNameSizeMax]; | 124 | Byte Name[kNameSizeMax]; // must be aligned for 2-bytes |
| 76 | // UInt16 NameSize; | 125 | // UInt16 NameSize; |
| 77 | // UInt32 Flags; | 126 | // UInt32 Flags; |
| 78 | FILETIME CTime; | 127 | FILETIME CTime; |
| @@ -82,484 +131,792 @@ struct CItem | |||
| 82 | UInt32 RightDid; | 131 | UInt32 RightDid; |
| 83 | UInt32 SonDid; | 132 | UInt32 SonDid; |
| 84 | UInt32 Sid; | 133 | UInt32 Sid; |
| 85 | Byte Type; | 134 | unsigned Type; // Byte : we use unsigned instead of Byte for alignment |
| 135 | |||
| 136 | UInt32 Level; | ||
| 86 | 137 | ||
| 87 | bool IsEmpty() const { return Type == NItemType::kEmpty; } | 138 | bool IsEmptyType() const { return Type == NItemType::kEmpty; } |
| 88 | bool IsDir() const { return Type == NItemType::kStorage || Type == NItemType::kRootStorage; } | 139 | bool IsDir() const { return Type == NItemType::kStorage || Type == NItemType::kRootStorage; } |
| 140 | bool IsStorage() const { return Type == NItemType::kStorage; } | ||
| 141 | |||
| 142 | bool IsLevel_Unused() const { return Level == k_Item_Level_Unused; } | ||
| 89 | 143 | ||
| 90 | void Parse(const Byte *p, bool mode64bit); | 144 | // bool IsSpecMsiName() const { return Get16(Name) == k_Msi_SpecUnicodeChar; } |
| 145 | bool AreMsiChars() const | ||
| 146 | { | ||
| 147 | for (unsigned i = 0; i < kNameSizeMax; i += 2) | ||
| 148 | { | ||
| 149 | unsigned c = Get16(Name + i); | ||
| 150 | if (c == 0) | ||
| 151 | break; | ||
| 152 | c -= k_Msi_StartUnicodeChar; | ||
| 153 | if (c <= k_Msi_UnicodeRange) | ||
| 154 | return true; | ||
| 155 | } | ||
| 156 | return false; | ||
| 157 | } | ||
| 158 | bool Parse(const Byte *p, bool mode64bit); | ||
| 91 | }; | 159 | }; |
| 92 | 160 | ||
| 161 | |||
| 162 | static const UInt32 k_Ref_Parent_Root = 0xffffffff; | ||
| 163 | |||
| 93 | struct CRef | 164 | struct CRef |
| 94 | { | 165 | { |
| 95 | int Parent; | 166 | UInt32 Parent; // index in Refs[] |
| 96 | UInt32 Did; | 167 | UInt32 Did; // index in Items[] |
| 97 | }; | 168 | }; |
| 98 | 169 | ||
| 170 | |||
| 99 | class CDatabase | 171 | class CDatabase |
| 100 | { | 172 | { |
| 101 | CObjArray<UInt32> MiniSids; | ||
| 102 | |||
| 103 | HRESULT AddNode(int parent, UInt32 did); | ||
| 104 | |||
| 105 | public: | 173 | public: |
| 174 | CRecordVector<CRef> Refs; | ||
| 175 | CObjectVector<CItem> Items; | ||
| 106 | CObjArray<UInt32> Fat; | 176 | CObjArray<UInt32> Fat; |
| 107 | CObjArray<UInt32> Mat; | 177 | CObjArray<UInt32> Mat; |
| 108 | CObjectVector<CItem> Items; | 178 | CObjArray<UInt32> MiniSids; |
| 109 | CRecordVector<CRef> Refs; | 179 | |
| 110 | private: | ||
| 111 | UInt32 NumSectorsInMiniStream; | ||
| 112 | public: | ||
| 113 | UInt32 MatSize; | ||
| 114 | UInt32 FatSize; | 180 | UInt32 FatSize; |
| 181 | UInt32 MatSize; | ||
| 182 | UInt32 NumSectors_in_MiniStream; | ||
| 115 | 183 | ||
| 116 | UInt32 LongStreamMinSize; | 184 | // UInt32 LongStreamMinSize; |
| 117 | unsigned SectorSizeBits; | 185 | unsigned SectorSizeBits; |
| 118 | unsigned MiniSectorSizeBits; | ||
| 119 | 186 | ||
| 120 | Int32 MainSubfile; | 187 | Int32 MainSubfile; |
| 121 | EType Type; | 188 | EArcType Type; |
| 189 | |||
| 190 | bool IsArc; | ||
| 191 | bool HeadersError; | ||
| 192 | // bool IsMsi; | ||
| 122 | 193 | ||
| 123 | UInt64 PhySize; | 194 | UInt64 PhySize; |
| 124 | UInt64 PhySize_Aligned; | 195 | UInt64 PhySize_Unaligned; |
| 196 | // UInt64 FreeSize; | ||
| 125 | 197 | ||
| 126 | bool IsNotArcType() const | 198 | IArchiveOpenCallback *OpenCallback; |
| 199 | UInt32 Callback_Cur; | ||
| 200 | |||
| 201 | private: | ||
| 202 | /* | ||
| 203 | HRESULT IncreaseOpenTotal(UInt32 numSects) | ||
| 127 | { | 204 | { |
| 128 | return | 205 | if (!OpenCallback) |
| 129 | Type != k_Type_Msi && | 206 | return S_OK; |
| 130 | Type != k_Type_Msp; | 207 | const UInt64 total = (UInt64)(Callback_Cur + numSects) << SectorSizeBits; |
| 208 | return OpenCallback->SetTotal(NULL, &total); | ||
| 131 | } | 209 | } |
| 210 | */ | ||
| 211 | HRESULT AddNodes(); | ||
| 212 | HRESULT ReadSector(IInStream *inStream, Byte *buf, UInt32 sid); | ||
| 213 | HRESULT ReadIDs(IInStream *inStream, Byte *buf, UInt32 sid, UInt32 *dest); | ||
| 214 | HRESULT Check_Item(unsigned index); | ||
| 132 | 215 | ||
| 133 | void UpdatePhySize(UInt64 val, UInt64 val_Aligned) | 216 | public: |
| 217 | bool IsNotArcType() const | ||
| 134 | { | 218 | { |
| 135 | if (PhySize < val) | 219 | return |
| 136 | PhySize = val; | 220 | Type != k_Type_Msi && |
| 137 | if (PhySize_Aligned < val_Aligned) | 221 | Type != k_Type_Msp && |
| 138 | PhySize_Aligned = val_Aligned; | 222 | Type != k_Type_Msm; |
| 139 | } | 223 | } |
| 140 | HRESULT ReadSector(IInStream *inStream, Byte *buf, unsigned sectorSizeBits, UInt32 sid); | ||
| 141 | HRESULT ReadIDs(IInStream *inStream, Byte *buf, unsigned sectorSizeBits, UInt32 sid, UInt32 *dest); | ||
| 142 | |||
| 143 | HRESULT Update_PhySize_WithItem(unsigned index); | ||
| 144 | 224 | ||
| 145 | void Clear(); | 225 | void Clear(); |
| 146 | bool IsLargeStream(UInt64 size) const { return size >= LongStreamMinSize; } | ||
| 147 | UString GetItemPath(UInt32 index) const; | 226 | UString GetItemPath(UInt32 index) const; |
| 148 | 227 | ||
| 149 | UInt64 GetItemPackSize(UInt64 size) const | 228 | UInt64 GetItemPackSize(UInt64 size) const |
| 150 | { | 229 | { |
| 151 | const UInt64 mask = ((UInt32)1 << (IsLargeStream(size) ? SectorSizeBits : MiniSectorSizeBits)) - 1; | 230 | const UInt64 mask = ((UInt32)1 << (IsLargeStream(size) ? SectorSizeBits : k_MiniSectorSizeBits)) - 1; |
| 152 | return (size + mask) & ~mask; | 231 | return (size + mask) & ~(UInt64)mask; |
| 153 | } | ||
| 154 | |||
| 155 | bool GetMiniCluster(UInt32 sid, UInt64 &res) const | ||
| 156 | { | ||
| 157 | const unsigned subBits = SectorSizeBits - MiniSectorSizeBits; | ||
| 158 | const UInt32 fid = sid >> subBits; | ||
| 159 | if (fid >= NumSectorsInMiniStream) | ||
| 160 | return false; | ||
| 161 | res = (((UInt64)MiniSids[fid] + 1) << subBits) + (sid & ((1 << subBits) - 1)); | ||
| 162 | return true; | ||
| 163 | } | 232 | } |
| 164 | 233 | ||
| 165 | HRESULT Open(IInStream *inStream); | 234 | HRESULT Open(IInStream *inStream); |
| 166 | }; | 235 | }; |
| 167 | 236 | ||
| 168 | 237 | ||
| 169 | HRESULT CDatabase::ReadSector(IInStream *inStream, Byte *buf, unsigned sectorSizeBits, UInt32 sid) | 238 | HRESULT CDatabase::ReadSector(IInStream *inStream, Byte *buf, UInt32 sid) |
| 170 | { | 239 | { |
| 171 | const UInt64 end = ((UInt64)sid + 2) << sectorSizeBits; | 240 | const unsigned sb = SectorSizeBits; |
| 172 | UpdatePhySize(end, end); | 241 | RINOK(InStream_SeekSet(inStream, ((UInt64)sid + 1) << sb)) |
| 173 | RINOK(InStream_SeekSet(inStream, (((UInt64)sid + 1) << sectorSizeBits))) | 242 | RINOK(ReadStream_FALSE(inStream, buf, (size_t)1 << sb)) |
| 174 | return ReadStream_FALSE(inStream, buf, (size_t)1 << sectorSizeBits); | 243 | if (OpenCallback) |
| 244 | { | ||
| 245 | if ((++Callback_Cur & 0xfff) == 0) | ||
| 246 | { | ||
| 247 | const UInt64 processed = (UInt64)Callback_Cur << sb; | ||
| 248 | const UInt64 numFiles = Items.Size(); | ||
| 249 | RINOK(OpenCallback->SetCompleted(&numFiles, &processed)) | ||
| 250 | } | ||
| 251 | } | ||
| 252 | return S_OK; | ||
| 175 | } | 253 | } |
| 176 | 254 | ||
| 177 | HRESULT CDatabase::ReadIDs(IInStream *inStream, Byte *buf, unsigned sectorSizeBits, UInt32 sid, UInt32 *dest) | 255 | HRESULT CDatabase::ReadIDs(IInStream *inStream, Byte *buf, UInt32 sid, UInt32 *dest) |
| 178 | { | 256 | { |
| 179 | RINOK(ReadSector(inStream, buf, sectorSizeBits, sid)) | 257 | RINOK(ReadSector(inStream, buf, sid)) |
| 180 | const UInt32 sectorSize = (UInt32)1 << sectorSizeBits; | 258 | const size_t sectorSize = (size_t)1 << SectorSizeBits; |
| 181 | for (UInt32 t = 0; t < sectorSize; t += 4) | 259 | for (size_t t = 0; t < sectorSize; t += 4) |
| 182 | *dest++ = Get32(buf + t); | 260 | *dest++ = Get32(buf + t); |
| 183 | return S_OK; | 261 | return S_OK; |
| 184 | } | 262 | } |
| 185 | 263 | ||
| 264 | |||
| 265 | Z7_FORCE_INLINE | ||
| 186 | static void GetFileTimeFromMem(const Byte *p, FILETIME *ft) | 266 | static void GetFileTimeFromMem(const Byte *p, FILETIME *ft) |
| 187 | { | 267 | { |
| 188 | ft->dwLowDateTime = Get32(p); | 268 | ft->dwLowDateTime = Get32(p); |
| 189 | ft->dwHighDateTime = Get32(p + 4); | 269 | ft->dwHighDateTime = Get32(p + 4); |
| 190 | } | 270 | } |
| 191 | 271 | ||
| 192 | void CItem::Parse(const Byte *p, bool mode64bit) | 272 | bool CItem::Parse(const Byte *p, bool mode64bit) |
| 193 | { | 273 | { |
| 194 | memcpy(Name, p, kNameSizeMax); | 274 | memcpy(Name, p, kNameSizeMax); |
| 195 | // NameSize = Get16(p + 64); | 275 | unsigned i; |
| 276 | for (i = 0; i < kNameSizeMax; i += 2) | ||
| 277 | if (*(const UInt16 *)(const void *)(p + i) == 0) | ||
| 278 | break; | ||
| 279 | #if 0 // 1 : for debug : for more strict field check | ||
| 280 | { | ||
| 281 | for (unsigned k = i; k < kNameSizeMax; k += 2) | ||
| 282 | if (*(const UInt16 *)(const void *)(p + k) != 0) | ||
| 283 | return false; | ||
| 284 | } | ||
| 285 | #endif | ||
| 196 | Type = p[66]; | 286 | Type = p[66]; |
| 287 | // DOC: names are limited to 32 UTF-16 code points, including the terminating null character. | ||
| 288 | if (!IsEmptyType()) | ||
| 289 | if (i == kNameSizeMax || i + 2 != Get16(p + 64)) // NameLength | ||
| 290 | return false; | ||
| 291 | if (p[67] >= 2) // Color: 0 (red) or 1 (black) | ||
| 292 | return false; | ||
| 197 | LeftDid = Get32(p + 68); | 293 | LeftDid = Get32(p + 68); |
| 198 | RightDid = Get32(p + 72); | 294 | RightDid = Get32(p + 72); |
| 199 | SonDid = Get32(p + 76); | 295 | SonDid = Get32(p + 76); |
| 200 | // Flags = Get32(p + 96); | 296 | // if (Get32(p + 96) == 0) return false; // State / Flags |
| 201 | GetFileTimeFromMem(p + 100, &CTime); | 297 | GetFileTimeFromMem(p + 100, &CTime); |
| 202 | GetFileTimeFromMem(p + 108, &MTime); | 298 | GetFileTimeFromMem(p + 108, &MTime); |
| 203 | Sid = Get32(p + 116); | 299 | Sid = Get32(p + 116); |
| 204 | Size = Get32(p + 120); | 300 | Size = Get32(p + 120); |
| 301 | /* MS DOC: it is recommended that parsers ignore the most | ||
| 302 | significant 32 bits of this field in version 3 compound files */ | ||
| 205 | if (mode64bit) | 303 | if (mode64bit) |
| 206 | Size |= ((UInt64)Get32(p + 124) << 32); | 304 | Size |= ((UInt64)Get32(p + 124) << 32); |
| 305 | return true; | ||
| 207 | } | 306 | } |
| 208 | 307 | ||
| 308 | |||
| 209 | void CDatabase::Clear() | 309 | void CDatabase::Clear() |
| 210 | { | 310 | { |
| 311 | Type = k_Type_Common; | ||
| 312 | MainSubfile = -1; | ||
| 313 | IsArc = false; | ||
| 314 | HeadersError = false; | ||
| 315 | // IsMsi = false; | ||
| 211 | PhySize = 0; | 316 | PhySize = 0; |
| 212 | PhySize_Aligned = 0; | 317 | PhySize_Unaligned = 0; |
| 213 | 318 | // FreeSize = 0; | |
| 319 | Callback_Cur = 0; | ||
| 320 | // OpenCallback = NULL; | ||
| 321 | |||
| 322 | FatSize = 0; | ||
| 323 | MatSize = 0; | ||
| 324 | NumSectors_in_MiniStream = 0; | ||
| 325 | |||
| 214 | Fat.Free(); | 326 | Fat.Free(); |
| 215 | MiniSids.Free(); | ||
| 216 | Mat.Free(); | 327 | Mat.Free(); |
| 328 | MiniSids.Free(); | ||
| 217 | Items.Clear(); | 329 | Items.Clear(); |
| 218 | Refs.Clear(); | 330 | Refs.Clear(); |
| 219 | } | 331 | } |
| 220 | 332 | ||
| 221 | static const UInt32 kNoDid = 0xFFFFFFFF; | ||
| 222 | 333 | ||
| 223 | HRESULT CDatabase::AddNode(int parent, UInt32 did) | 334 | static const UInt32 kNoDid = 0xffffffff; |
| 335 | |||
| 336 | HRESULT CDatabase::AddNodes() | ||
| 224 | { | 337 | { |
| 225 | if (did == kNoDid) | 338 | UInt32 index = Items[0].SonDid; // Items[0] is root item |
| 339 | if (index == kNoDid) // no files case | ||
| 226 | return S_OK; | 340 | return S_OK; |
| 227 | if (did >= (UInt32)Items.Size()) | 341 | if (index == 0 || index >= Items.Size()) |
| 228 | return S_FALSE; | ||
| 229 | const CItem &item = Items[did]; | ||
| 230 | if (item.IsEmpty()) | ||
| 231 | return S_FALSE; | ||
| 232 | CRef ref; | ||
| 233 | ref.Parent = parent; | ||
| 234 | ref.Did = did; | ||
| 235 | const unsigned index = Refs.Add(ref); | ||
| 236 | if (Refs.Size() > Items.Size()) | ||
| 237 | return S_FALSE; | 342 | return S_FALSE; |
| 238 | RINOK(AddNode(parent, item.LeftDid)) | 343 | |
| 239 | RINOK(AddNode(parent, item.RightDid)) | 344 | CObjArray<UInt32> itemParents(Items.Size()); |
| 240 | if (item.IsDir()) | 345 | CByteArr states(Items.Size()); |
| 346 | memset(itemParents, 0, (size_t)Items.Size() * sizeof(itemParents[0])); // optional | ||
| 347 | memset(states, 0, Items.Size()); | ||
| 348 | |||
| 349 | #if 1 // 0 : for debug | ||
| 350 | const UInt32 k_exitParent = 0; | ||
| 351 | const UInt32 k_startLevel = 1; | ||
| 352 | // we don't show "Root Entry" dir | ||
| 353 | states[0] = 3; // we mark root node as processed, also we block any cycle links to root node | ||
| 354 | // itemParents[0] = 0xffffffff; // optional / unused value | ||
| 355 | #else | ||
| 356 | // we show item[0] "Root Entry" dir | ||
| 357 | const UInt32 k_exitParent = 0xffffffff; | ||
| 358 | const UInt32 k_startLevel = 0; | ||
| 359 | index = 0; | ||
| 360 | #endif | ||
| 361 | |||
| 362 | UInt32 level = k_startLevel; // directory level | ||
| 363 | unsigned state = 0; | ||
| 364 | UInt32 parent = k_exitParent; // in Items[], itemParents[], states[] | ||
| 365 | UInt32 refParent = k_Ref_Parent_Root; // in Refs[] | ||
| 366 | |||
| 367 | for (;;) | ||
| 241 | { | 368 | { |
| 242 | RINOK(AddNode((int)index, item.SonDid)) | 369 | if (state >= 3) |
| 243 | } | 370 | { |
| 244 | return S_OK; | 371 | // we return to parent node |
| 245 | } | 372 | if (state != 3) |
| 373 | return E_FAIL; | ||
| 374 | index = parent; | ||
| 375 | if (index == k_exitParent) | ||
| 376 | break; | ||
| 377 | if (index >= Items.Size()) | ||
| 378 | return E_FAIL; // (index) was checked already | ||
| 379 | parent = itemParents[index]; | ||
| 380 | state = states[index]; | ||
| 381 | if (state == 0) | ||
| 382 | return E_FAIL; | ||
| 383 | if (state == 2) | ||
| 384 | { | ||
| 385 | // we return to parent Dir node | ||
| 386 | if (refParent >= Refs.Size()) | ||
| 387 | return E_FAIL; | ||
| 388 | refParent = Refs[refParent].Parent; | ||
| 389 | level--; | ||
| 390 | } | ||
| 391 | continue; | ||
| 392 | } | ||
| 246 | 393 | ||
| 247 | static UString CompoundNameToFileName(const UString &s) | 394 | if (index >= Items.Size()) |
| 248 | { | 395 | return S_FALSE; |
| 249 | UString res; | 396 | CItem &item = Items[index]; |
| 250 | for (unsigned i = 0; i < s.Len(); i++) | 397 | if (item.IsEmptyType()) |
| 398 | return S_FALSE; | ||
| 399 | item.Level = level; | ||
| 400 | state++; | ||
| 401 | states[index] = (Byte)state; // we mark current (index) node as used node | ||
| 402 | |||
| 403 | UInt32 newIndex; | ||
| 404 | if (state != 2) | ||
| 405 | newIndex = (state < 2) ? item.LeftDid : item.RightDid; | ||
| 406 | else | ||
| 407 | { | ||
| 408 | CRef ref; | ||
| 409 | ref.Parent = refParent; | ||
| 410 | ref.Did = index; | ||
| 411 | const unsigned refIndex = Refs.Add(ref); | ||
| 412 | if (!item.IsDir()) | ||
| 413 | continue; | ||
| 414 | newIndex = item.SonDid; | ||
| 415 | if (newIndex != kNoDid) | ||
| 416 | { | ||
| 417 | level++; | ||
| 418 | refParent = refIndex; | ||
| 419 | } | ||
| 420 | } | ||
| 421 | |||
| 422 | if (newIndex != kNoDid) | ||
| 423 | { | ||
| 424 | itemParents[index] = parent; | ||
| 425 | state = 0; | ||
| 426 | parent = index; | ||
| 427 | index = newIndex; | ||
| 428 | if (index >= Items.Size() || states[index]) | ||
| 429 | return S_FALSE; | ||
| 430 | } | ||
| 431 | } | ||
| 432 | |||
| 433 | if (level != k_startLevel || refParent != k_Ref_Parent_Root) | ||
| 434 | return E_FAIL; | ||
| 435 | #if 1 // 1 : optional | ||
| 436 | // we check that all non-empty items were processed correctly | ||
| 437 | FOR_VECTOR(i, Items) | ||
| 251 | { | 438 | { |
| 252 | const wchar_t c = s[i]; | 439 | const unsigned st = states[i]; |
| 253 | if ((unsigned)(int)c < 0x20) | 440 | if (Items[i].IsEmptyType()) |
| 254 | { | 441 | { |
| 255 | res.Add_Char('['); | 442 | if (st) |
| 256 | res.Add_UInt32((UInt32)(unsigned)(int)c); | 443 | return E_FAIL; |
| 257 | res.Add_Char(']'); | ||
| 258 | } | 444 | } |
| 445 | else if (st == 3) | ||
| 446 | continue; | ||
| 447 | else if (st) | ||
| 448 | return E_FAIL; | ||
| 259 | else | 449 | else |
| 260 | res += c; | 450 | return S_FALSE; // there is unused directory item |
| 261 | } | 451 | } |
| 262 | return res; | 452 | #endif |
| 453 | return S_OK; | ||
| 263 | } | 454 | } |
| 264 | 455 | ||
| 456 | |||
| 265 | static const char k_Msi_Chars[] = | 457 | static const char k_Msi_Chars[] = |
| 266 | "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz._"; | 458 | "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz._"; |
| 267 | 459 | static const char k_Msi_SpecChar_Replace = '!'; | |
| 268 | // static const char * const k_Msi_ID = ""; // "{msi}"; | ||
| 269 | static const char k_Msi_SpecChar = '!'; | ||
| 270 | |||
| 271 | static const unsigned k_Msi_NumBits = 6; | ||
| 272 | static const unsigned k_Msi_NumChars = 1 << k_Msi_NumBits; | ||
| 273 | static const unsigned k_Msi_CharMask = k_Msi_NumChars - 1; | ||
| 274 | static const unsigned k_Msi_StartUnicodeChar = 0x3800; | ||
| 275 | static const unsigned k_Msi_UnicodeRange = k_Msi_NumChars * (k_Msi_NumChars + 1); | ||
| 276 | |||
| 277 | |||
| 278 | static bool IsMsiName(const Byte *p) | ||
| 279 | { | ||
| 280 | UInt32 c = Get16(p); | ||
| 281 | return | ||
| 282 | c >= k_Msi_StartUnicodeChar && | ||
| 283 | c <= k_Msi_StartUnicodeChar + k_Msi_UnicodeRange; | ||
| 284 | } | ||
| 285 | 460 | ||
| 286 | static bool AreEqualNames(const Byte *rawName, const char *asciiName) | 461 | static bool AreEqualNames(const Byte *rawName, const char *asciiName) |
| 287 | { | 462 | { |
| 288 | for (unsigned i = 0; i < kNameSizeMax / 2; i++) | 463 | for (;;) |
| 289 | { | 464 | { |
| 290 | wchar_t c = Get16(rawName + i * 2); | 465 | const unsigned c = Get16(rawName); |
| 291 | wchar_t c2 = (Byte)asciiName[i]; | 466 | rawName += 2; |
| 467 | const unsigned c2 = (Byte)*asciiName; | ||
| 468 | asciiName++; | ||
| 292 | if (c != c2) | 469 | if (c != c2) |
| 293 | return false; | 470 | return false; |
| 294 | if (c == 0) | 471 | if (c2 == 0) |
| 295 | return true; | 472 | return true; |
| 296 | } | 473 | } |
| 297 | return false; | ||
| 298 | } | 474 | } |
| 299 | 475 | ||
| 300 | static bool CompoundMsiNameToFileName(const UString &name, UString &res) | ||
| 301 | { | ||
| 302 | res.Empty(); | ||
| 303 | for (unsigned i = 0; i < name.Len(); i++) | ||
| 304 | { | ||
| 305 | wchar_t c = name[i]; | ||
| 306 | if (c < (wchar_t)k_Msi_StartUnicodeChar || c > (wchar_t)(k_Msi_StartUnicodeChar + k_Msi_UnicodeRange)) | ||
| 307 | return false; | ||
| 308 | /* | ||
| 309 | if (i == 0) | ||
| 310 | res += k_Msi_ID; | ||
| 311 | */ | ||
| 312 | c -= (wchar_t)k_Msi_StartUnicodeChar; | ||
| 313 | |||
| 314 | const unsigned c0 = (unsigned)c & k_Msi_CharMask; | ||
| 315 | const unsigned c1 = (unsigned)c >> k_Msi_NumBits; | ||
| 316 | 476 | ||
| 317 | if (c1 <= k_Msi_NumChars) | 477 | static void MsiName_To_FileName(const Byte *p, UString &res) |
| 318 | { | ||
| 319 | res.Add_Char(k_Msi_Chars[c0]); | ||
| 320 | if (c1 == k_Msi_NumChars) | ||
| 321 | break; | ||
| 322 | res.Add_Char(k_Msi_Chars[c1]); | ||
| 323 | } | ||
| 324 | else | ||
| 325 | res.Add_Char(k_Msi_SpecChar); | ||
| 326 | } | ||
| 327 | return true; | ||
| 328 | } | ||
| 329 | |||
| 330 | static UString ConvertName(const Byte *p, bool &isMsi) | ||
| 331 | { | 478 | { |
| 332 | isMsi = false; | 479 | res.Empty(); |
| 333 | UString s; | ||
| 334 | |||
| 335 | for (unsigned i = 0; i < kNameSizeMax; i += 2) | 480 | for (unsigned i = 0; i < kNameSizeMax; i += 2) |
| 336 | { | 481 | { |
| 337 | wchar_t c = Get16(p + i); | 482 | unsigned c = Get16(p + i); |
| 338 | if (c == 0) | 483 | if (c == 0) |
| 339 | break; | 484 | break; |
| 340 | s += c; | 485 | if (c <= k_Msi_SpecUnicodeChar) |
| 341 | } | 486 | { |
| 342 | 487 | if (c < k_Msi_StartUnicodeChar) | |
| 343 | UString msiName; | 488 | { |
| 344 | if (CompoundMsiNameToFileName(s, msiName)) | 489 | if (c < 0x20) |
| 345 | { | 490 | { |
| 346 | isMsi = true; | 491 | res.Add_Char('['); |
| 347 | return msiName; | 492 | res.Add_UInt32((UInt32)c); |
| 493 | c = ']'; | ||
| 494 | } | ||
| 495 | } | ||
| 496 | else | ||
| 497 | { | ||
| 498 | #if 0 // 1 : for debug | ||
| 499 | if (i == 0) res += "{msi}"; | ||
| 500 | #endif | ||
| 501 | c -= k_Msi_StartUnicodeChar; | ||
| 502 | const unsigned c1 = (unsigned)c >> k_Msi_NumBits; | ||
| 503 | if (c1 <= k_Msi_NumChars) | ||
| 504 | { | ||
| 505 | res.Add_Char(k_Msi_Chars[(unsigned)c & k_Msi_CharMask]); | ||
| 506 | if (c1 == k_Msi_NumChars) | ||
| 507 | continue; | ||
| 508 | c = (Byte)k_Msi_Chars[c1]; | ||
| 509 | } | ||
| 510 | else | ||
| 511 | c = k_Msi_SpecChar_Replace; | ||
| 512 | } | ||
| 513 | } | ||
| 514 | res += (wchar_t)c; | ||
| 348 | } | 515 | } |
| 349 | return CompoundNameToFileName(s); | ||
| 350 | } | 516 | } |
| 351 | 517 | ||
| 352 | static UString ConvertName(const Byte *p) | ||
| 353 | { | ||
| 354 | bool isMsi; | ||
| 355 | return ConvertName(p, isMsi); | ||
| 356 | } | ||
| 357 | 518 | ||
| 358 | UString CDatabase::GetItemPath(UInt32 index) const | 519 | UString CDatabase::GetItemPath(UInt32 index) const |
| 359 | { | 520 | { |
| 360 | UString s; | 521 | UString s; |
| 361 | while (index != kNoDid) | 522 | UString name; |
| 523 | unsigned level = 0; | ||
| 524 | while (index != k_Ref_Parent_Root) | ||
| 362 | { | 525 | { |
| 363 | const CRef &ref = Refs[index]; | 526 | const CRef &ref = Refs[index]; |
| 364 | const CItem &item = Items[ref.Did]; | 527 | const CItem &item = Items[ref.Did]; |
| 365 | if (!s.IsEmpty()) | 528 | if (!s.IsEmpty()) |
| 366 | s.InsertAtFront(WCHAR_PATH_SEPARATOR); | 529 | s.InsertAtFront(WCHAR_PATH_SEPARATOR); |
| 367 | s.Insert(0, ConvertName(item.Name)); | 530 | // if (IsMsi) |
| 368 | index = (unsigned)ref.Parent; | 531 | MsiName_To_FileName(item.Name, name); |
| 532 | // else NonMsiName_To_FileName(item.Name, name); | ||
| 533 | NItemName::NormalizeSlashes_in_FileName_for_OsPath(name); | ||
| 534 | if (name.IsEmpty()) | ||
| 535 | name = "[]"; | ||
| 536 | s.Insert(0, name); | ||
| 537 | index = ref.Parent; | ||
| 538 | #ifdef Z7_COMPOUND_SHOW_DELETED | ||
| 539 | if (item.IsLevel_Unused()) | ||
| 540 | { | ||
| 541 | s.Insert(0, L"[DELETED]" WSTRING_PATH_SEPARATOR); | ||
| 542 | break; | ||
| 543 | } | ||
| 544 | #endif | ||
| 545 | if (item.Level >= k_Long_path_level_limit && level) | ||
| 546 | { | ||
| 547 | s.Insert(0, L"[LONG_PATH]" WSTRING_PATH_SEPARATOR); | ||
| 548 | break; | ||
| 549 | } | ||
| 550 | level = 1; // level++; | ||
| 369 | } | 551 | } |
| 370 | return s; | 552 | return s; |
| 371 | } | 553 | } |
| 372 | 554 | ||
| 373 | HRESULT CDatabase::Update_PhySize_WithItem(unsigned index) | 555 | |
| 556 | HRESULT CDatabase::Check_Item(unsigned index) | ||
| 374 | { | 557 | { |
| 375 | const CItem &item = Items[index]; | 558 | const CItem &item = Items[index]; |
| 376 | const bool isLargeStream = (index == 0 || IsLargeStream(item.Size)); | 559 | if (item.IsEmptyType() || item.IsStorage()) |
| 377 | if (!isLargeStream) | ||
| 378 | return S_OK; | 560 | return S_OK; |
| 379 | const unsigned bsLog = isLargeStream ? SectorSizeBits : MiniSectorSizeBits; | ||
| 380 | // streamSpec->Size = item.Size; | ||
| 381 | |||
| 382 | const UInt32 clusterSize = (UInt32)1 << bsLog; | ||
| 383 | const UInt64 numClusters64 = (item.Size + clusterSize - 1) >> bsLog; | ||
| 384 | if (numClusters64 >= ((UInt32)1 << 31)) | ||
| 385 | return S_FALSE; | ||
| 386 | UInt32 sid = item.Sid; | ||
| 387 | UInt64 size = item.Size; | 561 | UInt64 size = item.Size; |
| 388 | 562 | const bool isLargeStream = (index == 0 || IsLargeStream(size)); | |
| 389 | if (size != 0) | 563 | if (!isLargeStream) |
| 390 | { | 564 | { |
| 391 | for (;; size -= clusterSize) | 565 | const unsigned bsLog = k_MiniSectorSizeBits; |
| 566 | const UInt32 clusterSize = (UInt32)1 << bsLog; | ||
| 567 | const UInt64 numClusters = (size + clusterSize - 1) >> bsLog; | ||
| 568 | if (numClusters > MatSize) | ||
| 569 | return S_FALSE; | ||
| 570 | UInt32 sid = item.Sid; | ||
| 571 | if (size != 0) | ||
| 392 | { | 572 | { |
| 393 | // if (isLargeStream) | 573 | for (;; size -= clusterSize) |
| 574 | { | ||
| 575 | if (sid >= MatSize) | ||
| 576 | return S_FALSE; | ||
| 577 | const unsigned subBits = SectorSizeBits - k_MiniSectorSizeBits; | ||
| 578 | const UInt32 fid = sid >> subBits; | ||
| 579 | if (fid >= NumSectors_in_MiniStream) | ||
| 580 | return false; | ||
| 581 | sid = Mat[sid]; | ||
| 582 | if (size <= clusterSize) | ||
| 583 | break; | ||
| 584 | } | ||
| 585 | } | ||
| 586 | if (sid != NFatID::kEndOfChain) | ||
| 587 | return S_FALSE; | ||
| 588 | } | ||
| 589 | else | ||
| 590 | { | ||
| 591 | const unsigned bsLog = SectorSizeBits; | ||
| 592 | const UInt32 clusterSize = (UInt32)1 << bsLog; | ||
| 593 | const UInt64 numClusters = (size + clusterSize - 1) >> bsLog; | ||
| 594 | if (numClusters > FatSize) | ||
| 595 | return S_FALSE; | ||
| 596 | UInt32 sid = item.Sid; | ||
| 597 | if (size != 0) | ||
| 598 | { | ||
| 599 | for (;; size -= clusterSize) | ||
| 394 | { | 600 | { |
| 395 | if (sid >= FatSize) | 601 | if (sid >= FatSize) |
| 396 | return S_FALSE; | 602 | return S_FALSE; |
| 397 | UInt64 end = ((UInt64)sid + 1) << bsLog; | 603 | const UInt32 sidPrev = sid; |
| 398 | const UInt64 end_Aligned = end + clusterSize; | ||
| 399 | if (size < clusterSize) | ||
| 400 | end += size; | ||
| 401 | else | ||
| 402 | end = end_Aligned; | ||
| 403 | UpdatePhySize(end, end_Aligned); | ||
| 404 | sid = Fat[sid]; | 604 | sid = Fat[sid]; |
| 605 | if (size <= clusterSize) | ||
| 606 | { | ||
| 607 | const UInt64 phySize = (((UInt64)sidPrev + 1) << SectorSizeBits) + size; | ||
| 608 | if (PhySize_Unaligned < phySize) | ||
| 609 | PhySize_Unaligned = phySize; | ||
| 610 | break; | ||
| 611 | } | ||
| 405 | } | 612 | } |
| 406 | if (size <= clusterSize) | ||
| 407 | break; | ||
| 408 | } | 613 | } |
| 614 | if (sid != NFatID::kEndOfChain) | ||
| 615 | return S_FALSE; | ||
| 409 | } | 616 | } |
| 410 | if (sid != NFatID::kEndOfChain) | ||
| 411 | return S_FALSE; | ||
| 412 | return S_OK; | 617 | return S_OK; |
| 413 | } | 618 | } |
| 414 | 619 | ||
| 415 | // There is name "[!]MsiPatchSequence" in msp files | ||
| 416 | static const unsigned kMspSequence_Size = 18; | ||
| 417 | static const Byte kMspSequence[kMspSequence_Size] = | ||
| 418 | { 0x40, 0x48, 0x96, 0x45, 0x6C, 0x3E, 0xE4, 0x45, | ||
| 419 | 0xE6, 0x42, 0x16, 0x42, 0x37, 0x41, 0x27, 0x41, | ||
| 420 | 0x37, 0x41 }; | ||
| 421 | 620 | ||
| 422 | HRESULT CDatabase::Open(IInStream *inStream) | 621 | HRESULT CDatabase::Open(IInStream *inStream) |
| 423 | { | 622 | { |
| 424 | MainSubfile = -1; | 623 | const unsigned kHeaderSize = 512; |
| 425 | Type = k_Type_Common; | 624 | UInt32 p32[kHeaderSize / 4]; |
| 426 | const UInt32 kHeaderSize = 512; | 625 | RINOK(ReadStream_FALSE(inStream, p32, kHeaderSize)) |
| 427 | Byte p[kHeaderSize]; | 626 | const Byte *p = (const Byte *)(const void *)p32; |
| 428 | PhySize = kHeaderSize; | 627 | if (memcmp(p, kSignature, Z7_ARRAY_SIZE(kSignature))) |
| 429 | RINOK(ReadStream_FALSE(inStream, p, kHeaderSize)) | 628 | return S_FALSE; |
| 430 | if (memcmp(p, kSignature, Z7_ARRAY_SIZE(kSignature)) != 0) | 629 | /* |
| 630 | if (memcmp(p + 8, k_CLSID_AAF_V3, Z7_ARRAY_SIZE(k_CLSID_AAF_V3)) == 0 || | ||
| 631 | memcmp(p + 8, k_CLSID_AAF_V4, Z7_ARRAY_SIZE(k_CLSID_AAF_V4)) == 0) | ||
| 632 | */ | ||
| 633 | if (Get32(p32 + 4) == 0x342b0e06) // simplified AAF signature check | ||
| 634 | Type = k_Type_Aaf; | ||
| 635 | if (Get16(p + 0x18) != 0x3e) // minorVer | ||
| 431 | return S_FALSE; | 636 | return S_FALSE; |
| 432 | if (Get16(p + 0x1A) > 4) // majorVer | 637 | const unsigned ver = Get16(p + 0x1a); // majorVer |
| 638 | if (ver < 3 || ver > 4) | ||
| 433 | return S_FALSE; | 639 | return S_FALSE; |
| 434 | if (Get16(p + 0x1C) != 0xFFFE) // Little-endian | 640 | if (Get16(p + 0x1c) != 0xfffe) // Little-endian |
| 641 | return S_FALSE; | ||
| 642 | const unsigned sectorSizeBits = Get16(p + 0x1e); | ||
| 643 | if (sectorSizeBits != ver * 3) // (ver == 3 ? 9 : 12) | ||
| 435 | return S_FALSE; | 644 | return S_FALSE; |
| 436 | unsigned sectorSizeBits = Get16(p + 0x1E); | ||
| 437 | bool mode64bit = (sectorSizeBits >= 12); | ||
| 438 | unsigned miniSectorSizeBits = Get16(p + 0x20); | ||
| 439 | SectorSizeBits = sectorSizeBits; | 645 | SectorSizeBits = sectorSizeBits; |
| 440 | MiniSectorSizeBits = miniSectorSizeBits; | 646 | if (Get16(p + 0x20) != k_MiniSectorSizeBits) |
| 647 | return S_FALSE; | ||
| 648 | |||
| 649 | IsArc = true; | ||
| 650 | HeadersError = true; | ||
| 441 | 651 | ||
| 442 | if (sectorSizeBits > 24 || | 652 | const bool mode64bit = (sectorSizeBits >= 12); // (ver == 4) |
| 443 | sectorSizeBits < 7 || | 653 | if (Get16(p + 0x22) || p32[9]) // reserved |
| 444 | miniSectorSizeBits > 24 || | 654 | return S_FALSE; |
| 445 | miniSectorSizeBits < 2 || | 655 | |
| 446 | miniSectorSizeBits > sectorSizeBits) | 656 | const UInt32 numDirSectors = Get32(p32 + 10); |
| 657 | // If (ver==3), the Number of Directory Sectors MUST be zero. | ||
| 658 | if (ver != 3 + (unsigned)(numDirSectors != 0)) | ||
| 659 | return S_FALSE; | ||
| 660 | if (numDirSectors > ((1u << (32 - 2)) >> (sectorSizeBits - (7 + 2)))) | ||
| 661 | return S_FALSE; | ||
| 662 | |||
| 663 | const UInt32 numSectorsForFAT = Get32(p32 + 11); // SAT | ||
| 664 | |||
| 665 | // MSDOC: A 512-byte sector compound file MUST be no greater than 2 GB in size for compatibility reasons. | ||
| 666 | // but actual restriction for windows compond creation code can be more strict: | ||
| 667 | // (numSectorsForFAT < (1 << 15)) : actual restriction in win10 for compound creation code | ||
| 668 | // (numSectorsForFAT <= (1 << 15)) : relaxed restriction to allow 2 GB files. | ||
| 669 | if (sectorSizeBits == 9 && | ||
| 670 | numSectorsForFAT >= (1u << (31 - (9 + 9 - 2)))) // we use most strict check | ||
| 447 | return S_FALSE; | 671 | return S_FALSE; |
| 448 | UInt32 numSectorsForFAT = Get32(p + 0x2C); // SAT | ||
| 449 | LongStreamMinSize = Get32(p + 0x38); | ||
| 450 | |||
| 451 | UInt32 sectSize = (UInt32)1 << sectorSizeBits; | ||
| 452 | 672 | ||
| 453 | CByteBuffer sect(sectSize); | 673 | // const UInt32 TransactionSignatureNumber = Get32(p32 + 13); |
| 674 | if (Get32(p32 + 14) != k_LongStreamMinSize) | ||
| 675 | return S_FALSE; | ||
| 454 | 676 | ||
| 455 | unsigned ssb2 = sectorSizeBits - 2; | 677 | const unsigned ssb2 = sectorSizeBits - 2; |
| 456 | UInt32 numSidsInSec = (UInt32)1 << ssb2; | 678 | const UInt32 numSidsInSec = (UInt32)1 << ssb2; |
| 457 | UInt32 numFatItems = numSectorsForFAT << ssb2; | 679 | const UInt32 numFatItems = numSectorsForFAT << ssb2; |
| 458 | if ((numFatItems >> ssb2) != numSectorsForFAT) | 680 | if (numFatItems == 0 || (numFatItems >> ssb2) != numSectorsForFAT) |
| 459 | return S_FALSE; | 681 | return S_FALSE; |
| 460 | FatSize = numFatItems; | ||
| 461 | 682 | ||
| 683 | const size_t sectSize = (size_t)1 << sectorSizeBits; | ||
| 684 | CByteArr sect(sectSize); | ||
| 685 | CByteArr used(numFatItems); | ||
| 686 | // don't change these const values. These values use same order as (0xffffffff - NFatID::const) | ||
| 687 | // const Byte k_Used_Free = 0; | ||
| 688 | const Byte k_Used_ChainTo = 1; | ||
| 689 | const Byte k_Used_FAT = 2; | ||
| 690 | const Byte k_Used_DIFAT = 3; | ||
| 691 | memset(used, 0, numFatItems); | ||
| 692 | UInt32 *fat; | ||
| 462 | { | 693 | { |
| 463 | UInt32 numSectorsForBat = Get32(p + 0x48); // master sector allocation table | 694 | // ========== READ FAT ========== |
| 464 | const UInt32 kNumHeaderBatItems = 109; | 695 | const UInt32 numSectorsForBat = Get32(p32 + 18); // master sector allocation table |
| 465 | UInt32 numBatItems = kNumHeaderBatItems + (numSectorsForBat << ssb2); | 696 | const unsigned ssb2_m1 = ssb2 - 1; |
| 466 | if (numBatItems < kNumHeaderBatItems || ((numBatItems - kNumHeaderBatItems) >> ssb2) != numSectorsForBat) | 697 | if (numSectorsForBat > ((1u << 30) >> ssb2_m1 >> ssb2_m1)) |
| 467 | return S_FALSE; | 698 | return S_FALSE; |
| 699 | const unsigned kNumHeaderBatItems = 109; | ||
| 700 | UInt32 numBatItems = kNumHeaderBatItems + (numSectorsForBat << ssb2); // real size can be smaller | ||
| 468 | CObjArray<UInt32> bat(numBatItems); | 701 | CObjArray<UInt32> bat(numBatItems); |
| 469 | UInt32 i; | 702 | size_t i; |
| 470 | for (i = 0; i < kNumHeaderBatItems; i++) | 703 | for (i = 0; i < kNumHeaderBatItems; i++) |
| 471 | bat[i] = Get32(p + 0x4c + i * 4); | 704 | bat[i] = Get32(p32 + 19 + i); |
| 472 | UInt32 sid = Get32(p + 0x44); | ||
| 473 | for (UInt32 s = 0; s < numSectorsForBat; s++) | ||
| 474 | { | 705 | { |
| 475 | RINOK(ReadIDs(inStream, sect, sectorSizeBits, sid, bat + i)) | 706 | UInt32 sid = Get32(p32 + 17); |
| 476 | i += numSidsInSec - 1; | 707 | for (UInt32 s = 0; s < numSectorsForBat; s++) |
| 477 | sid = bat[i]; | 708 | { |
| 709 | if (sid >= numFatItems || used[sid]) | ||
| 710 | return S_FALSE; | ||
| 711 | used[sid] = k_Used_DIFAT; | ||
| 712 | RINOK(ReadIDs(inStream, sect, sid, bat + i)) | ||
| 713 | i += numSidsInSec - 1; | ||
| 714 | sid = bat[i]; | ||
| 715 | } | ||
| 716 | if (sid != NFatID::kEndOfChain // NFatID::kEndOfChain is expected value for most files | ||
| 717 | && sid != NFatID::kFree) // NFatID::kFree is used in some AAF files | ||
| 718 | return S_FALSE; | ||
| 478 | } | 719 | } |
| 479 | numBatItems = i; | 720 | numBatItems = (UInt32)i; // corrected value |
| 480 | 721 | if (numSectorsForFAT > numBatItems) | |
| 722 | return S_FALSE; | ||
| 723 | for (i = numSectorsForFAT; i < numBatItems; i++) | ||
| 724 | if (bat[i] != NFatID::kFree) | ||
| 725 | return S_FALSE; | ||
| 726 | |||
| 727 | // RINOK(IncreaseOpenTotal(numSectorsForFAT + numDirSectors)) | ||
| 728 | |||
| 481 | Fat.Alloc(numFatItems); | 729 | Fat.Alloc(numFatItems); |
| 482 | UInt32 j = 0; | 730 | fat = Fat; |
| 483 | 731 | for (i = 0; i < numSectorsForFAT; i++) | |
| 484 | for (i = 0; i < numFatItems; j++, i += numSidsInSec) | ||
| 485 | { | 732 | { |
| 486 | if (j >= numBatItems) | 733 | const UInt32 sectorIndex = bat[i]; |
| 734 | if (sectorIndex >= numFatItems) | ||
| 487 | return S_FALSE; | 735 | return S_FALSE; |
| 488 | RINOK(ReadIDs(inStream, sect, sectorSizeBits, bat[j], Fat + i)) | 736 | if (used[sectorIndex]) |
| 737 | return S_FALSE; | ||
| 738 | used[sectorIndex] = k_Used_FAT; | ||
| 739 | UInt32 *fat2 = fat + ((size_t)i << ssb2); | ||
| 740 | RINOK(ReadIDs(inStream, sect, sectorIndex, fat2)) | ||
| 741 | for (size_t k = 0; k < numSidsInSec; k++) | ||
| 742 | { | ||
| 743 | const UInt32 sid = fat2[k]; | ||
| 744 | if (sid > NFatID::kMaxValue) | ||
| 745 | { | ||
| 746 | if (sid == NFatID::k_DIF_SECT | ||
| 747 | && used[((size_t)i << ssb2) + k] != k_Used_DIFAT) | ||
| 748 | return S_FALSE; | ||
| 749 | continue; | ||
| 750 | } | ||
| 751 | if (sid >= numFatItems || used[sid]) | ||
| 752 | return S_FALSE; // strict error check | ||
| 753 | used[sid] = k_Used_ChainTo; | ||
| 754 | } | ||
| 489 | } | 755 | } |
| 490 | FatSize = numFatItems = i; | 756 | { |
| 757 | for (i = 0; i < numSectorsForFAT; i++) | ||
| 758 | if (fat[bat[i]] != NFatID::kFatSector) | ||
| 759 | return S_FALSE; | ||
| 760 | } | ||
| 761 | FatSize = numFatItems; | ||
| 762 | } | ||
| 763 | |||
| 764 | { | ||
| 765 | size_t i = numFatItems; | ||
| 766 | do | ||
| 767 | if (fat[i - 1] != NFatID::kFree) | ||
| 768 | break; | ||
| 769 | while (--i); | ||
| 770 | PhySize = ((UInt64)i + 1) << sectorSizeBits; | ||
| 771 | /* | ||
| 772 | if (i) | ||
| 773 | { | ||
| 774 | const UInt32 *lim = fat + i; | ||
| 775 | UInt32 num = 0; | ||
| 776 | do | ||
| 777 | if (*fat++ == NFatID::kFree) | ||
| 778 | num++; | ||
| 779 | while (fat != lim); | ||
| 780 | FreeSize = num << sectorSizeBits; | ||
| 781 | } | ||
| 782 | */ | ||
| 491 | } | 783 | } |
| 492 | 784 | ||
| 493 | UInt32 numMatItems; | 785 | UInt32 numMatItems; |
| 494 | { | 786 | { |
| 495 | UInt32 numSectorsForMat = Get32(p + 0x40); | 787 | // ========== READ MAT ========== |
| 788 | const UInt32 numSectorsForMat = Get32(p32 + 16); | ||
| 496 | numMatItems = (UInt32)numSectorsForMat << ssb2; | 789 | numMatItems = (UInt32)numSectorsForMat << ssb2; |
| 497 | if ((numMatItems >> ssb2) != numSectorsForMat) | 790 | if ((numMatItems >> ssb2) != numSectorsForMat) |
| 498 | return S_FALSE; | 791 | return S_FALSE; |
| 499 | Mat.Alloc(numMatItems); | 792 | Mat.Alloc(numMatItems); |
| 500 | UInt32 i; | 793 | UInt32 sid = Get32(p32 + 15); // short-sector table SID |
| 501 | UInt32 sid = Get32(p + 0x3C); // short-sector table SID | 794 | if (numMatItems) |
| 502 | for (i = 0; i < numMatItems; i += numSidsInSec) | 795 | { |
| 796 | if (sid >= numFatItems || used[sid]) | ||
| 797 | return S_FALSE; | ||
| 798 | used[sid] = k_Used_ChainTo; | ||
| 799 | } | ||
| 800 | for (UInt32 i = 0; i < numMatItems; i += numSidsInSec) | ||
| 503 | { | 801 | { |
| 504 | RINOK(ReadIDs(inStream, sect, sectorSizeBits, sid, Mat + i)) | ||
| 505 | if (sid >= numFatItems) | 802 | if (sid >= numFatItems) |
| 506 | return S_FALSE; | 803 | return S_FALSE; |
| 507 | sid = Fat[sid]; | 804 | RINOK(ReadIDs(inStream, sect, sid, Mat + i)) |
| 805 | sid = fat[sid]; | ||
| 508 | } | 806 | } |
| 509 | if (sid != NFatID::kEndOfChain) | 807 | if (sid != NFatID::kEndOfChain) |
| 510 | return S_FALSE; | 808 | return S_FALSE; |
| 511 | } | 809 | } |
| 512 | 810 | ||
| 513 | { | 811 | { |
| 514 | CByteBuffer used(numFatItems); | 812 | // ========== READ DIR ITEMS ========== |
| 515 | for (UInt32 i = 0; i < numFatItems; i++) | 813 | UInt32 sid = Get32(p32 + 12); // directory stream SID |
| 516 | used[i] = 0; | 814 | UInt32 numDirSectors_Processed = 0; |
| 517 | UInt32 sid = Get32(p + 0x30); // directory stream SID | 815 | if (sid >= numFatItems || used[sid]) |
| 518 | for (;;) | 816 | return S_FALSE; |
| 817 | used[sid] = k_Used_ChainTo; | ||
| 818 | do | ||
| 519 | { | 819 | { |
| 820 | // we need to check sid here becase kEndOfChain sid < numFatItems is required | ||
| 520 | if (sid >= numFatItems) | 821 | if (sid >= numFatItems) |
| 521 | return S_FALSE; | 822 | return S_FALSE; |
| 522 | if (used[sid]) | 823 | if (numDirSectors && numDirSectors_Processed >= numDirSectors) |
| 523 | return S_FALSE; | 824 | return S_FALSE; |
| 524 | used[sid] = 1; | 825 | numDirSectors_Processed++; |
| 525 | RINOK(ReadSector(inStream, sect, sectorSizeBits, sid)) | 826 | RINOK(ReadSector(inStream, sect, sid)) |
| 526 | for (UInt32 i = 0; i < sectSize; i += 128) | 827 | for (size_t i = 0; i < sectSize; i += (1 << 7)) |
| 527 | { | 828 | { |
| 528 | CItem item; | 829 | CItem item; |
| 529 | item.Parse(sect + i, mode64bit); | 830 | item.Level = k_Item_Level_Unused; |
| 831 | if (!item.Parse(sect + i, mode64bit)) | ||
| 832 | return S_FALSE; | ||
| 530 | // we use (item.Size) check here. | 833 | // we use (item.Size) check here. |
| 531 | // so we don't need additional overflow checks for (item.Size +) in another code | 834 | // so we don't need additional overflow checks for (item.Size +) in another code |
| 532 | if (item.Size >= ((UInt64)1 << 63)) | 835 | if ((UInt32)(item.Size >> 32) >= sectSize) // it's because FAT size is limited by (1 << 32) items. |
| 533 | return S_FALSE; | 836 | return S_FALSE; |
| 837 | |||
| 838 | if (Items.IsEmpty()) | ||
| 839 | { | ||
| 840 | if (item.Type != NItemType::kRootStorage | ||
| 841 | || item.LeftDid != kNoDid | ||
| 842 | || item.RightDid != kNoDid | ||
| 843 | || item.SonDid == 0) | ||
| 844 | return S_FALSE; | ||
| 845 | if (item.Sid != NFatID::kEndOfChain) | ||
| 846 | { | ||
| 847 | if (item.Sid >= numFatItems || used[item.Sid]) | ||
| 848 | return S_FALSE; | ||
| 849 | used[item.Sid] = k_Used_ChainTo; | ||
| 850 | } | ||
| 851 | } | ||
| 852 | else if (item.IsStorage()) | ||
| 853 | { | ||
| 854 | if (item.Size != 0) // by specification | ||
| 855 | return S_FALSE; | ||
| 856 | if (item.Sid != 0 // by specification | ||
| 857 | && item.Sid != NFatID::kFree) // NFatID::kFree is used in some AAF files | ||
| 858 | return S_FALSE; | ||
| 859 | } | ||
| 860 | // else if (item.Type == NItemType::kRootStorage) return S_FALSE; | ||
| 861 | else if (item.IsEmptyType()) | ||
| 862 | { | ||
| 863 | // kNoDid is expected in *Did fileds, but rare case MSI contains zero in all fields | ||
| 864 | if ((item.Sid != 0 // expected value | ||
| 865 | && item.Sid != NFatID::kFree // NFatID::kFree is used in some AAF files | ||
| 866 | && item.Sid != NFatID::kEndOfChain) // used by some MSI file | ||
| 867 | || (item.LeftDid != kNoDid && item.LeftDid) | ||
| 868 | || (item.RightDid != kNoDid && item.RightDid) | ||
| 869 | || (item.SonDid != kNoDid && item.SonDid) | ||
| 870 | // || item.Size != 0 // the check is disabled because some MSI file contains non zero | ||
| 871 | // || Get16(item.Name) != 0 // the check is disabled because some MSI file contains some name | ||
| 872 | ) | ||
| 873 | return S_FALSE; | ||
| 874 | } | ||
| 875 | else | ||
| 876 | { | ||
| 877 | if (item.Type != NItemType::kStream) | ||
| 878 | return S_FALSE; | ||
| 879 | // NItemType::kStream case | ||
| 880 | if (item.SonDid != kNoDid) // optional check | ||
| 881 | return S_FALSE; | ||
| 882 | if (item.Size == 0) | ||
| 883 | { | ||
| 884 | if (item.Sid != NFatID::kEndOfChain) | ||
| 885 | return S_FALSE; | ||
| 886 | } | ||
| 887 | else if (IsLargeStream(item.Size)) | ||
| 888 | { | ||
| 889 | if (item.Sid >= numFatItems || used[item.Sid]) | ||
| 890 | return S_FALSE; | ||
| 891 | used[item.Sid] = k_Used_ChainTo; | ||
| 892 | } | ||
| 893 | } | ||
| 894 | |||
| 534 | Items.Add(item); | 895 | Items.Add(item); |
| 535 | } | 896 | } |
| 536 | sid = Fat[sid]; | 897 | sid = fat[sid]; |
| 537 | if (sid == NFatID::kEndOfChain) | ||
| 538 | break; | ||
| 539 | } | 898 | } |
| 899 | while (sid != NFatID::kEndOfChain); | ||
| 540 | } | 900 | } |
| 541 | 901 | ||
| 542 | const CItem &root = Items[0]; | ||
| 543 | |||
| 544 | { | 902 | { |
| 903 | // root stream contains all data that stored with mini Sectors | ||
| 904 | const CItem &root = Items[0]; | ||
| 545 | UInt32 numSectorsInMiniStream; | 905 | UInt32 numSectorsInMiniStream; |
| 546 | { | 906 | { |
| 547 | UInt64 numSatSects64 = (root.Size + sectSize - 1) >> sectorSizeBits; | 907 | const UInt64 numSatSects64 = (root.Size + sectSize - 1) >> sectorSizeBits; |
| 548 | if (numSatSects64 > NFatID::kMaxValue) | 908 | if (numSatSects64 > NFatID::kMaxValue + 1) |
| 549 | return S_FALSE; | 909 | return S_FALSE; |
| 550 | numSectorsInMiniStream = (UInt32)numSatSects64; | 910 | numSectorsInMiniStream = (UInt32)numSatSects64; |
| 551 | } | 911 | } |
| 552 | NumSectorsInMiniStream = numSectorsInMiniStream; | ||
| 553 | MiniSids.Alloc(numSectorsInMiniStream); | ||
| 554 | { | 912 | { |
| 555 | UInt64 matSize64 = (root.Size + ((UInt64)1 << miniSectorSizeBits) - 1) >> miniSectorSizeBits; | 913 | const UInt64 matSize64 = (root.Size + (1 << k_MiniSectorSizeBits) - 1) >> k_MiniSectorSizeBits; |
| 556 | if (matSize64 > NFatID::kMaxValue) | 914 | if (matSize64 > numMatItems) |
| 557 | return S_FALSE; | 915 | return S_FALSE; |
| 558 | MatSize = (UInt32)matSize64; | 916 | MatSize = (UInt32)matSize64; |
| 559 | if (numMatItems < MatSize) | ||
| 560 | return S_FALSE; | ||
| 561 | } | 917 | } |
| 562 | 918 | MiniSids.Alloc(numSectorsInMiniStream); | |
| 919 | UInt32 * const miniSids = MiniSids; | ||
| 563 | UInt32 sid = root.Sid; | 920 | UInt32 sid = root.Sid; |
| 564 | for (UInt32 i = 0; ; i++) | 921 | for (UInt32 i = 0; ; i++) |
| 565 | { | 922 | { |
| @@ -571,95 +928,186 @@ HRESULT CDatabase::Open(IInStream *inStream) | |||
| 571 | } | 928 | } |
| 572 | if (i >= numSectorsInMiniStream) | 929 | if (i >= numSectorsInMiniStream) |
| 573 | return S_FALSE; | 930 | return S_FALSE; |
| 574 | MiniSids[i] = sid; | ||
| 575 | if (sid >= numFatItems) | 931 | if (sid >= numFatItems) |
| 576 | return S_FALSE; | 932 | return S_FALSE; |
| 577 | sid = Fat[sid]; | 933 | miniSids[i] = sid; |
| 934 | sid = fat[sid]; | ||
| 578 | } | 935 | } |
| 936 | NumSectors_in_MiniStream = numSectorsInMiniStream; | ||
| 579 | } | 937 | } |
| 580 | 938 | ||
| 581 | RINOK(AddNode(-1, root.SonDid)) | 939 | |
| 582 | |||
| 583 | unsigned numCabs = 0; | ||
| 584 | |||
| 585 | FOR_VECTOR (i, Refs) | ||
| 586 | { | 940 | { |
| 587 | const CItem &item = Items[Refs[i].Did]; | 941 | /* |
| 588 | if (item.IsDir() || numCabs > 1) | 942 | MS DOCs: |
| 589 | continue; | 943 | The range lock sector covers file offsets 0x7FFFFF00-0x7FFFFFFF. |
| 590 | bool isMsiName; | 944 | These offsets are reserved for byte-range locking to support |
| 591 | const UString msiName = ConvertName(item.Name, isMsiName); | 945 | concurrency, transactions, and other compound file features. |
| 592 | if (isMsiName && !msiName.IsEmpty()) | 946 | The range lock sector MUST be allocated in the FAT and marked with |
| 593 | { | 947 | ENDOFCHAIN (0xFFFFFFFE), when the compound file grows beyond 2 GB. |
| 594 | // bool isThereExt = (msiName.Find(L'.') >= 0); | 948 | If the compound file is greater than 2 GB and then shrinks to below 2 GB, |
| 595 | bool isMsiSpec = (msiName[0] == k_Msi_SpecChar); | 949 | the range lock sector SHOULD be marked as FREESECT (0xFFFFFFFF) in the FAT. |
| 596 | if ((msiName.Len() >= 4 && StringsAreEqualNoCase_Ascii(msiName.RightPtr(4), ".cab")) | 950 | */ |
| 597 | || (!isMsiSpec && msiName.Len() >= 3 && StringsAreEqualNoCase_Ascii(msiName.RightPtr(3), "exe")) | 951 | { |
| 598 | // || (!isMsiSpec && !isThereExt) | 952 | const UInt32 lockSector = (0x7fffffff >> sectorSizeBits) - 1; |
| 599 | ) | 953 | if (lockSector < numFatItems) |
| 600 | { | 954 | { |
| 601 | numCabs++; | 955 | if (used[lockSector]) |
| 602 | MainSubfile = (int)i; | 956 | return S_FALSE; |
| 957 | const UInt32 f = fat[lockSector]; | ||
| 958 | if (f == NFatID::kEndOfChain) | ||
| 959 | used[lockSector] = k_Used_ChainTo; // we use fake state to pass the check in loop below | ||
| 960 | else if (f != NFatID::kFree) | ||
| 961 | return S_FALSE; | ||
| 603 | } | 962 | } |
| 604 | } | 963 | } |
| 964 | for (size_t i = 0; i < numFatItems; i++) | ||
| 965 | { | ||
| 966 | UInt32 f = fat[i]; | ||
| 967 | const UInt32 u = ~(UInt32)used[i]; // (0xffffffff - used[i]) | ||
| 968 | if (f < NFatID::kMaxValue + 1) | ||
| 969 | f = NFatID::kEndOfChain; | ||
| 970 | if (f != u) | ||
| 971 | return S_FALSE; | ||
| 972 | } | ||
| 605 | } | 973 | } |
| 606 | |||
| 607 | if (numCabs > 1) | ||
| 608 | MainSubfile = -1; | ||
| 609 | 974 | ||
| 610 | { | 975 | { |
| 611 | FOR_VECTOR (t, Items) | 976 | // Don't move that code up, becase Check_Item uses Mat[] array. |
| 977 | FOR_VECTOR(t, Items) | ||
| 612 | { | 978 | { |
| 613 | Update_PhySize_WithItem(t); | 979 | RINOK(Check_Item(t)) |
| 614 | } | 980 | } |
| 615 | } | 981 | } |
| 982 | |||
| 983 | RINOK(AddNodes()) | ||
| 984 | |||
| 985 | { | ||
| 986 | // some msi (in rare cases) have unaligned size of archive, | ||
| 987 | // unaligned size of compond files is also possible if we create just one stream | ||
| 988 | // where there is no padding data after payload data in last cluster of archive | ||
| 989 | UInt64 fileSize; | ||
| 990 | RINOK(InStream_GetSize_SeekToEnd(inStream, fileSize)) | ||
| 991 | if ( fileSize < PhySize | ||
| 992 | && fileSize > PhySize - sectSize | ||
| 993 | && fileSize >= PhySize_Unaligned | ||
| 994 | && PhySize_Unaligned > PhySize - sectSize) | ||
| 995 | PhySize = PhySize_Unaligned; | ||
| 996 | } | ||
| 997 | |||
| 998 | bool isMsi = false; | ||
| 616 | { | 999 | { |
| 617 | if (PhySize != PhySize_Aligned) | 1000 | FOR_VECTOR (i, Refs) |
| 618 | { | 1001 | { |
| 619 | /* some msi (in rare cases) have unaligned size of archive, | 1002 | const CItem &item = Items[Refs[i].Did]; |
| 620 | where there is no padding data after payload data in last cluster of archive */ | 1003 | if (item.IsDir()) |
| 621 | UInt64 fileSize; | 1004 | continue; |
| 622 | RINOK(InStream_GetSize_SeekToEnd(inStream, fileSize)) | 1005 | if (item.AreMsiChars()) |
| 623 | if (PhySize != fileSize) | 1006 | // if (item.IsSpecMsiName()) |
| 624 | PhySize = PhySize_Aligned; | 1007 | { |
| 1008 | isMsi = true; | ||
| 1009 | break; | ||
| 1010 | } | ||
| 625 | } | 1011 | } |
| 626 | } | 1012 | } |
| 1013 | |||
| 1014 | // IsMsi = isMsi; | ||
| 1015 | if (isMsi) | ||
| 627 | { | 1016 | { |
| 628 | FOR_VECTOR (t, Items) | 1017 | unsigned numCabs = 0; |
| 1018 | UString name; | ||
| 1019 | FOR_VECTOR (i, Refs) | ||
| 629 | { | 1020 | { |
| 630 | const CItem &item = Items[t]; | 1021 | const CItem &item = Items[Refs[i].Did]; |
| 631 | 1022 | if (item.IsDir() /* || item.IsSpecMsiName() */) | |
| 632 | if (IsMsiName(item.Name)) | 1023 | continue; |
| 1024 | MsiName_To_FileName(item.Name, name); | ||
| 1025 | if ( (name.Len() >= 4 && StringsAreEqualNoCase_Ascii(name.RightPtr(4), ".cab")) | ||
| 1026 | || (name.Len() >= 3 && StringsAreEqualNoCase_Ascii(name.RightPtr(3), "exe")) | ||
| 1027 | ) | ||
| 633 | { | 1028 | { |
| 634 | Type = k_Type_Msi; | 1029 | numCabs++; |
| 635 | if (memcmp(item.Name, kMspSequence, kMspSequence_Size) == 0) | 1030 | if (numCabs > 1) |
| 636 | { | 1031 | { |
| 637 | Type = k_Type_Msp; | 1032 | MainSubfile = -1; |
| 638 | break; | 1033 | break; |
| 639 | } | 1034 | } |
| 640 | continue; | 1035 | MainSubfile = (int)i; |
| 641 | } | ||
| 642 | if (AreEqualNames(item.Name, "WordDocument")) | ||
| 643 | { | ||
| 644 | Type = k_Type_Doc; | ||
| 645 | break; | ||
| 646 | } | 1036 | } |
| 647 | if (AreEqualNames(item.Name, "PowerPoint Document")) | 1037 | } |
| 1038 | } | ||
| 1039 | |||
| 1040 | if (isMsi) // we provide msi priority over AAF | ||
| 1041 | Type = k_Type_Msi; | ||
| 1042 | if (Type != k_Type_Aaf) | ||
| 1043 | { | ||
| 1044 | FOR_VECTOR (i, Refs) | ||
| 1045 | { | ||
| 1046 | const CItem &item = Items[Refs[i].Did]; | ||
| 1047 | if (item.IsDir()) | ||
| 1048 | continue; | ||
| 1049 | const Byte *name = item.Name; | ||
| 1050 | // if (IsMsiName(name)) | ||
| 1051 | if (isMsi) | ||
| 648 | { | 1052 | { |
| 649 | Type = k_Type_Ppt; | 1053 | if (memcmp(name, k_Sequence_msp, sizeof(k_Sequence_msp)) == 0) |
| 650 | break; | 1054 | { |
| 1055 | Type = k_Type_Msp; | ||
| 1056 | break; | ||
| 1057 | } | ||
| 1058 | if (memcmp(name, k_Sequence_msm, sizeof(k_Sequence_msm)) == 0) | ||
| 1059 | { | ||
| 1060 | Type = k_Type_Msm; | ||
| 1061 | break; | ||
| 1062 | } | ||
| 651 | } | 1063 | } |
| 652 | if (AreEqualNames(item.Name, "Workbook")) | 1064 | else |
| 653 | { | 1065 | { |
| 654 | Type = k_Type_Xls; | 1066 | if (AreEqualNames(name, "WordDocument")) |
| 655 | break; | 1067 | { |
| 1068 | Type = k_Type_Doc; | ||
| 1069 | break; | ||
| 1070 | } | ||
| 1071 | if (AreEqualNames(name, "PowerPoint Document")) | ||
| 1072 | { | ||
| 1073 | Type = k_Type_Ppt; | ||
| 1074 | break; | ||
| 1075 | } | ||
| 1076 | if (AreEqualNames(name, "Workbook")) | ||
| 1077 | { | ||
| 1078 | Type = k_Type_Xls; | ||
| 1079 | break; | ||
| 1080 | } | ||
| 656 | } | 1081 | } |
| 657 | } | 1082 | } |
| 658 | } | 1083 | } |
| 659 | 1084 | ||
| 1085 | #ifdef Z7_COMPOUND_SHOW_DELETED | ||
| 1086 | { | ||
| 1087 | // we skip Items[0] that is root item | ||
| 1088 | for (unsigned t = 1; t < Items.Size(); t++) | ||
| 1089 | { | ||
| 1090 | const CItem &item = Items[t]; | ||
| 1091 | if ( | ||
| 1092 | #if 1 // 0 for debug to show empty files | ||
| 1093 | item.IsEmptyType() || | ||
| 1094 | #endif | ||
| 1095 | !item.IsLevel_Unused()) | ||
| 1096 | continue; | ||
| 1097 | CRef ref; | ||
| 1098 | ref.Parent = k_Ref_Parent_Root; | ||
| 1099 | ref.Did = t; | ||
| 1100 | Refs.Add(ref); | ||
| 1101 | } | ||
| 1102 | } | ||
| 1103 | #endif | ||
| 1104 | |||
| 1105 | HeadersError = false; | ||
| 660 | return S_OK; | 1106 | return S_OK; |
| 661 | } | 1107 | } |
| 662 | 1108 | ||
| 1109 | |||
| 1110 | |||
| 663 | Z7_CLASS_IMP_CHandler_IInArchive_1( | 1111 | Z7_CLASS_IMP_CHandler_IInArchive_1( |
| 664 | IInArchiveGetStream | 1112 | IInArchiveGetStream |
| 665 | ) | 1113 | ) |
| @@ -674,13 +1122,15 @@ static const Byte kProps[] = | |||
| 674 | kpidPackSize, | 1122 | kpidPackSize, |
| 675 | kpidCTime, | 1123 | kpidCTime, |
| 676 | kpidMTime | 1124 | kpidMTime |
| 1125 | // , kpidCharacts // for debug | ||
| 677 | }; | 1126 | }; |
| 678 | 1127 | ||
| 679 | static const Byte kArcProps[] = | 1128 | static const Byte kArcProps[] = |
| 680 | { | 1129 | { |
| 681 | kpidExtension, | 1130 | kpidExtension, |
| 682 | kpidClusterSize, | 1131 | kpidClusterSize |
| 683 | kpidSectorSize | 1132 | // , kpidSectorSize |
| 1133 | // , kpidFreeSpace | ||
| 684 | }; | 1134 | }; |
| 685 | 1135 | ||
| 686 | IMP_IInArchive_Props | 1136 | IMP_IInArchive_Props |
| @@ -695,9 +1145,20 @@ Z7_COM7F_IMF(CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value)) | |||
| 695 | case kpidExtension: prop = kExtensions[(unsigned)_db.Type]; break; | 1145 | case kpidExtension: prop = kExtensions[(unsigned)_db.Type]; break; |
| 696 | case kpidPhySize: prop = _db.PhySize; break; | 1146 | case kpidPhySize: prop = _db.PhySize; break; |
| 697 | case kpidClusterSize: prop = (UInt32)1 << _db.SectorSizeBits; break; | 1147 | case kpidClusterSize: prop = (UInt32)1 << _db.SectorSizeBits; break; |
| 698 | case kpidSectorSize: prop = (UInt32)1 << _db.MiniSectorSizeBits; break; | 1148 | // case kpidSectorSize: prop = (UInt32)1 << _db.MiniSectorSizeBits; break; |
| 699 | case kpidMainSubfile: if (_db.MainSubfile >= 0) prop = (UInt32)_db.MainSubfile; break; | 1149 | case kpidMainSubfile: if (_db.MainSubfile >= 0) prop = (UInt32)_db.MainSubfile; break; |
| 1150 | // case kpidFreeSpace: prop = _db.FreeSize; break; | ||
| 700 | case kpidIsNotArcType: if (_db.IsNotArcType()) prop = true; break; | 1151 | case kpidIsNotArcType: if (_db.IsNotArcType()) prop = true; break; |
| 1152 | case kpidErrorFlags: | ||
| 1153 | { | ||
| 1154 | UInt32 v = 0; | ||
| 1155 | if (!_db.IsArc) | ||
| 1156 | v |= kpv_ErrorFlags_IsNotArc; | ||
| 1157 | if (_db.HeadersError) | ||
| 1158 | v |= kpv_ErrorFlags_HeadersError; | ||
| 1159 | prop = v; | ||
| 1160 | break; | ||
| 1161 | } | ||
| 701 | } | 1162 | } |
| 702 | prop.Detach(value); | 1163 | prop.Detach(value); |
| 703 | return S_OK; | 1164 | return S_OK; |
| @@ -719,6 +1180,7 @@ Z7_COM7F_IMF(CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *val | |||
| 719 | case kpidMTime: prop = item.MTime; break; | 1180 | case kpidMTime: prop = item.MTime; break; |
| 720 | case kpidPackSize: if (!item.IsDir()) prop = _db.GetItemPackSize(item.Size); break; | 1181 | case kpidPackSize: if (!item.IsDir()) prop = _db.GetItemPackSize(item.Size); break; |
| 721 | case kpidSize: if (!item.IsDir()) prop = item.Size; break; | 1182 | case kpidSize: if (!item.IsDir()) prop = item.Size; break; |
| 1183 | // case kpidCharacts: prop = item.Level; break; | ||
| 722 | } | 1184 | } |
| 723 | prop.Detach(value); | 1185 | prop.Detach(value); |
| 724 | return S_OK; | 1186 | return S_OK; |
| @@ -727,17 +1189,17 @@ Z7_COM7F_IMF(CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *val | |||
| 727 | 1189 | ||
| 728 | Z7_COM7F_IMF(CHandler::Open(IInStream *inStream, | 1190 | Z7_COM7F_IMF(CHandler::Open(IInStream *inStream, |
| 729 | const UInt64 * /* maxCheckStartPosition */, | 1191 | const UInt64 * /* maxCheckStartPosition */, |
| 730 | IArchiveOpenCallback * /* openArchiveCallback */)) | 1192 | IArchiveOpenCallback *openArchiveCallback)) |
| 731 | { | 1193 | { |
| 732 | COM_TRY_BEGIN | 1194 | COM_TRY_BEGIN |
| 733 | Close(); | 1195 | Close(); |
| 734 | try | 1196 | _db.OpenCallback = openArchiveCallback; |
| 1197 | // try | ||
| 735 | { | 1198 | { |
| 736 | if (_db.Open(inStream) != S_OK) | 1199 | RINOK(_db.Open(inStream)) |
| 737 | return S_FALSE; | ||
| 738 | _stream = inStream; | 1200 | _stream = inStream; |
| 739 | } | 1201 | } |
| 740 | catch(...) { return S_FALSE; } | 1202 | // catch(...) { return S_FALSE; } |
| 741 | return S_OK; | 1203 | return S_OK; |
| 742 | COM_TRY_END | 1204 | COM_TRY_END |
| 743 | } | 1205 | } |
| @@ -775,52 +1237,57 @@ Z7_COM7F_IMF(CHandler::Extract(const UInt32 *indices, UInt32 numItems, | |||
| 775 | CMyComPtr2_Create<ICompressProgressInfo, CLocalProgress> lps; | 1237 | CMyComPtr2_Create<ICompressProgressInfo, CLocalProgress> lps; |
| 776 | lps->Init(extractCallback, false); | 1238 | lps->Init(extractCallback, false); |
| 777 | 1239 | ||
| 778 | for (i = 0; i < numItems; i++) | 1240 | for (i = 0;; i++) |
| 779 | { | 1241 | { |
| 780 | lps->InSize = totalPackSize; | 1242 | lps->InSize = totalPackSize; |
| 781 | lps->OutSize = totalSize; | 1243 | lps->OutSize = totalSize; |
| 782 | RINOK(lps->SetCur()) | 1244 | RINOK(lps->SetCur()) |
| 1245 | if (i >= numItems) | ||
| 1246 | break; | ||
| 1247 | |||
| 783 | const UInt32 index = allFilesMode ? i : indices[i]; | 1248 | const UInt32 index = allFilesMode ? i : indices[i]; |
| 784 | const CItem &item = _db.Items[_db.Refs[index].Did]; | 1249 | const CItem &item = _db.Items[_db.Refs[index].Did]; |
| 785 | Int32 res; | 1250 | Int32 res; |
| 786 | { | ||
| 787 | CMyComPtr<ISequentialOutStream> outStream; | ||
| 788 | const Int32 askMode = testMode ? | ||
| 789 | NExtract::NAskMode::kTest : | ||
| 790 | NExtract::NAskMode::kExtract; | ||
| 791 | RINOK(extractCallback->GetStream(index, &outStream, askMode)) | ||
| 792 | |||
| 793 | if (item.IsDir()) | ||
| 794 | { | 1251 | { |
| 1252 | CMyComPtr<ISequentialOutStream> outStream; | ||
| 1253 | const Int32 askMode = testMode ? | ||
| 1254 | NExtract::NAskMode::kTest : | ||
| 1255 | NExtract::NAskMode::kExtract; | ||
| 1256 | RINOK(extractCallback->GetStream(index, &outStream, askMode)) | ||
| 1257 | |||
| 1258 | if (item.IsDir()) | ||
| 1259 | { | ||
| 1260 | RINOK(extractCallback->PrepareOperation(askMode)) | ||
| 1261 | RINOK(extractCallback->SetOperationResult(NExtract::NOperationResult::kOK)) | ||
| 1262 | continue; | ||
| 1263 | } | ||
| 1264 | |||
| 1265 | totalPackSize += _db.GetItemPackSize(item.Size); | ||
| 1266 | totalSize += item.Size; | ||
| 1267 | |||
| 1268 | if (!testMode && !outStream) | ||
| 1269 | continue; | ||
| 795 | RINOK(extractCallback->PrepareOperation(askMode)) | 1270 | RINOK(extractCallback->PrepareOperation(askMode)) |
| 796 | RINOK(extractCallback->SetOperationResult(NExtract::NOperationResult::kOK)) | ||
| 797 | continue; | ||
| 798 | } | ||
| 799 | |||
| 800 | totalPackSize += _db.GetItemPackSize(item.Size); | ||
| 801 | totalSize += item.Size; | ||
| 802 | |||
| 803 | if (!testMode && !outStream) | ||
| 804 | continue; | ||
| 805 | RINOK(extractCallback->PrepareOperation(askMode)) | ||
| 806 | res = NExtract::NOperationResult::kDataError; | ||
| 807 | CMyComPtr<ISequentialInStream> inStream; | ||
| 808 | HRESULT hres = GetStream(index, &inStream); | ||
| 809 | if (hres == S_FALSE) | ||
| 810 | res = NExtract::NOperationResult::kDataError; | 1271 | res = NExtract::NOperationResult::kDataError; |
| 811 | else if (hres == E_NOTIMPL) | 1272 | CMyComPtr<ISequentialInStream> inStream; |
| 812 | res = NExtract::NOperationResult::kUnsupportedMethod; | 1273 | const HRESULT hres = GetStream(index, &inStream); |
| 813 | else | 1274 | if (hres == S_FALSE) |
| 814 | { | 1275 | res = NExtract::NOperationResult::kDataError; |
| 815 | RINOK(hres) | 1276 | /* |
| 816 | if (inStream) | 1277 | else if (hres == E_NOTIMPL) |
| 1278 | res = NExtract::NOperationResult::kUnsupportedMethod; | ||
| 1279 | */ | ||
| 1280 | else | ||
| 817 | { | 1281 | { |
| 818 | RINOK(copyCoder.Interface()->Code(inStream, outStream, NULL, NULL, lps)) | 1282 | RINOK(hres) |
| 819 | if (copyCoder->TotalSize == item.Size) | 1283 | if (inStream) |
| 820 | res = NExtract::NOperationResult::kOK; | 1284 | { |
| 1285 | RINOK(copyCoder.Interface()->Code(inStream, outStream, NULL, NULL, lps)) | ||
| 1286 | if (copyCoder->TotalSize == item.Size) | ||
| 1287 | res = NExtract::NOperationResult::kOK; | ||
| 1288 | } | ||
| 821 | } | 1289 | } |
| 822 | } | 1290 | } |
| 823 | } | ||
| 824 | RINOK(extractCallback->SetOperationResult(res)) | 1291 | RINOK(extractCallback->SetOperationResult(res)) |
| 825 | } | 1292 | } |
| 826 | return S_OK; | 1293 | return S_OK; |
| @@ -839,20 +1306,64 @@ Z7_COM7F_IMF(CHandler::GetStream(UInt32 index, ISequentialInStream **stream)) | |||
| 839 | *stream = NULL; | 1306 | *stream = NULL; |
| 840 | const UInt32 itemIndex = _db.Refs[index].Did; | 1307 | const UInt32 itemIndex = _db.Refs[index].Did; |
| 841 | const CItem &item = _db.Items[itemIndex]; | 1308 | const CItem &item = _db.Items[itemIndex]; |
| 1309 | if (item.IsDir()) | ||
| 1310 | return S_FALSE; | ||
| 1311 | const bool isLargeStream = (itemIndex == 0 || IsLargeStream(item.Size)); | ||
| 1312 | if (!isLargeStream) | ||
| 1313 | { | ||
| 1314 | CBufferInStream *streamSpec = new CBufferInStream; | ||
| 1315 | CMyComPtr<IInStream> streamTemp = streamSpec; | ||
| 1316 | |||
| 1317 | UInt32 size = (UInt32)item.Size; | ||
| 1318 | streamSpec->Buf.Alloc(size); | ||
| 1319 | streamSpec->Init(); | ||
| 1320 | |||
| 1321 | UInt32 sid = item.Sid; | ||
| 1322 | Byte *dest = streamSpec->Buf; | ||
| 1323 | |||
| 1324 | UInt64 phyPos = 0; | ||
| 1325 | while (size) | ||
| 1326 | { | ||
| 1327 | if (sid >= _db.MatSize) | ||
| 1328 | return S_FALSE; | ||
| 1329 | const unsigned subBits = _db.SectorSizeBits - k_MiniSectorSizeBits; | ||
| 1330 | const UInt32 fid = sid >> subBits; | ||
| 1331 | if (fid >= _db.NumSectors_in_MiniStream) | ||
| 1332 | return false; | ||
| 1333 | const UInt64 offset = (((UInt64)_db.MiniSids[fid] + 1) << _db.SectorSizeBits) + | ||
| 1334 | ((sid & ((1u << subBits) - 1)) << k_MiniSectorSizeBits); | ||
| 1335 | if (phyPos != offset) | ||
| 1336 | { | ||
| 1337 | RINOK(InStream_SeekSet(_stream, offset)) | ||
| 1338 | phyPos = offset; | ||
| 1339 | } | ||
| 1340 | UInt32 readSize = (UInt32)1 << k_MiniSectorSizeBits; | ||
| 1341 | if (readSize > size) | ||
| 1342 | readSize = size; | ||
| 1343 | RINOK(ReadStream_FALSE(_stream, dest, readSize)) | ||
| 1344 | phyPos += readSize; | ||
| 1345 | dest += readSize; | ||
| 1346 | sid = _db.Mat[sid]; | ||
| 1347 | size -= readSize; | ||
| 1348 | } | ||
| 1349 | if (sid != NFatID::kEndOfChain) | ||
| 1350 | return S_FALSE; | ||
| 1351 | *stream = streamTemp.Detach(); | ||
| 1352 | return S_OK; | ||
| 1353 | } | ||
| 1354 | |||
| 842 | CClusterInStream *streamSpec = new CClusterInStream; | 1355 | CClusterInStream *streamSpec = new CClusterInStream; |
| 843 | CMyComPtr<ISequentialInStream> streamTemp = streamSpec; | 1356 | CMyComPtr<ISequentialInStream> streamTemp = streamSpec; |
| 844 | streamSpec->Stream = _stream; | 1357 | streamSpec->Stream = _stream; |
| 845 | streamSpec->StartOffset = 0; | 1358 | streamSpec->StartOffset = 0; |
| 846 | 1359 | const unsigned bsLog = _db.SectorSizeBits; | |
| 847 | const bool isLargeStream = (itemIndex == 0 || _db.IsLargeStream(item.Size)); | ||
| 848 | const unsigned bsLog = isLargeStream ? _db.SectorSizeBits : _db.MiniSectorSizeBits; | ||
| 849 | streamSpec->BlockSizeLog = bsLog; | 1360 | streamSpec->BlockSizeLog = bsLog; |
| 850 | streamSpec->Size = item.Size; | 1361 | streamSpec->Size = item.Size; |
| 851 | 1362 | ||
| 852 | const UInt32 clusterSize = (UInt32)1 << bsLog; | 1363 | const UInt32 clusterSize = (UInt32)1 << bsLog; |
| 853 | const UInt64 numClusters64 = (item.Size + clusterSize - 1) >> bsLog; | 1364 | const UInt64 numClusters64 = (item.Size + clusterSize - 1) >> bsLog; |
| 854 | if (numClusters64 >= ((UInt32)1 << 31)) | 1365 | if (numClusters64 > _db.FatSize) |
| 855 | return E_NOTIMPL; | 1366 | return S_FALSE; |
| 856 | streamSpec->Vector.ClearAndReserve((unsigned)numClusters64); | 1367 | streamSpec->Vector.ClearAndReserve((unsigned)numClusters64); |
| 857 | UInt32 sid = item.Sid; | 1368 | UInt32 sid = item.Sid; |
| 858 | UInt64 size = item.Size; | 1369 | UInt64 size = item.Size; |
| @@ -861,21 +1372,10 @@ Z7_COM7F_IMF(CHandler::GetStream(UInt32 index, ISequentialInStream **stream)) | |||
| 861 | { | 1372 | { |
| 862 | for (;; size -= clusterSize) | 1373 | for (;; size -= clusterSize) |
| 863 | { | 1374 | { |
| 864 | if (isLargeStream) | 1375 | if (sid >= _db.FatSize) |
| 865 | { | 1376 | return S_FALSE; |
| 866 | if (sid >= _db.FatSize) | 1377 | streamSpec->Vector.AddInReserved(sid + 1); |
| 867 | return S_FALSE; | 1378 | sid = _db.Fat[sid]; |
| 868 | streamSpec->Vector.AddInReserved(sid + 1); | ||
| 869 | sid = _db.Fat[sid]; | ||
| 870 | } | ||
| 871 | else | ||
| 872 | { | ||
| 873 | UInt64 val = 0; | ||
| 874 | if (sid >= _db.MatSize || !_db.GetMiniCluster(sid, val) || val >= (UInt64)1 << 32) | ||
| 875 | return S_FALSE; | ||
| 876 | streamSpec->Vector.AddInReserved((UInt32)val); | ||
| 877 | sid = _db.Mat[sid]; | ||
| 878 | } | ||
| 879 | if (size <= clusterSize) | 1379 | if (size <= clusterSize) |
| 880 | break; | 1380 | break; |
| 881 | } | 1381 | } |
| @@ -889,7 +1389,7 @@ Z7_COM7F_IMF(CHandler::GetStream(UInt32 index, ISequentialInStream **stream)) | |||
| 889 | } | 1389 | } |
| 890 | 1390 | ||
| 891 | REGISTER_ARC_I( | 1391 | REGISTER_ARC_I( |
| 892 | "Compound", "msi msp doc xls ppt", NULL, 0xE5, | 1392 | "Compound", "msi msp msm doc xls ppt aaf", NULL, 0xe5, |
| 893 | kSignature, | 1393 | kSignature, |
| 894 | 0, | 1394 | 0, |
| 895 | 0, | 1395 | 0, |
diff --git a/CPP/7zip/Archive/CpioHandler.cpp b/CPP/7zip/Archive/CpioHandler.cpp index 62184f0..e1d6d81 100644 --- a/CPP/7zip/Archive/CpioHandler.cpp +++ b/CPP/7zip/Archive/CpioHandler.cpp | |||
| @@ -927,7 +927,7 @@ Z7_COM7F_IMF(CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *val | |||
| 927 | { | 927 | { |
| 928 | #ifdef _WIN32 | 928 | #ifdef _WIN32 |
| 929 | UString u; | 929 | UString u; |
| 930 | ConvertUTF8ToUnicode(item.Name, u); | 930 | ConvertUTF8ToUnicode(s, u); |
| 931 | #else | 931 | #else |
| 932 | const UString u = MultiByteToUnicodeString(s, CP_OEMCP); | 932 | const UString u = MultiByteToUnicodeString(s, CP_OEMCP); |
| 933 | #endif | 933 | #endif |
diff --git a/CPP/7zip/Archive/QcowHandler.cpp b/CPP/7zip/Archive/QcowHandler.cpp index b072880..6edf86d 100644 --- a/CPP/7zip/Archive/QcowHandler.cpp +++ b/CPP/7zip/Archive/QcowHandler.cpp | |||
| @@ -482,6 +482,10 @@ HRESULT CHandler::Open2(IInStream *stream, IArchiveOpenCallback *openCallback) | |||
| 482 | if (_phySize < headerSize) | 482 | if (_phySize < headerSize) |
| 483 | _phySize = headerSize; | 483 | _phySize = headerSize; |
| 484 | 484 | ||
| 485 | // we use 32 MiB limit for L1 size, as QEMU with QCOW_MAX_L1_SIZE limit. | ||
| 486 | if (l1Size > (1u << 22)) // if (l1Size > (1u << (sizeof(size_t) * 8 - 4))) | ||
| 487 | return S_FALSE; | ||
| 488 | |||
| 485 | _isArc = true; | 489 | _isArc = true; |
| 486 | { | 490 | { |
| 487 | const UInt64 backOffset = Get64((const Byte *)(const void *)buf64 + 8); | 491 | const UInt64 backOffset = Get64((const Byte *)(const void *)buf64 + 8); |
| @@ -519,7 +523,6 @@ HRESULT CHandler::Open2(IInStream *stream, IArchiveOpenCallback *openCallback) | |||
| 519 | } | 523 | } |
| 520 | CObjArray<UInt64> table64(l1Size); | 524 | CObjArray<UInt64> table64(l1Size); |
| 521 | { | 525 | { |
| 522 | // if ((t1SizeBytes >> 3) != l1Size) return S_FALSE; | ||
| 523 | RINOK(InStream_SeekSet(stream, l1Offset)) | 526 | RINOK(InStream_SeekSet(stream, l1Offset)) |
| 524 | RINOK(ReadStream_FALSE(stream, table64, t1SizeBytes)) | 527 | RINOK(ReadStream_FALSE(stream, table64, t1SizeBytes)) |
| 525 | } | 528 | } |
diff --git a/CPP/7zip/Archive/Rar/Rar5Handler.cpp b/CPP/7zip/Archive/Rar/Rar5Handler.cpp index a639d8b..c15ff52 100644 --- a/CPP/7zip/Archive/Rar/Rar5Handler.cpp +++ b/CPP/7zip/Archive/Rar/Rar5Handler.cpp | |||
| @@ -8,6 +8,7 @@ | |||
| 8 | #include "../../../Common/ComTry.h" | 8 | #include "../../../Common/ComTry.h" |
| 9 | #include "../../../Common/IntToString.h" | 9 | #include "../../../Common/IntToString.h" |
| 10 | #include "../../../Common/MyBuffer2.h" | 10 | #include "../../../Common/MyBuffer2.h" |
| 11 | #include "../../../Common/MyLinux.h" | ||
| 11 | #include "../../../Common/UTFConvert.h" | 12 | #include "../../../Common/UTFConvert.h" |
| 12 | 13 | ||
| 13 | #include "../../../Windows/PropVariantUtils.h" | 14 | #include "../../../Windows/PropVariantUtils.h" |
| @@ -1184,7 +1185,15 @@ HRESULT CUnpacker::Code(const CItem &item, const CItem &lastItem, UInt64 packSiz | |||
| 1184 | 1185 | ||
| 1185 | const UInt64 processedSize = outStream->GetPos(); | 1186 | const UInt64 processedSize = outStream->GetPos(); |
| 1186 | if (res == S_OK && !lastItem.Is_UnknownSize() && processedSize != lastItem.Size) | 1187 | if (res == S_OK && !lastItem.Is_UnknownSize() && processedSize != lastItem.Size) |
| 1187 | res = S_FALSE; | 1188 | { |
| 1189 | // rar_v7.13-: linux archive contains symLink with (packSize == 0 && lastItem.Size != 0) | ||
| 1190 | // v25.02: we ignore such record in rar headers: | ||
| 1191 | if (packSize != 0 | ||
| 1192 | || method != 0 | ||
| 1193 | || lastItem.HostOS != kHost_Unix | ||
| 1194 | || !MY_LIN_S_ISLNK(lastItem.Attrib)) | ||
| 1195 | res = S_FALSE; | ||
| 1196 | } | ||
| 1188 | 1197 | ||
| 1189 | // if (res == S_OK) | 1198 | // if (res == S_OK) |
| 1190 | { | 1199 | { |
diff --git a/CPP/7zip/Archive/Rar/RarHandler.cpp b/CPP/7zip/Archive/Rar/RarHandler.cpp index dfbad33..6c53847 100644 --- a/CPP/7zip/Archive/Rar/RarHandler.cpp +++ b/CPP/7zip/Archive/Rar/RarHandler.cpp | |||
| @@ -7,6 +7,7 @@ | |||
| 7 | #include "../../../Common/ComTry.h" | 7 | #include "../../../Common/ComTry.h" |
| 8 | #include "../../../Common/IntToString.h" | 8 | #include "../../../Common/IntToString.h" |
| 9 | #include "../../../Common/MyBuffer2.h" | 9 | #include "../../../Common/MyBuffer2.h" |
| 10 | #include "../../../Common/MyLinux.h" | ||
| 10 | #include "../../../Common/UTFConvert.h" | 11 | #include "../../../Common/UTFConvert.h" |
| 11 | 12 | ||
| 12 | #include "../../../Windows/PropVariantUtils.h" | 13 | #include "../../../Windows/PropVariantUtils.h" |
| @@ -70,8 +71,14 @@ bool CItem::IsDir() const | |||
| 70 | case NHeader::NFile::kHostMSDOS: | 71 | case NHeader::NFile::kHostMSDOS: |
| 71 | case NHeader::NFile::kHostOS2: | 72 | case NHeader::NFile::kHostOS2: |
| 72 | case NHeader::NFile::kHostWin32: | 73 | case NHeader::NFile::kHostWin32: |
| 73 | if ((Attrib & FILE_ATTRIBUTE_DIRECTORY) != 0) | 74 | if (Attrib & FILE_ATTRIBUTE_DIRECTORY) |
| 74 | return true; | 75 | return true; |
| 76 | break; | ||
| 77 | case NHeader::NFile::kHostUnix: | ||
| 78 | case NHeader::NFile::kHostBeOS: | ||
| 79 | if (MY_LIN_S_ISDIR(Attrib)) | ||
| 80 | return true; | ||
| 81 | break; | ||
| 75 | } | 82 | } |
| 76 | return false; | 83 | return false; |
| 77 | } | 84 | } |
| @@ -86,11 +93,20 @@ UInt32 CItem::GetWinAttrib() const | |||
| 86 | case NHeader::NFile::kHostWin32: | 93 | case NHeader::NFile::kHostWin32: |
| 87 | a = Attrib; | 94 | a = Attrib; |
| 88 | break; | 95 | break; |
| 96 | case NHeader::NFile::kHostUnix: | ||
| 97 | case NHeader::NFile::kHostBeOS: | ||
| 98 | a = Attrib << 16; | ||
| 99 | a |= 0x8000; // add posix mode marker | ||
| 100 | break; | ||
| 101 | // case NHeader::NFile::kHostMacOS: | ||
| 102 | // kHostMacOS was used only by some very old rare case rar. | ||
| 103 | // New rar4-rar7 for macos probably uses kHostUnix. | ||
| 104 | // So we process kHostMacOS without attribute parsing: | ||
| 89 | default: | 105 | default: |
| 90 | a = 0; // must be converted from unix value; | 106 | a = 0; |
| 91 | } | 107 | } |
| 92 | if (IsDir()) | 108 | if (IsDir()) |
| 93 | a |= NHeader::NFile::kWinFileDirectoryAttributeMask; | 109 | a |= FILE_ATTRIBUTE_DIRECTORY; |
| 94 | return a; | 110 | return a; |
| 95 | } | 111 | } |
| 96 | 112 | ||
diff --git a/CPP/7zip/Archive/Tar/TarHandler.cpp b/CPP/7zip/Archive/Tar/TarHandler.cpp index 29f28e8..5761ea3 100644 --- a/CPP/7zip/Archive/Tar/TarHandler.cpp +++ b/CPP/7zip/Archive/Tar/TarHandler.cpp | |||
| @@ -65,7 +65,7 @@ static const Byte kArcProps[] = | |||
| 65 | kpidComment | 65 | kpidComment |
| 66 | }; | 66 | }; |
| 67 | 67 | ||
| 68 | static const char *k_Characts_Prefix = "PREFIX"; | 68 | static const char * const k_Characts_Prefix = "PREFIX"; |
| 69 | 69 | ||
| 70 | IMP_IInArchive_Props | 70 | IMP_IInArchive_Props |
| 71 | IMP_IInArchive_ArcProps | 71 | IMP_IInArchive_ArcProps |
| @@ -684,10 +684,14 @@ Z7_COM7F_IMF(CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *val | |||
| 684 | s.Add_OptSpaced("SCHILY.fflags="); | 684 | s.Add_OptSpaced("SCHILY.fflags="); |
| 685 | s += item->SCHILY_fflags; | 685 | s += item->SCHILY_fflags; |
| 686 | } | 686 | } |
| 687 | if (item->Is_Sparse()) | ||
| 688 | s.Add_OptSpaced("SPARSE"); | ||
| 687 | if (item->IsThereWarning()) | 689 | if (item->IsThereWarning()) |
| 688 | s.Add_OptSpaced("WARNING"); | 690 | s.Add_OptSpaced("WARNING"); |
| 689 | if (item->HeaderError) | 691 | if (item->HeaderError) |
| 690 | s.Add_OptSpaced("ERROR"); | 692 | s.Add_OptSpaced("ERROR"); |
| 693 | if (item->Method_Error) | ||
| 694 | s.Add_OptSpaced("METHOD_ERROR"); | ||
| 691 | if (item->Pax_Error) | 695 | if (item->Pax_Error) |
| 692 | s.Add_OptSpaced("PAX_error"); | 696 | s.Add_OptSpaced("PAX_error"); |
| 693 | if (!item->PaxExtra.RawLines.IsEmpty()) | 697 | if (!item->PaxExtra.RawLines.IsEmpty()) |
| @@ -812,11 +816,16 @@ Z7_COM7F_IMF(CHandler::Extract(const UInt32 *indices, UInt32 numItems, | |||
| 812 | inStream2 = inStream; | 816 | inStream2 = inStream; |
| 813 | else | 817 | else |
| 814 | { | 818 | { |
| 815 | GetStream(index, &inStream2); | 819 | const HRESULT hres = GetStream(index, &inStream2); |
| 816 | if (!inStream2) | 820 | if (hres == E_NOTIMPL) |
| 817 | return E_FAIL; | 821 | opRes = NExtract::NOperationResult::kHeadersError; // kUnsupportedMethod |
| 822 | else if (!inStream2) | ||
| 823 | { | ||
| 824 | opRes = NExtract::NOperationResult::kDataError; | ||
| 825 | // return E_FAIL; | ||
| 826 | } | ||
| 818 | } | 827 | } |
| 819 | 828 | if (opRes == NExtract::NOperationResult::kOK) | |
| 820 | { | 829 | { |
| 821 | if (item->Is_SymLink()) | 830 | if (item->Is_SymLink()) |
| 822 | { | 831 | { |
| @@ -855,9 +864,9 @@ Z7_CLASS_IMP_IInStream( | |||
| 855 | bool _needStartSeek; | 864 | bool _needStartSeek; |
| 856 | 865 | ||
| 857 | public: | 866 | public: |
| 867 | unsigned ItemIndex; | ||
| 858 | CHandler *Handler; | 868 | CHandler *Handler; |
| 859 | CMyComPtr<IUnknown> HandlerRef; | 869 | CMyComPtr<IUnknown> HandlerRef; |
| 860 | unsigned ItemIndex; | ||
| 861 | CRecordVector<UInt64> PhyOffsets; | 870 | CRecordVector<UInt64> PhyOffsets; |
| 862 | 871 | ||
| 863 | void Init() | 872 | void Init() |
| @@ -879,7 +888,7 @@ Z7_COM7F_IMF(CSparseStream::Read(void *data, UInt32 size, UInt32 *processedSize) | |||
| 879 | if (_virtPos >= item.Size) | 888 | if (_virtPos >= item.Size) |
| 880 | return S_OK; | 889 | return S_OK; |
| 881 | { | 890 | { |
| 882 | UInt64 rem = item.Size - _virtPos; | 891 | const UInt64 rem = item.Size - _virtPos; |
| 883 | if (size > rem) | 892 | if (size > rem) |
| 884 | size = (UInt32)rem; | 893 | size = (UInt32)rem; |
| 885 | } | 894 | } |
| @@ -903,17 +912,17 @@ Z7_COM7F_IMF(CSparseStream::Read(void *data, UInt32 size, UInt32 *processedSize) | |||
| 903 | } | 912 | } |
| 904 | 913 | ||
| 905 | const CSparseBlock &sb = item.SparseBlocks[left]; | 914 | const CSparseBlock &sb = item.SparseBlocks[left]; |
| 906 | UInt64 relat = _virtPos - sb.Offset; | 915 | const UInt64 relat = _virtPos - sb.Offset; |
| 907 | 916 | ||
| 908 | if (_virtPos >= sb.Offset && relat < sb.Size) | 917 | if (_virtPos >= sb.Offset && relat < sb.Size) |
| 909 | { | 918 | { |
| 910 | UInt64 rem = sb.Size - relat; | 919 | const UInt64 rem = sb.Size - relat; |
| 911 | if (size > rem) | 920 | if (size > rem) |
| 912 | size = (UInt32)rem; | 921 | size = (UInt32)rem; |
| 913 | UInt64 phyPos = PhyOffsets[left] + relat; | 922 | const UInt64 phyPos = PhyOffsets[left] + relat; |
| 914 | if (_needStartSeek || _phyPos != phyPos) | 923 | if (_needStartSeek || _phyPos != phyPos) |
| 915 | { | 924 | { |
| 916 | RINOK(InStream_SeekSet(Handler->_stream, (item.Get_DataPos() + phyPos))) | 925 | RINOK(InStream_SeekSet(Handler->_stream, item.Get_DataPos() + phyPos)) |
| 917 | _needStartSeek = false; | 926 | _needStartSeek = false; |
| 918 | _phyPos = phyPos; | 927 | _phyPos = phyPos; |
| 919 | } | 928 | } |
| @@ -927,7 +936,7 @@ Z7_COM7F_IMF(CSparseStream::Read(void *data, UInt32 size, UInt32 *processedSize) | |||
| 927 | next = sb.Offset; | 936 | next = sb.Offset; |
| 928 | else if (left + 1 < item.SparseBlocks.Size()) | 937 | else if (left + 1 < item.SparseBlocks.Size()) |
| 929 | next = item.SparseBlocks[left + 1].Offset; | 938 | next = item.SparseBlocks[left + 1].Offset; |
| 930 | UInt64 rem = next - _virtPos; | 939 | const UInt64 rem = next - _virtPos; |
| 931 | if (size > rem) | 940 | if (size > rem) |
| 932 | size = (UInt32)rem; | 941 | size = (UInt32)rem; |
| 933 | memset(data, 0, size); | 942 | memset(data, 0, size); |
| @@ -965,6 +974,8 @@ Z7_COM7F_IMF(CHandler::GetStream(UInt32 index, ISequentialInStream **stream)) | |||
| 965 | 974 | ||
| 966 | if (item.Is_Sparse()) | 975 | if (item.Is_Sparse()) |
| 967 | { | 976 | { |
| 977 | if (item.Method_Error) | ||
| 978 | return E_NOTIMPL; // S_FALSE | ||
| 968 | CSparseStream *streamSpec = new CSparseStream; | 979 | CSparseStream *streamSpec = new CSparseStream; |
| 969 | CMyComPtr<IInStream> streamTemp = streamSpec; | 980 | CMyComPtr<IInStream> streamTemp = streamSpec; |
| 970 | streamSpec->Init(); | 981 | streamSpec->Init(); |
diff --git a/CPP/7zip/Archive/Tar/TarIn.cpp b/CPP/7zip/Archive/Tar/TarIn.cpp index 22b8902..e702b68 100644 --- a/CPP/7zip/Archive/Tar/TarIn.cpp +++ b/CPP/7zip/Archive/Tar/TarIn.cpp | |||
| @@ -181,6 +181,7 @@ HRESULT CArchive::GetNextItemReal(CItemEx &item) | |||
| 181 | { | 181 | { |
| 182 | char buf[NFileHeader::kRecordSize]; | 182 | char buf[NFileHeader::kRecordSize]; |
| 183 | 183 | ||
| 184 | item.Method_Error = false; | ||
| 184 | error = k_ErrorType_OK; | 185 | error = k_ErrorType_OK; |
| 185 | filled = false; | 186 | filled = false; |
| 186 | 187 | ||
| @@ -218,10 +219,7 @@ HRESULT CArchive::GetNextItemReal(CItemEx &item) | |||
| 218 | break; | 219 | break; |
| 219 | item.HeaderSize += NFileHeader::kRecordSize; | 220 | item.HeaderSize += NFileHeader::kRecordSize; |
| 220 | thereAreEmptyRecords = true; | 221 | thereAreEmptyRecords = true; |
| 221 | if (OpenCallback) | 222 | RINOK(Progress(item, 0)) |
| 222 | { | ||
| 223 | RINOK(Progress(item, 0)) | ||
| 224 | } | ||
| 225 | } | 223 | } |
| 226 | if (thereAreEmptyRecords) | 224 | if (thereAreEmptyRecords) |
| 227 | { | 225 | { |
| @@ -335,84 +333,83 @@ HRESULT CArchive::GetNextItemReal(CItemEx &item) | |||
| 335 | 333 | ||
| 336 | if (item.LinkFlag == NFileHeader::NLinkFlag::kSparse) | 334 | if (item.LinkFlag == NFileHeader::NLinkFlag::kSparse) |
| 337 | { | 335 | { |
| 338 | Byte isExtended = (Byte)buf[482]; | 336 | // OLD GNU format: parse sparse file information: |
| 339 | if (isExtended != 0 && isExtended != 1) | 337 | // PackSize = cumulative size of all non-empty blocks of the file. |
| 340 | return S_OK; | 338 | // We read actual file size from 'realsize' member of oldgnu_header: |
| 341 | RIF(ParseSize(buf + 483, item.Size, item.Size_IsBin)) | 339 | RIF(ParseSize(buf + 483, item.Size, item.Size_IsBin)) |
| 342 | UInt64 min = 0; | 340 | if (item.Size < item.PackSize) // additional check |
| 343 | for (unsigned i = 0; i < 4; i++) | ||
| 344 | { | ||
| 345 | p = buf + 386 + 24 * i; | ||
| 346 | if (GetBe32(p) == 0) | ||
| 347 | { | ||
| 348 | if (isExtended != 0) | ||
| 349 | return S_OK; | ||
| 350 | break; | ||
| 351 | } | ||
| 352 | CSparseBlock sb; | ||
| 353 | RIF(ParseSize(p, sb.Offset)) | ||
| 354 | RIF(ParseSize(p + 12, sb.Size)) | ||
| 355 | item.SparseBlocks.Add(sb); | ||
| 356 | if (sb.Offset < min || sb.Offset > item.Size) | ||
| 357 | return S_OK; | ||
| 358 | if ((sb.Offset & 0x1FF) != 0 || (sb.Size & 0x1FF) != 0) | ||
| 359 | return S_OK; | ||
| 360 | min = sb.Offset + sb.Size; | ||
| 361 | if (min < sb.Offset) | ||
| 362 | return S_OK; | ||
| 363 | } | ||
| 364 | if (min > item.Size) | ||
| 365 | return S_OK; | 341 | return S_OK; |
| 366 | 342 | ||
| 367 | while (isExtended != 0) | 343 | p = buf + 386; |
| 368 | { | 344 | |
| 369 | size_t processedSize = NFileHeader::kRecordSize; | 345 | UInt64 end = 0, packSum = 0; |
| 370 | RINOK(ReadStream(SeqStream, buf, &processedSize)) | 346 | unsigned numRecords = 4; |
| 371 | if (processedSize != NFileHeader::kRecordSize) | 347 | unsigned isExtended = (Byte)p[4 * 24]; // (Byte)p[numRecords * 24]; |
| 372 | { | 348 | // the list of blocks contains non-empty blocks. All another data is empty. |
| 373 | error = k_ErrorType_UnexpectedEnd; | ||
| 374 | return S_OK; | ||
| 375 | } | ||
| 376 | |||
| 377 | item.HeaderSize += NFileHeader::kRecordSize; | ||
| 378 | |||
| 379 | if (OpenCallback) | ||
| 380 | { | ||
| 381 | RINOK(Progress(item, 0)) | ||
| 382 | } | ||
| 383 | 349 | ||
| 384 | isExtended = (Byte)buf[21 * 24]; | 350 | for (;;) |
| 385 | if (isExtended != 0 && isExtended != 1) | 351 | { |
| 352 | // const unsigned isExtended = (Byte)p[numRecords * 24]; | ||
| 353 | if (isExtended > 1) | ||
| 386 | return S_OK; | 354 | return S_OK; |
| 387 | for (unsigned i = 0; i < 21; i++) | 355 | do |
| 388 | { | 356 | { |
| 389 | p = buf + 24 * i; | ||
| 390 | if (GetBe32(p) == 0) | 357 | if (GetBe32(p) == 0) |
| 391 | { | 358 | { |
| 392 | if (isExtended != 0) | 359 | if (isExtended) |
| 393 | return S_OK; | 360 | return S_OK; |
| 394 | break; | 361 | break; |
| 395 | } | 362 | } |
| 396 | CSparseBlock sb; | 363 | CSparseBlock sb; |
| 397 | RIF(ParseSize(p, sb.Offset)) | 364 | RIF(ParseSize(p, sb.Offset)) |
| 398 | RIF(ParseSize(p + 12, sb.Size)) | 365 | RIF(ParseSize(p + 12, sb.Size)) |
| 399 | item.SparseBlocks.Add(sb); | 366 | p += 24; |
| 400 | if (sb.Offset < min || sb.Offset > item.Size) | 367 | /* for all non-last blocks we expect : |
| 401 | return S_OK; | 368 | ((sb.Size & 0x1ff) == 0) && ((sb.Offset & 0x1ff) == 0) |
| 402 | if ((sb.Offset & 0x1FF) != 0 || (sb.Size & 0x1FF) != 0) | 369 | for last block : (sb.Size == 0) is possible. |
| 403 | return S_OK; | 370 | */ |
| 404 | min = sb.Offset + sb.Size; | 371 | if (sb.Offset < end |
| 405 | if (min < sb.Offset) | 372 | || item.Size < sb.Offset |
| 373 | || item.Size - sb.Offset < sb.Size) | ||
| 406 | return S_OK; | 374 | return S_OK; |
| 375 | // optional check: | ||
| 376 | if (sb.Size && ((end & 0x1ff) || (sb.Offset & 0x1ff))) | ||
| 377 | { | ||
| 378 | item.Method_Error = true; // relaxed check | ||
| 379 | // return S_OK; | ||
| 380 | } | ||
| 381 | end = sb.Offset + sb.Size; | ||
| 382 | packSum += sb.Size; | ||
| 383 | item.SparseBlocks.Add(sb); | ||
| 384 | } | ||
| 385 | while (--numRecords); | ||
| 386 | |||
| 387 | if (!isExtended) | ||
| 388 | break; | ||
| 389 | |||
| 390 | size_t processedSize = NFileHeader::kRecordSize; | ||
| 391 | RINOK(ReadStream(SeqStream, buf, &processedSize)) | ||
| 392 | if (processedSize != NFileHeader::kRecordSize) | ||
| 393 | { | ||
| 394 | error = k_ErrorType_UnexpectedEnd; | ||
| 395 | return S_OK; | ||
| 407 | } | 396 | } |
| 397 | item.HeaderSize += NFileHeader::kRecordSize; | ||
| 398 | RINOK(Progress(item, 0)) | ||
| 399 | p = buf; | ||
| 400 | numRecords = 21; | ||
| 401 | isExtended = (Byte)p[21 * 24]; // (Byte)p[numRecords * 24]; | ||
| 402 | } | ||
| 403 | // optional checks for strict size consistency: | ||
| 404 | if (end != item.Size || packSum != item.PackSize) | ||
| 405 | { | ||
| 406 | item.Method_Error = true; // relaxed check | ||
| 407 | // return S_OK; | ||
| 408 | } | 408 | } |
| 409 | if (min > item.Size) | ||
| 410 | return S_OK; | ||
| 411 | } | 409 | } |
| 412 | 410 | ||
| 413 | if (item.PackSize >= (UInt64)1 << 63) | 411 | if (item.PackSize >= (UInt64)1 << 63) // optional check. It was checked in ParseSize() already |
| 414 | return S_OK; | 412 | return S_OK; |
| 415 | |||
| 416 | filled = true; | 413 | filled = true; |
| 417 | error = k_ErrorType_OK; | 414 | error = k_ErrorType_OK; |
| 418 | return S_OK; | 415 | return S_OK; |
| @@ -421,6 +418,8 @@ HRESULT CArchive::GetNextItemReal(CItemEx &item) | |||
| 421 | 418 | ||
| 422 | HRESULT CArchive::Progress(const CItemEx &item, UInt64 posOffset) | 419 | HRESULT CArchive::Progress(const CItemEx &item, UInt64 posOffset) |
| 423 | { | 420 | { |
| 421 | if (!OpenCallback) | ||
| 422 | return S_OK; | ||
| 424 | const UInt64 pos = item.Get_DataPos() + posOffset; | 423 | const UInt64 pos = item.Get_DataPos() + posOffset; |
| 425 | if (NumFiles - NumFiles_Prev < (1 << 16) | 424 | if (NumFiles - NumFiles_Prev < (1 << 16) |
| 426 | // && NumRecords - NumRecords_Prev < (1 << 16) | 425 | // && NumRecords - NumRecords_Prev < (1 << 16) |
| @@ -500,10 +499,7 @@ HRESULT CArchive::ReadDataToBuffer(const CItemEx &item, | |||
| 500 | 499 | ||
| 501 | do | 500 | do |
| 502 | { | 501 | { |
| 503 | if (OpenCallback) | 502 | RINOK(Progress(item, pos)) |
| 504 | { | ||
| 505 | RINOK(Progress(item, pos)) | ||
| 506 | } | ||
| 507 | 503 | ||
| 508 | unsigned size = kBufSize; | 504 | unsigned size = kBufSize; |
| 509 | if (size > packSize) | 505 | if (size > packSize) |
| @@ -813,6 +809,7 @@ HRESULT CArchive::ReadItem2(CItemEx &item) | |||
| 813 | item.LongLink_WasUsed_2 = false; | 809 | item.LongLink_WasUsed_2 = false; |
| 814 | 810 | ||
| 815 | item.HeaderError = false; | 811 | item.HeaderError = false; |
| 812 | item.Method_Error = false; | ||
| 816 | item.IsSignedChecksum = false; | 813 | item.IsSignedChecksum = false; |
| 817 | item.Prefix_WasUsed = false; | 814 | item.Prefix_WasUsed = false; |
| 818 | 815 | ||
| @@ -838,13 +835,8 @@ HRESULT CArchive::ReadItem2(CItemEx &item) | |||
| 838 | 835 | ||
| 839 | for (;;) | 836 | for (;;) |
| 840 | { | 837 | { |
| 841 | if (OpenCallback) | 838 | RINOK(Progress(item, 0)) |
| 842 | { | ||
| 843 | RINOK(Progress(item, 0)) | ||
| 844 | } | ||
| 845 | |||
| 846 | RINOK(GetNextItemReal(item)) | 839 | RINOK(GetNextItemReal(item)) |
| 847 | |||
| 848 | // NumRecords++; | 840 | // NumRecords++; |
| 849 | 841 | ||
| 850 | if (!filled) | 842 | if (!filled) |
| @@ -1064,9 +1056,14 @@ HRESULT CArchive::ReadItem2(CItemEx &item) | |||
| 1064 | // GNU TAR ignores (item.Size) in that case | 1056 | // GNU TAR ignores (item.Size) in that case |
| 1065 | if (item.Size != 0 && item.Size != piSize) | 1057 | if (item.Size != 0 && item.Size != piSize) |
| 1066 | item.Pax_Error = true; | 1058 | item.Pax_Error = true; |
| 1067 | item.Size = piSize; | 1059 | if (piSize >= ((UInt64)1 << 63)) |
| 1068 | item.PackSize = piSize; | 1060 | item.Pax_Error = true; |
| 1069 | item.pax_size_WasUsed = true; | 1061 | else |
| 1062 | { | ||
| 1063 | item.Size = piSize; | ||
| 1064 | item.PackSize = piSize; | ||
| 1065 | item.pax_size_WasUsed = true; | ||
| 1066 | } | ||
| 1070 | } | 1067 | } |
| 1071 | 1068 | ||
| 1072 | item.PaxTimes = paxInfo; | 1069 | item.PaxTimes = paxInfo; |
diff --git a/CPP/7zip/Archive/Tar/TarItem.h b/CPP/7zip/Archive/Tar/TarItem.h index 112f38d..d4e2ea5 100644 --- a/CPP/7zip/Archive/Tar/TarItem.h +++ b/CPP/7zip/Archive/Tar/TarItem.h | |||
| @@ -322,6 +322,7 @@ struct CPaxExtra | |||
| 322 | struct CItemEx: public CItem | 322 | struct CItemEx: public CItem |
| 323 | { | 323 | { |
| 324 | bool HeaderError; | 324 | bool HeaderError; |
| 325 | bool Method_Error; | ||
| 325 | 326 | ||
| 326 | bool IsSignedChecksum; | 327 | bool IsSignedChecksum; |
| 327 | bool Prefix_WasUsed; | 328 | bool Prefix_WasUsed; |
diff --git a/CPP/7zip/Archive/Udf/UdfIn.cpp b/CPP/7zip/Archive/Udf/UdfIn.cpp index ce87c54..a9e4ebf 100644 --- a/CPP/7zip/Archive/Udf/UdfIn.cpp +++ b/CPP/7zip/Archive/Udf/UdfIn.cpp | |||
| @@ -500,10 +500,15 @@ size_t CFileId::Parse(const Byte *p, size_t size) | |||
| 500 | processed += impLen; | 500 | processed += impLen; |
| 501 | Id.Parse(p + processed, idLen); | 501 | Id.Parse(p + processed, idLen); |
| 502 | processed += idLen; | 502 | processed += idLen; |
| 503 | // const size_t processed2 = processed; | ||
| 503 | for (;(processed & 3) != 0; processed++) | 504 | for (;(processed & 3) != 0; processed++) |
| 504 | if (p[processed] != 0) | 505 | if (p[processed] != 0) |
| 505 | return 0; | 506 | return 0; |
| 506 | if ((size_t)tag.CrcLen + 16 != processed) return 0; | 507 | // some program can create non-standard UDF file where CrcLen doesn't include Padding data |
| 508 | if ((size_t)tag.CrcLen + 16 != processed | ||
| 509 | // && (size_t)tag.CrcLen + 16 != processed2 // we can enable this check to support non-standard UDF | ||
| 510 | ) | ||
| 511 | return 0; | ||
| 507 | return (processed <= size) ? processed : 0; | 512 | return (processed <= size) ? processed : 0; |
| 508 | } | 513 | } |
| 509 | 514 | ||
| @@ -577,15 +582,20 @@ HRESULT CInArchive::ReadItem(unsigned volIndex, int fsIndex, const CLongAllocDes | |||
| 577 | 582 | ||
| 578 | item.IcbTag.Parse(p + 16); | 583 | item.IcbTag.Parse(p + 16); |
| 579 | 584 | ||
| 585 | // maybe another FileType values are possible in rare cases. | ||
| 586 | // Shoud we ignore FileType here? | ||
| 580 | if (fsIndex < 0) | 587 | if (fsIndex < 0) |
| 581 | { | 588 | { |
| 589 | // if (item.IcbTag.FileType == ICB_FILE_TYPE_DIR) return S_FALSE; | ||
| 582 | if (item.IcbTag.FileType != ICB_FILE_TYPE_METADATA && | 590 | if (item.IcbTag.FileType != ICB_FILE_TYPE_METADATA && |
| 583 | item.IcbTag.FileType != ICB_FILE_TYPE_METADATA_MIRROR) | 591 | item.IcbTag.FileType != ICB_FILE_TYPE_METADATA_MIRROR && |
| 592 | item.IcbTag.FileType != ICB_FILE_TYPE_METADATA_BITMAP) | ||
| 584 | return S_FALSE; | 593 | return S_FALSE; |
| 585 | } | 594 | } |
| 586 | else if ( | 595 | else if ( |
| 587 | item.IcbTag.FileType != ICB_FILE_TYPE_DIR && | 596 | item.IcbTag.FileType != ICB_FILE_TYPE_DIR && |
| 588 | item.IcbTag.FileType != ICB_FILE_TYPE_FILE) | 597 | item.IcbTag.FileType != ICB_FILE_TYPE_FILE && |
| 598 | item.IcbTag.FileType != ICB_FILE_TYPE_REAL_TIME_FILE) // M2TS files in /BDMV/STREAM/ in Blu-ray movie | ||
| 589 | return S_FALSE; | 599 | return S_FALSE; |
| 590 | 600 | ||
| 591 | item.Parse(p); | 601 | item.Parse(p); |
| @@ -1210,7 +1220,7 @@ HRESULT CInArchive::Open2() | |||
| 1210 | if (tag.Id != DESC_TYPE_FileSet) | 1220 | if (tag.Id != DESC_TYPE_FileSet) |
| 1211 | return S_FALSE; | 1221 | return S_FALSE; |
| 1212 | 1222 | ||
| 1213 | PRF(printf("\n FileSet", volIndex)); | 1223 | PRF(printf("\n FileSet")); |
| 1214 | CFileSet fs; | 1224 | CFileSet fs; |
| 1215 | fs.RecordingTime.Parse(p + 16); | 1225 | fs.RecordingTime.Parse(p + 16); |
| 1216 | // fs.InterchangeLevel = Get16(p + 18); | 1226 | // fs.InterchangeLevel = Get16(p + 18); |
diff --git a/CPP/7zip/Archive/Udf/UdfIn.h b/CPP/7zip/Archive/Udf/UdfIn.h index 9ccbf74..cbe1a27 100644 --- a/CPP/7zip/Archive/Udf/UdfIn.h +++ b/CPP/7zip/Archive/Udf/UdfIn.h | |||
| @@ -250,9 +250,10 @@ enum EIcbFileType | |||
| 250 | { | 250 | { |
| 251 | ICB_FILE_TYPE_DIR = 4, | 251 | ICB_FILE_TYPE_DIR = 4, |
| 252 | ICB_FILE_TYPE_FILE = 5, | 252 | ICB_FILE_TYPE_FILE = 5, |
| 253 | 253 | ICB_FILE_TYPE_REAL_TIME_FILE = 249, // 2.3.5.2.1 | |
| 254 | ICB_FILE_TYPE_METADATA = 250, // 2.2.13.1 Metadata File | 254 | ICB_FILE_TYPE_METADATA = 250, // 2.2.13.1 |
| 255 | ICB_FILE_TYPE_METADATA_MIRROR = 251 | 255 | ICB_FILE_TYPE_METADATA_MIRROR = 251, // 2.2.13.1 |
| 256 | ICB_FILE_TYPE_METADATA_BITMAP = 252 // 2.2.13.2 | ||
| 256 | }; | 257 | }; |
| 257 | 258 | ||
| 258 | enum EIcbDescriptorType | 259 | enum EIcbDescriptorType |
diff --git a/CPP/7zip/Archive/Zip/ZipIn.cpp b/CPP/7zip/Archive/Zip/ZipIn.cpp index 788810f..9d77e87 100644 --- a/CPP/7zip/Archive/Zip/ZipIn.cpp +++ b/CPP/7zip/Archive/Zip/ZipIn.cpp | |||
| @@ -1718,61 +1718,49 @@ HRESULT CInArchive::TryEcd64(UInt64 offset, CCdInfo &cdInfo) | |||
| 1718 | 1718 | ||
| 1719 | HRESULT CInArchive::FindCd(bool checkOffsetMode) | 1719 | HRESULT CInArchive::FindCd(bool checkOffsetMode) |
| 1720 | { | 1720 | { |
| 1721 | CCdInfo &cdInfo = Vols.ecd; | ||
| 1722 | |||
| 1723 | UInt64 endPos; | ||
| 1724 | |||
| 1725 | // There are no useful data in cache in most cases here. | 1721 | // There are no useful data in cache in most cases here. |
| 1726 | // So here we don't use cache data from previous operations . | 1722 | // So here we don't use cache data from previous operations. |
| 1727 | |||
| 1728 | InitBuf(); | 1723 | InitBuf(); |
| 1724 | UInt64 endPos; | ||
| 1729 | RINOK(InStream_GetSize_SeekToEnd(Stream, endPos)) | 1725 | RINOK(InStream_GetSize_SeekToEnd(Stream, endPos)) |
| 1730 | _streamPos = endPos; | 1726 | _streamPos = endPos; |
| 1731 | 1727 | const size_t kBufSizeMax = (size_t)1 << 17; // must be larger than | |
| 1732 | // const UInt32 kBufSizeMax2 = ((UInt32)1 << 16) + kEcdSize + kEcd64Locator_Size + kEcd64_FullSize; | 1728 | // (1 << 16) + kEcdSize + kEcd64Locator_Size + kEcd64_FullSize |
| 1733 | const size_t kBufSizeMax = ((size_t)1 << 17); // must be larger than kBufSizeMax2 | ||
| 1734 | |||
| 1735 | const size_t bufSize = (endPos < kBufSizeMax) ? (size_t)endPos : kBufSizeMax; | 1729 | const size_t bufSize = (endPos < kBufSizeMax) ? (size_t)endPos : kBufSizeMax; |
| 1736 | if (bufSize < kEcdSize) | 1730 | if (bufSize < kEcdSize) |
| 1737 | return S_FALSE; | 1731 | return S_FALSE; |
| 1738 | // CByteArr byteBuffer(bufSize); | ||
| 1739 | |||
| 1740 | RINOK(AllocateBuffer(kBufSizeMax)) | 1732 | RINOK(AllocateBuffer(kBufSizeMax)) |
| 1733 | { | ||
| 1734 | RINOK(Seek_SavePos(endPos - bufSize)) | ||
| 1735 | size_t processed = bufSize; | ||
| 1736 | const HRESULT res = ReadStream(Stream, Buffer, &processed); | ||
| 1737 | _streamPos += processed; | ||
| 1738 | _bufCached = processed; | ||
| 1739 | _bufPos = 0; | ||
| 1740 | _cnt += processed; | ||
| 1741 | if (res != S_OK) | ||
| 1742 | return res; | ||
| 1743 | if (processed != bufSize) | ||
| 1744 | return S_FALSE; | ||
| 1745 | } | ||
| 1741 | 1746 | ||
| 1742 | RINOK(Seek_SavePos(endPos - bufSize)) | 1747 | CCdInfo &cdInfo = Vols.ecd; |
| 1743 | |||
| 1744 | size_t processed = bufSize; | ||
| 1745 | HRESULT res = ReadStream(Stream, Buffer, &processed); | ||
| 1746 | _streamPos += processed; | ||
| 1747 | _bufCached = processed; | ||
| 1748 | _bufPos = 0; | ||
| 1749 | _cnt += processed; | ||
| 1750 | if (res != S_OK) | ||
| 1751 | return res; | ||
| 1752 | if (processed != bufSize) | ||
| 1753 | return S_FALSE; | ||
| 1754 | |||
| 1755 | 1748 | ||
| 1756 | for (size_t i = bufSize - kEcdSize + 1;;) | 1749 | for (size_t i = bufSize - kEcdSize + 1;;) |
| 1757 | { | 1750 | { |
| 1758 | if (i == 0) | ||
| 1759 | return S_FALSE; | ||
| 1760 | |||
| 1761 | const Byte *buf = Buffer; | 1751 | const Byte *buf = Buffer; |
| 1762 | |||
| 1763 | for (;;) | ||
| 1764 | { | 1752 | { |
| 1765 | i--; | 1753 | const Byte *p = buf + i; |
| 1766 | if (buf[i] == 0x50) | 1754 | do |
| 1767 | break; | 1755 | if (p == buf) |
| 1768 | if (i == 0) | 1756 | return S_FALSE; |
| 1769 | return S_FALSE; | 1757 | while (*(--p) != 0x50); |
| 1770 | } | ||
| 1771 | |||
| 1772 | if (Get32(buf + i) != NSignature::kEcd) | ||
| 1773 | continue; | ||
| 1774 | 1758 | ||
| 1775 | cdInfo.ParseEcd32(buf + i); | 1759 | i = (size_t)(p - buf); |
| 1760 | if (Get32(p) != NSignature::kEcd) | ||
| 1761 | continue; | ||
| 1762 | cdInfo.ParseEcd32(p); | ||
| 1763 | } | ||
| 1776 | 1764 | ||
| 1777 | if (i >= kEcd64Locator_Size) | 1765 | if (i >= kEcd64Locator_Size) |
| 1778 | { | 1766 | { |
| @@ -1793,29 +1781,24 @@ HRESULT CInArchive::FindCd(bool checkOffsetMode) | |||
| 1793 | 1781 | ||
| 1794 | // Most of the zip64 use fixed size Zip64 ECD | 1782 | // Most of the zip64 use fixed size Zip64 ECD |
| 1795 | // we try relative backward reading. | 1783 | // we try relative backward reading. |
| 1796 | 1784 | const UInt64 absEcd64 = endPos - bufSize + i - (kEcd64Locator_Size + kEcd64_FullSize); | |
| 1797 | UInt64 absEcd64 = endPos - bufSize + i - (kEcd64Locator_Size + kEcd64_FullSize); | ||
| 1798 | 1785 | ||
| 1799 | if (locatorIndex >= kEcd64_FullSize) | 1786 | if (locatorIndex >= kEcd64_FullSize) |
| 1800 | if (checkOffsetMode || absEcd64 == locator.Ecd64Offset) | 1787 | if (checkOffsetMode || absEcd64 == locator.Ecd64Offset) |
| 1801 | { | 1788 | { |
| 1802 | const Byte *ecd64 = buf + locatorIndex - kEcd64_FullSize; | 1789 | const Byte *ecd64 = buf + locatorIndex - kEcd64_FullSize; |
| 1803 | if (Get32(ecd64) == NSignature::kEcd64) | 1790 | if (Get32(ecd64) == NSignature::kEcd64 && |
| 1791 | Get64(ecd64 + 4) == kEcd64_MainSize) | ||
| 1804 | { | 1792 | { |
| 1805 | UInt64 mainEcd64Size = Get64(ecd64 + 4); | 1793 | cdInfo.ParseEcd64e(ecd64 + 12); |
| 1806 | if (mainEcd64Size == kEcd64_MainSize) | 1794 | ArcInfo.Base = (Int64)(absEcd64 - locator.Ecd64Offset); |
| 1807 | { | 1795 | // ArcInfo.BaseVolIndex = cdInfo.ThisDisk; |
| 1808 | cdInfo.ParseEcd64e(ecd64 + 12); | 1796 | return S_OK; |
| 1809 | ArcInfo.Base = (Int64)(absEcd64 - locator.Ecd64Offset); | ||
| 1810 | // ArcInfo.BaseVolIndex = cdInfo.ThisDisk; | ||
| 1811 | return S_OK; | ||
| 1812 | } | ||
| 1813 | } | 1797 | } |
| 1814 | } | 1798 | } |
| 1815 | 1799 | ||
| 1816 | // some zip64 use variable size Zip64 ECD. | 1800 | // some zip64 use variable size Zip64 ECD. |
| 1817 | // we try to use absolute offset from locator. | 1801 | // we try to use absolute offset from locator. |
| 1818 | |||
| 1819 | if (absEcd64 != locator.Ecd64Offset) | 1802 | if (absEcd64 != locator.Ecd64Offset) |
| 1820 | { | 1803 | { |
| 1821 | if (TryEcd64(locator.Ecd64Offset, cdInfo) == S_OK) | 1804 | if (TryEcd64(locator.Ecd64Offset, cdInfo) == S_OK) |
| @@ -1881,6 +1864,9 @@ HRESULT CInArchive::TryReadCd(CObjectVector<CItemEx> &items, const CCdInfo &cdIn | |||
| 1881 | items.Clear(); | 1864 | items.Clear(); |
| 1882 | IsCdUnsorted = false; | 1865 | IsCdUnsorted = false; |
| 1883 | 1866 | ||
| 1867 | if ((Int64)cdOffset < 0) | ||
| 1868 | return S_FALSE; | ||
| 1869 | |||
| 1884 | // _startLocalFromCd_Disk = (UInt32)(Int32)-1; | 1870 | // _startLocalFromCd_Disk = (UInt32)(Int32)-1; |
| 1885 | // _startLocalFromCd_Offset = (UInt64)(Int64)-1; | 1871 | // _startLocalFromCd_Offset = (UInt64)(Int64)-1; |
| 1886 | 1872 | ||
diff --git a/CPP/7zip/Archive/Zip/ZipOut.cpp b/CPP/7zip/Archive/Zip/ZipOut.cpp index 63f1a71..e8a21c2 100644 --- a/CPP/7zip/Archive/Zip/ZipOut.cpp +++ b/CPP/7zip/Archive/Zip/ZipOut.cpp | |||
| @@ -49,42 +49,54 @@ void COutArchive::SeekToCurPos() | |||
| 49 | // #define DOES_NEED_ZIP64(v) (v >= 0) | 49 | // #define DOES_NEED_ZIP64(v) (v >= 0) |
| 50 | 50 | ||
| 51 | 51 | ||
| 52 | Z7_NO_INLINE | ||
| 52 | void COutArchive::WriteBytes(const void *data, size_t size) | 53 | void COutArchive::WriteBytes(const void *data, size_t size) |
| 53 | { | 54 | { |
| 54 | m_OutBuffer.WriteBytes(data, size); | 55 | m_OutBuffer.WriteBytes(data, size); |
| 55 | m_CurPos += size; | 56 | m_CurPos += size; |
| 56 | } | 57 | } |
| 57 | 58 | ||
| 59 | Z7_NO_INLINE | ||
| 58 | void COutArchive::Write8(Byte b) | 60 | void COutArchive::Write8(Byte b) |
| 59 | { | 61 | { |
| 60 | m_OutBuffer.WriteByte(b); | 62 | m_OutBuffer.WriteByte(b); |
| 61 | m_CurPos++; | 63 | m_CurPos++; |
| 62 | } | 64 | } |
| 63 | 65 | ||
| 66 | Z7_NO_INLINE | ||
| 64 | void COutArchive::Write16(UInt16 val) | 67 | void COutArchive::Write16(UInt16 val) |
| 65 | { | 68 | { |
| 66 | Write8((Byte)val); | 69 | Write8((Byte)val); |
| 67 | Write8((Byte)(val >> 8)); | 70 | Write8((Byte)(val >> 8)); |
| 68 | } | 71 | } |
| 69 | 72 | ||
| 73 | Z7_NO_INLINE | ||
| 70 | void COutArchive::Write32(UInt32 val) | 74 | void COutArchive::Write32(UInt32 val) |
| 71 | { | 75 | { |
| 72 | for (int i = 0; i < 4; i++) | 76 | for (int i = 0; i < 4; i++) |
| 73 | { | 77 | { |
| 74 | Write8((Byte)val); | 78 | // Write8((Byte)val); |
| 79 | m_OutBuffer.WriteByte((Byte)val); | ||
| 75 | val >>= 8; | 80 | val >>= 8; |
| 76 | } | 81 | } |
| 82 | m_CurPos += 4; | ||
| 77 | } | 83 | } |
| 78 | 84 | ||
| 85 | #define WRITE_CONST_PAIR_16_16(a, b) { Write32((a) | ((UInt32)(b) << 16)); } | ||
| 86 | |||
| 87 | Z7_NO_INLINE | ||
| 79 | void COutArchive::Write64(UInt64 val) | 88 | void COutArchive::Write64(UInt64 val) |
| 80 | { | 89 | { |
| 81 | for (int i = 0; i < 8; i++) | 90 | for (int i = 0; i < 8; i++) |
| 82 | { | 91 | { |
| 83 | Write8((Byte)val); | 92 | // Write8((Byte)val); |
| 93 | m_OutBuffer.WriteByte((Byte)val); | ||
| 84 | val >>= 8; | 94 | val >>= 8; |
| 85 | } | 95 | } |
| 96 | m_CurPos += 8; | ||
| 86 | } | 97 | } |
| 87 | 98 | ||
| 99 | Z7_NO_INLINE | ||
| 88 | void COutArchive::WriteExtra(const CExtraBlock &extra) | 100 | void COutArchive::WriteExtra(const CExtraBlock &extra) |
| 89 | { | 101 | { |
| 90 | FOR_VECTOR (i, extra.SubBlocks) | 102 | FOR_VECTOR (i, extra.SubBlocks) |
| @@ -134,11 +146,9 @@ void COutArchive::WriteTimeExtra(const CItemOut &item, bool writeNtfs) | |||
| 134 | if (writeNtfs) | 146 | if (writeNtfs) |
| 135 | { | 147 | { |
| 136 | // windows explorer ignores that extra | 148 | // windows explorer ignores that extra |
| 137 | Write16(NFileHeader::NExtraID::kNTFS); | 149 | WRITE_CONST_PAIR_16_16(NFileHeader::NExtraID::kNTFS, k_Ntfs_ExtraSize) |
| 138 | Write16(k_Ntfs_ExtraSize); | ||
| 139 | Write32(0); // reserved | 150 | Write32(0); // reserved |
| 140 | Write16(NFileHeader::NNtfsExtra::kTagTime); | 151 | WRITE_CONST_PAIR_16_16(NFileHeader::NNtfsExtra::kTagTime, 8 * 3) |
| 141 | Write16(8 * 3); | ||
| 142 | WriteNtfsTime(item.Ntfs_MTime); | 152 | WriteNtfsTime(item.Ntfs_MTime); |
| 143 | WriteNtfsTime(item.Ntfs_ATime); | 153 | WriteNtfsTime(item.Ntfs_ATime); |
| 144 | WriteNtfsTime(item.Ntfs_CTime); | 154 | WriteNtfsTime(item.Ntfs_CTime); |
| @@ -148,8 +158,7 @@ void COutArchive::WriteTimeExtra(const CItemOut &item, bool writeNtfs) | |||
| 148 | { | 158 | { |
| 149 | // windows explorer ignores that extra | 159 | // windows explorer ignores that extra |
| 150 | // by specification : should we write to local header also? | 160 | // by specification : should we write to local header also? |
| 151 | Write16(NFileHeader::NExtraID::kUnixTime); | 161 | WRITE_CONST_PAIR_16_16(NFileHeader::NExtraID::kUnixTime, k_UnixTime_ExtraSize) |
| 152 | Write16(k_UnixTime_ExtraSize); | ||
| 153 | const Byte flags = (Byte)((unsigned)1 << NFileHeader::NUnixTime::kMTime); | 162 | const Byte flags = (Byte)((unsigned)1 << NFileHeader::NUnixTime::kMTime); |
| 154 | Write8(flags); | 163 | Write8(flags); |
| 155 | UInt32 unixTime; | 164 | UInt32 unixTime; |
| @@ -217,8 +226,7 @@ void COutArchive::WriteLocalHeader(CItemOut &item, bool needCheck) | |||
| 217 | 226 | ||
| 218 | if (isZip64) | 227 | if (isZip64) |
| 219 | { | 228 | { |
| 220 | Write16(NFileHeader::NExtraID::kZip64); | 229 | WRITE_CONST_PAIR_16_16(NFileHeader::NExtraID::kZip64, 8 + 8) |
| 221 | Write16(8 + 8); | ||
| 222 | Write64(size); | 230 | Write64(size); |
| 223 | Write64(packSize); | 231 | Write64(packSize); |
| 224 | } | 232 | } |
| @@ -357,8 +365,9 @@ HRESULT COutArchive::WriteCentralDir(const CObjectVector<CItemOut> &items, const | |||
| 357 | const UInt64 cdSize = cd64EndOffset - cdOffset; | 365 | const UInt64 cdSize = cd64EndOffset - cdOffset; |
| 358 | const bool cdOffset64 = DOES_NEED_ZIP64(cdOffset); | 366 | const bool cdOffset64 = DOES_NEED_ZIP64(cdOffset); |
| 359 | const bool cdSize64 = DOES_NEED_ZIP64(cdSize); | 367 | const bool cdSize64 = DOES_NEED_ZIP64(cdSize); |
| 360 | const bool items64 = items.Size() >= 0xFFFF; | 368 | const bool need_Items_64 = items.Size() >= 0xFFFF; |
| 361 | const bool isZip64 = (cdOffset64 || cdSize64 || items64); | 369 | const unsigned items16 = (UInt16)(need_Items_64 ? 0xFFFF: items.Size()); |
| 370 | const bool isZip64 = (cdOffset64 || cdSize64 || need_Items_64); | ||
| 362 | 371 | ||
| 363 | // isZip64 = true; // to test Zip64 | 372 | // isZip64 = true; // to test Zip64 |
| 364 | 373 | ||
| @@ -371,8 +380,8 @@ HRESULT COutArchive::WriteCentralDir(const CObjectVector<CItemOut> &items, const | |||
| 371 | // const UInt32 extraSize = 1 << 26; | 380 | // const UInt32 extraSize = 1 << 26; |
| 372 | // Write64(kEcd64_MainSize + extraSize); | 381 | // Write64(kEcd64_MainSize + extraSize); |
| 373 | 382 | ||
| 374 | Write16(45); // made by version | 383 | WRITE_CONST_PAIR_16_16(45, // made by version |
| 375 | Write16(45); // extract version | 384 | 45) // extract version |
| 376 | Write32(0); // ThisDiskNumber | 385 | Write32(0); // ThisDiskNumber |
| 377 | Write32(0); // StartCentralDirectoryDiskNumber | 386 | Write32(0); // StartCentralDirectoryDiskNumber |
| 378 | Write64((UInt64)items.Size()); | 387 | Write64((UInt64)items.Size()); |
| @@ -389,10 +398,9 @@ HRESULT COutArchive::WriteCentralDir(const CObjectVector<CItemOut> &items, const | |||
| 389 | } | 398 | } |
| 390 | 399 | ||
| 391 | Write32(NSignature::kEcd); | 400 | Write32(NSignature::kEcd); |
| 392 | Write16(0); // ThisDiskNumber | 401 | WRITE_CONST_PAIR_16_16(0, 0) // ThisDiskNumber, StartCentralDirectoryDiskNumber |
| 393 | Write16(0); // StartCentralDirectoryDiskNumber | 402 | Write16((UInt16)items16); |
| 394 | Write16((UInt16)(items64 ? 0xFFFF: items.Size())); | 403 | Write16((UInt16)items16); |
| 395 | Write16((UInt16)(items64 ? 0xFFFF: items.Size())); | ||
| 396 | 404 | ||
| 397 | WRITE_32_VAL_SPEC(cdSize, cdSize64) | 405 | WRITE_32_VAL_SPEC(cdSize, cdSize64) |
| 398 | WRITE_32_VAL_SPEC(cdOffset, cdOffset64) | 406 | WRITE_32_VAL_SPEC(cdOffset, cdOffset64) |
diff --git a/CPP/7zip/Bundles/SFXCon/SfxCon.cpp b/CPP/7zip/Bundles/SFXCon/SfxCon.cpp index aac4e28..9e2d13d 100644 --- a/CPP/7zip/Bundles/SFXCon/SfxCon.cpp +++ b/CPP/7zip/Bundles/SFXCon/SfxCon.cpp | |||
| @@ -153,7 +153,7 @@ namespace NCommandType | |||
| 153 | }; | 153 | }; |
| 154 | } | 154 | } |
| 155 | 155 | ||
| 156 | static const char *g_Commands = "txl"; | 156 | static const char * const g_Commands = "txl"; |
| 157 | 157 | ||
| 158 | struct CArchiveCommand | 158 | struct CArchiveCommand |
| 159 | { | 159 | { |
diff --git a/CPP/7zip/Bundles/SFXSetup/SfxSetup.cpp b/CPP/7zip/Bundles/SFXSetup/SfxSetup.cpp index 0c09807..d4240d9 100644 --- a/CPP/7zip/Bundles/SFXSetup/SfxSetup.cpp +++ b/CPP/7zip/Bundles/SFXSetup/SfxSetup.cpp | |||
| @@ -48,72 +48,60 @@ static bool ReadDataString(CFSTR fileName, LPCSTR startID, | |||
| 48 | NIO::CInFile inFile; | 48 | NIO::CInFile inFile; |
| 49 | if (!inFile.Open(fileName)) | 49 | if (!inFile.Open(fileName)) |
| 50 | return false; | 50 | return false; |
| 51 | const size_t kBufferSize = (1 << 12); | 51 | const size_t kBufferSize = 1 << 12; |
| 52 | 52 | ||
| 53 | Byte buffer[kBufferSize]; | 53 | Byte buffer[kBufferSize]; |
| 54 | const unsigned signatureStartSize = MyStringLen(startID); | 54 | const size_t signatureStartSize = MyStringLen(startID + 1); |
| 55 | const unsigned signatureEndSize = MyStringLen(endID); | 55 | const size_t signatureEndSize = MyStringLen(endID + 1); |
| 56 | 56 | ||
| 57 | size_t numBytesPrev = 0; | 57 | size_t numBytesPrev = 0; |
| 58 | bool writeMode = false; | 58 | bool writeMode = false; |
| 59 | UInt64 posTotal = 0; | 59 | UInt32 posTotal = 0; |
| 60 | for (;;) | 60 | for (;;) |
| 61 | { | 61 | { |
| 62 | if (posTotal > (1 << 20)) | ||
| 63 | return (stringResult.IsEmpty()); | ||
| 64 | const size_t numReadBytes = kBufferSize - numBytesPrev; | 62 | const size_t numReadBytes = kBufferSize - numBytesPrev; |
| 65 | size_t processedSize; | 63 | size_t processedSize; |
| 66 | if (!inFile.ReadFull(buffer + numBytesPrev, numReadBytes, processedSize)) | 64 | if (!inFile.ReadFull(buffer + numBytesPrev, numReadBytes, processedSize)) |
| 67 | return false; | 65 | return false; |
| 68 | if (processedSize == 0) | 66 | if (processedSize == 0) |
| 69 | return true; | 67 | return true; |
| 70 | const size_t numBytesInBuffer = numBytesPrev + processedSize; | 68 | numBytesPrev += processedSize; |
| 71 | UInt32 pos = 0; | 69 | size_t pos = 0; |
| 72 | for (;;) | 70 | for (;;) |
| 73 | { | 71 | { |
| 74 | if (writeMode) | 72 | if (writeMode) |
| 75 | { | 73 | { |
| 76 | if (pos + signatureEndSize > numBytesInBuffer) | 74 | if (pos + signatureEndSize > numBytesPrev) |
| 77 | break; | 75 | break; |
| 78 | if (memcmp(buffer + pos, endID, signatureEndSize) == 0) | 76 | const Byte b = buffer[pos++]; |
| 79 | return true; | ||
| 80 | const Byte b = buffer[pos]; | ||
| 81 | if (b == 0) | 77 | if (b == 0) |
| 82 | return false; | 78 | return false; |
| 79 | if (b == ';' && memcmp(buffer + pos, endID + 1, signatureEndSize) == 0) | ||
| 80 | return true; | ||
| 83 | stringResult += (char)b; | 81 | stringResult += (char)b; |
| 84 | pos++; | ||
| 85 | } | 82 | } |
| 86 | else | 83 | else |
| 87 | { | 84 | { |
| 88 | if (pos + signatureStartSize > numBytesInBuffer) | 85 | if (pos + signatureStartSize > numBytesPrev) |
| 89 | break; | 86 | break; |
| 90 | if (memcmp(buffer + pos, startID, signatureStartSize) == 0) | 87 | const Byte b = buffer[pos++]; |
| 88 | if (b == ';' && memcmp(buffer + pos, startID + 1, signatureStartSize) == 0) | ||
| 91 | { | 89 | { |
| 92 | writeMode = true; | 90 | writeMode = true; |
| 93 | pos += signatureStartSize; | 91 | pos += signatureStartSize; |
| 94 | } | 92 | } |
| 95 | else | ||
| 96 | pos++; | ||
| 97 | } | 93 | } |
| 98 | } | 94 | } |
| 99 | numBytesPrev = numBytesInBuffer - pos; | 95 | posTotal += (UInt32)pos; |
| 100 | posTotal += pos; | 96 | if (posTotal > (1 << 21)) |
| 97 | return stringResult.IsEmpty(); | ||
| 98 | numBytesPrev -= pos; | ||
| 101 | memmove(buffer, buffer + pos, numBytesPrev); | 99 | memmove(buffer, buffer + pos, numBytesPrev); |
| 102 | } | 100 | } |
| 103 | } | 101 | } |
| 104 | 102 | ||
| 105 | static char kStartID[] = { ',','!','@','I','n','s','t','a','l','l','@','!','U','T','F','-','8','!', 0 }; | 103 | static const char * const kStartID = ",!@Install@!UTF-8!"; |
| 106 | static char kEndID[] = { ',','!','@','I','n','s','t','a','l','l','E','n','d','@','!', 0 }; | 104 | static const char * const kEndID = ",!@InstallEnd@!"; |
| 107 | |||
| 108 | static struct CInstallIDInit | ||
| 109 | { | ||
| 110 | CInstallIDInit() | ||
| 111 | { | ||
| 112 | kStartID[0] = ';'; | ||
| 113 | kEndID[0] = ';'; | ||
| 114 | } | ||
| 115 | } g_CInstallIDInit; | ||
| 116 | |||
| 117 | 105 | ||
| 118 | #if defined(_WIN32) && defined(_UNICODE) && !defined(_WIN64) && !defined(UNDER_CE) | 106 | #if defined(_WIN32) && defined(_UNICODE) && !defined(_WIN64) && !defined(UNDER_CE) |
| 119 | #define NT_CHECK_FAIL_ACTION ShowErrorMessage(L"Unsupported Windows version"); return 1; | 107 | #define NT_CHECK_FAIL_ACTION ShowErrorMessage(L"Unsupported Windows version"); return 1; |
diff --git a/CPP/7zip/Common/FileStreams.cpp b/CPP/7zip/Common/FileStreams.cpp index f90e280..b7e4fbe 100644 --- a/CPP/7zip/Common/FileStreams.cpp +++ b/CPP/7zip/Common/FileStreams.cpp | |||
| @@ -753,7 +753,7 @@ Z7_COM7F_IMF(CInFileStream::GetProperty(PROPID propID, PROPVARIANT *value)) | |||
| 753 | { | 753 | { |
| 754 | if (StoreOwnerName) | 754 | if (StoreOwnerName) |
| 755 | { | 755 | { |
| 756 | const uid_t gid = st.st_gid; | 756 | const gid_t gid = st.st_gid; |
| 757 | { | 757 | { |
| 758 | if (!OwnerGroup.IsEmpty() && _gid == gid) | 758 | if (!OwnerGroup.IsEmpty() && _gid == gid) |
| 759 | prop = OwnerGroup; | 759 | prop = OwnerGroup; |
diff --git a/CPP/7zip/Common/FileStreams.h b/CPP/7zip/Common/FileStreams.h index 212d4f0..7f465cf 100644 --- a/CPP/7zip/Common/FileStreams.h +++ b/CPP/7zip/Common/FileStreams.h | |||
| @@ -84,8 +84,8 @@ public: | |||
| 84 | BY_HANDLE_FILE_INFORMATION _info; | 84 | BY_HANDLE_FILE_INFORMATION _info; |
| 85 | #else | 85 | #else |
| 86 | struct stat _info; | 86 | struct stat _info; |
| 87 | UInt32 _uid; | 87 | uid_t _uid; // uid_t can be unsigned or signed int |
| 88 | UInt32 _gid; | 88 | gid_t _gid; |
| 89 | UString OwnerName; | 89 | UString OwnerName; |
| 90 | UString OwnerGroup; | 90 | UString OwnerGroup; |
| 91 | bool StoreOwnerId; | 91 | bool StoreOwnerId; |
diff --git a/CPP/7zip/UI/Common/ArchiveCommandLine.cpp b/CPP/7zip/UI/Common/ArchiveCommandLine.cpp index 7fe18fb..73974e6 100644 --- a/CPP/7zip/UI/Common/ArchiveCommandLine.cpp +++ b/CPP/7zip/UI/Common/ArchiveCommandLine.cpp | |||
| @@ -426,7 +426,7 @@ static NRecursedType::EEnum GetRecursedTypeFromIndex(int index) | |||
| 426 | } | 426 | } |
| 427 | } | 427 | } |
| 428 | 428 | ||
| 429 | static const char *g_Commands = "audtexlbih"; | 429 | static const char * const g_Commands = "audtexlbih"; |
| 430 | 430 | ||
| 431 | static bool ParseArchiveCommand(const UString &commandString, CArcCommand &command) | 431 | static bool ParseArchiveCommand(const UString &commandString, CArcCommand &command) |
| 432 | { | 432 | { |
diff --git a/CPP/7zip/UI/Common/ArchiveName.cpp b/CPP/7zip/UI/Common/ArchiveName.cpp index 3c0976d..f859d94 100644 --- a/CPP/7zip/UI/Common/ArchiveName.cpp +++ b/CPP/7zip/UI/Common/ArchiveName.cpp | |||
| @@ -17,14 +17,14 @@ using namespace NWindows; | |||
| 17 | using namespace NFile; | 17 | using namespace NFile; |
| 18 | 18 | ||
| 19 | 19 | ||
| 20 | static const char *g_ArcExts = | 20 | static const char * const g_ArcExts = |
| 21 | "7z" | 21 | "7z" |
| 22 | "\0" "zip" | 22 | "\0" "zip" |
| 23 | "\0" "tar" | 23 | "\0" "tar" |
| 24 | "\0" "wim" | 24 | "\0" "wim" |
| 25 | "\0"; | 25 | "\0"; |
| 26 | 26 | ||
| 27 | static const char *g_HashExts = | 27 | static const char * const g_HashExts = |
| 28 | "sha256" | 28 | "sha256" |
| 29 | "\0"; | 29 | "\0"; |
| 30 | 30 | ||
diff --git a/CPP/7zip/UI/Common/Bench.cpp b/CPP/7zip/UI/Common/Bench.cpp index eb24e7f..316c980 100644 --- a/CPP/7zip/UI/Common/Bench.cpp +++ b/CPP/7zip/UI/Common/Bench.cpp | |||
| @@ -3038,7 +3038,7 @@ AString GetProcessThreadsInfo(const NSystem::CProcessAffinity &ti) | |||
| 3038 | FOR_VECTOR (i, ti.Groups.GroupSizes) | 3038 | FOR_VECTOR (i, ti.Groups.GroupSizes) |
| 3039 | { | 3039 | { |
| 3040 | if (i != 0) | 3040 | if (i != 0) |
| 3041 | s.Add_Char(' '); | 3041 | s.Add_Space(); |
| 3042 | s.Add_UInt32(ti.Groups.GroupSizes[i]); | 3042 | s.Add_UInt32(ti.Groups.GroupSizes[i]); |
| 3043 | } | 3043 | } |
| 3044 | } | 3044 | } |
| @@ -3773,10 +3773,11 @@ HRESULT Bench( | |||
| 3773 | 3773 | ||
| 3774 | #ifndef Z7_ST | 3774 | #ifndef Z7_ST |
| 3775 | 3775 | ||
| 3776 | if (threadsInfo.Get() && threadsInfo.GetNumProcessThreads() != 0) | 3776 | if (!threadsInfo.Get() |
| 3777 | numCPUs = threadsInfo.GetNumProcessThreads(); | 3777 | || (numCPUs = threadsInfo.GetNumProcessThreads()) == 0) |
| 3778 | else | ||
| 3779 | numCPUs = NSystem::GetNumberOfProcessors(); | 3778 | numCPUs = NSystem::GetNumberOfProcessors(); |
| 3779 | // numCPUs : is number of threads assigned to process with affinity, | ||
| 3780 | // or it's total number of threads in all groups, if IsGroupMode == true, and there is default affinity. | ||
| 3780 | 3781 | ||
| 3781 | #endif | 3782 | #endif |
| 3782 | 3783 | ||
diff --git a/CPP/7zip/UI/Console/List.cpp b/CPP/7zip/UI/Console/List.cpp index 874caef..2d9f5a3 100644 --- a/CPP/7zip/UI/Console/List.cpp +++ b/CPP/7zip/UI/Console/List.cpp | |||
| @@ -201,8 +201,8 @@ static const CFieldInfoInit kStandardFieldTable[] = | |||
| 201 | { kpidPath, "Name", kLeft, kLeft, 2, 24 } | 201 | { kpidPath, "Name", kLeft, kLeft, 2, 24 } |
| 202 | }; | 202 | }; |
| 203 | 203 | ||
| 204 | const unsigned kNumSpacesMax = 32; // it must be larger than max CFieldInfoInit.Width | 204 | static const unsigned kNumSpacesMax = 32; // it must be larger than max CFieldInfoInit.Width |
| 205 | static const char *g_Spaces = | 205 | static const char * const g_Spaces = |
| 206 | " " ; | 206 | " " ; |
| 207 | 207 | ||
| 208 | static void PrintSpaces(unsigned numSpaces) | 208 | static void PrintSpaces(unsigned numSpaces) |
diff --git a/CPP/7zip/UI/FileManager/BrowseDialog2.cpp b/CPP/7zip/UI/FileManager/BrowseDialog2.cpp index ee98ab4..9f083c5 100644 --- a/CPP/7zip/UI/FileManager/BrowseDialog2.cpp +++ b/CPP/7zip/UI/FileManager/BrowseDialog2.cpp | |||
| @@ -9,6 +9,7 @@ | |||
| 9 | #include <windowsx.h> | 9 | #include <windowsx.h> |
| 10 | 10 | ||
| 11 | #include "../../../Common/IntToString.h" | 11 | #include "../../../Common/IntToString.h" |
| 12 | #include "../../../Common/MyCom.h" | ||
| 12 | #include "../../../Common/StringConvert.h" | 13 | #include "../../../Common/StringConvert.h" |
| 13 | #include "../../../Common/Wildcard.h" | 14 | #include "../../../Common/Wildcard.h" |
| 14 | 15 | ||
| @@ -19,6 +20,7 @@ | |||
| 19 | #include "../../../Windows/Menu.h" | 20 | #include "../../../Windows/Menu.h" |
| 20 | #include "../../../Windows/ProcessUtils.h" | 21 | #include "../../../Windows/ProcessUtils.h" |
| 21 | #include "../../../Windows/PropVariantConv.h" | 22 | #include "../../../Windows/PropVariantConv.h" |
| 23 | #include "../../../Windows/Shell.h" | ||
| 22 | #include "../../../Windows/Control/ComboBox.h" | 24 | #include "../../../Windows/Control/ComboBox.h" |
| 23 | #include "../../../Windows/Control/Dialog.h" | 25 | #include "../../../Windows/Control/Dialog.h" |
| 24 | #include "../../../Windows/Control/Edit.h" | 26 | #include "../../../Windows/Control/Edit.h" |
| @@ -57,7 +59,7 @@ static const int kParentIndex = -1; | |||
| 57 | // static const UINT k_Message_RefreshPathEdit = WM_APP + 1; | 59 | // static const UINT k_Message_RefreshPathEdit = WM_APP + 1; |
| 58 | 60 | ||
| 59 | 61 | ||
| 60 | static const wchar_t *k_Message_Link_operation_was_Blocked = | 62 | static const wchar_t * const k_Message_Link_operation_was_Blocked = |
| 61 | L"link openning was blocked by 7-Zip"; | 63 | L"link openning was blocked by 7-Zip"; |
| 62 | 64 | ||
| 63 | extern UString HResultToMessage(HRESULT errorCode); | 65 | extern UString HResultToMessage(HRESULT errorCode); |
| @@ -978,35 +980,61 @@ void CBrowseDialog2::OnHelp() | |||
| 978 | #endif | 980 | #endif |
| 979 | 981 | ||
| 980 | 982 | ||
| 983 | HRESULT ShellFolder_ParseDisplayName(IShellFolder *shellFolder, | ||
| 984 | HWND hwnd, const UString &path, LPITEMIDLIST *ppidl); | ||
| 985 | |||
| 981 | HRESULT StartApplication(const UString &dir, const UString &path, HWND window, CProcess &process); | 986 | HRESULT StartApplication(const UString &dir, const UString &path, HWND window, CProcess &process); |
| 982 | HRESULT StartApplication(const UString &dir, const UString &path, HWND window, CProcess &process) | 987 | HRESULT StartApplication(const UString &dir, const UString &path, HWND window, CProcess &process) |
| 983 | { | 988 | { |
| 984 | UString path2 = path; | 989 | UString path2 = path; |
| 985 | 990 | UINT32 result; | |
| 986 | #ifdef _WIN32 | 991 | { |
| 992 | #ifdef _WIN32 | ||
| 993 | NShell::CItemIDList pidl; | ||
| 994 | // SHELLEXECUTEINFO::pidl is more accurate way than SHELLEXECUTEINFO::lpFile | ||
| 995 | { | ||
| 996 | CMyComPtr<IShellFolder> desktop; | ||
| 997 | if (SHGetDesktopFolder(&desktop) == S_OK && desktop) | ||
| 998 | if (ShellFolder_ParseDisplayName(desktop, | ||
| 999 | NULL, // HWND : do we need (window) or NULL here? | ||
| 1000 | path, | ||
| 1001 | &pidl) != S_OK) | ||
| 1002 | pidl.Detach(); | ||
| 1003 | } | ||
| 987 | { | 1004 | { |
| 988 | const int dot = path2.ReverseFind_Dot(); | 1005 | const int dot = path2.ReverseFind_Dot(); |
| 989 | const int separ = path2.ReverseFind_PathSepar(); | 1006 | const int separ = path2.ReverseFind_PathSepar(); |
| 990 | if (dot < 0 || dot < separ) | 1007 | if (separ != (int)path2.Len() - 1) |
| 991 | path2.Add_Dot(); | 1008 | if (dot < 0 || dot < separ) |
| 1009 | path2.Add_Dot(); | ||
| 992 | } | 1010 | } |
| 993 | #endif | 1011 | #endif // _WIN32 |
| 994 | 1012 | ||
| 995 | UINT32 result; | ||
| 996 | |||
| 997 | #ifndef _UNICODE | 1013 | #ifndef _UNICODE |
| 998 | if (g_IsNT) | 1014 | if (g_IsNT) |
| 999 | { | 1015 | { |
| 1000 | SHELLEXECUTEINFOW execInfo; | 1016 | SHELLEXECUTEINFOW execInfo; |
| 1017 | memset(&execInfo, 0, sizeof(execInfo)); | ||
| 1018 | // execInfo.hwnd = NULL; | ||
| 1019 | // execInfo.lpVerb = NULL; | ||
| 1020 | // execInfo.lpFile = NULL; | ||
| 1021 | // execInfo.lpDirectory = NULL; | ||
| 1022 | // execInfo.lpParameters = NULL; | ||
| 1023 | // execInfo.hProcess = NULL; | ||
| 1001 | execInfo.cbSize = sizeof(execInfo); | 1024 | execInfo.cbSize = sizeof(execInfo); |
| 1002 | execInfo.fMask = SEE_MASK_NOCLOSEPROCESS | SEE_MASK_FLAG_DDEWAIT; | 1025 | execInfo.fMask = SEE_MASK_NOCLOSEPROCESS | SEE_MASK_FLAG_DDEWAIT; |
| 1003 | execInfo.hwnd = NULL; | 1026 | if (!dir.IsEmpty()) |
| 1004 | execInfo.lpVerb = NULL; | 1027 | execInfo.lpDirectory = dir; |
| 1005 | execInfo.lpFile = path2; | ||
| 1006 | execInfo.lpParameters = NULL; | ||
| 1007 | execInfo.lpDirectory = dir.IsEmpty() ? NULL : (LPCWSTR)dir; | ||
| 1008 | execInfo.nShow = SW_SHOWNORMAL; | 1028 | execInfo.nShow = SW_SHOWNORMAL; |
| 1009 | execInfo.hProcess = NULL; | 1029 | |
| 1030 | if ((LPCITEMIDLIST)pidl) | ||
| 1031 | { | ||
| 1032 | execInfo.lpIDList = pidl; | ||
| 1033 | execInfo.fMask |= SEE_MASK_IDLIST; | ||
| 1034 | } | ||
| 1035 | else | ||
| 1036 | execInfo.lpFile = path2; | ||
| 1037 | |||
| 1010 | typedef BOOL (WINAPI * Func_ShellExecuteExW)(LPSHELLEXECUTEINFOW lpExecInfo); | 1038 | typedef BOOL (WINAPI * Func_ShellExecuteExW)(LPSHELLEXECUTEINFOW lpExecInfo); |
| 1011 | Z7_DIAGNOSTIC_IGNORE_CAST_FUNCTION | 1039 | Z7_DIAGNOSTIC_IGNORE_CAST_FUNCTION |
| 1012 | const | 1040 | const |
| @@ -1024,34 +1052,40 @@ Z7_DIAGNOSTIC_IGNORE_CAST_FUNCTION | |||
| 1024 | #endif | 1052 | #endif |
| 1025 | { | 1053 | { |
| 1026 | SHELLEXECUTEINFO execInfo; | 1054 | SHELLEXECUTEINFO execInfo; |
| 1055 | memset(&execInfo, 0, sizeof(execInfo)); | ||
| 1056 | // execInfo.hwnd = NULL; | ||
| 1057 | // execInfo.lpVerb = NULL; | ||
| 1058 | // execInfo.lpFile = NULL; | ||
| 1059 | // execInfo.lpDirectory = NULL; | ||
| 1060 | // execInfo.lpParameters = NULL; | ||
| 1061 | // execInfo.hProcess = NULL; | ||
| 1027 | execInfo.cbSize = sizeof(execInfo); | 1062 | execInfo.cbSize = sizeof(execInfo); |
| 1028 | execInfo.fMask = SEE_MASK_NOCLOSEPROCESS | 1063 | execInfo.fMask = SEE_MASK_NOCLOSEPROCESS |
| 1029 | #ifndef UNDER_CE | 1064 | #ifndef UNDER_CE |
| 1030 | | SEE_MASK_FLAG_DDEWAIT | 1065 | | SEE_MASK_FLAG_DDEWAIT |
| 1031 | #endif | 1066 | #endif |
| 1032 | ; | 1067 | ; |
| 1033 | execInfo.hwnd = NULL; | 1068 | execInfo.nShow = SW_SHOWNORMAL; |
| 1034 | execInfo.lpVerb = NULL; | ||
| 1035 | const CSysString sysPath (GetSystemString(path2)); | 1069 | const CSysString sysPath (GetSystemString(path2)); |
| 1036 | const CSysString sysDir (GetSystemString(dir)); | 1070 | const CSysString sysDir (GetSystemString(dir)); |
| 1037 | execInfo.lpFile = sysPath; | 1071 | #ifndef UNDER_CE |
| 1038 | execInfo.lpParameters = NULL; | 1072 | if (!sysDir.IsEmpty()) |
| 1039 | execInfo.lpDirectory = | 1073 | execInfo.lpDirectory = sysDir; |
| 1040 | #ifdef UNDER_CE | 1074 | #endif |
| 1041 | NULL | 1075 | |
| 1042 | #else | 1076 | if ((LPCITEMIDLIST)pidl) |
| 1043 | sysDir.IsEmpty() ? NULL : (LPCTSTR)sysDir | 1077 | { |
| 1044 | #endif | 1078 | execInfo.lpIDList = pidl; |
| 1045 | ; | 1079 | execInfo.fMask |= SEE_MASK_IDLIST; |
| 1046 | execInfo.nShow = SW_SHOWNORMAL; | 1080 | } |
| 1047 | execInfo.hProcess = NULL; | 1081 | else |
| 1082 | execInfo.lpFile = sysPath; | ||
| 1048 | ::ShellExecuteEx(&execInfo); | 1083 | ::ShellExecuteEx(&execInfo); |
| 1049 | result = (UINT32)(UINT_PTR)execInfo.hInstApp; | 1084 | result = (UINT32)(UINT_PTR)execInfo.hInstApp; |
| 1050 | process.Attach(execInfo.hProcess); | 1085 | process.Attach(execInfo.hProcess); |
| 1051 | } | 1086 | } |
| 1052 | |||
| 1053 | // DEBUG_PRINT_NUM("-- ShellExecuteEx -- execInfo.hInstApp = ", result) | 1087 | // DEBUG_PRINT_NUM("-- ShellExecuteEx -- execInfo.hInstApp = ", result) |
| 1054 | 1088 | } | |
| 1055 | if (result <= 32) | 1089 | if (result <= 32) |
| 1056 | { | 1090 | { |
| 1057 | switch (result) | 1091 | switch (result) |
| @@ -1063,10 +1097,8 @@ Z7_DIAGNOSTIC_IGNORE_CAST_FUNCTION | |||
| 1063 | // L"There is no application associated with the given file name extension", | 1097 | // L"There is no application associated with the given file name extension", |
| 1064 | ); | 1098 | ); |
| 1065 | } | 1099 | } |
| 1066 | |||
| 1067 | return E_FAIL; // fixed in 15.13. Can we use it for any Windows version? | 1100 | return E_FAIL; // fixed in 15.13. Can we use it for any Windows version? |
| 1068 | } | 1101 | } |
| 1069 | |||
| 1070 | return S_OK; | 1102 | return S_OK; |
| 1071 | } | 1103 | } |
| 1072 | 1104 | ||
diff --git a/CPP/7zip/UI/FileManager/FSFolder.cpp b/CPP/7zip/UI/FileManager/FSFolder.cpp index 7956d86..51dfaa9 100644 --- a/CPP/7zip/UI/FileManager/FSFolder.cpp +++ b/CPP/7zip/UI/FileManager/FSFolder.cpp | |||
| @@ -748,8 +748,8 @@ Z7_COM7F_IMF2(Int32, CFSFolder::CompareItems(UInt32 index1, UInt32 index2, PROPI | |||
| 748 | case kpidMTime: return CompareFileTime(&fi1.MTime, &fi2.MTime); | 748 | case kpidMTime: return CompareFileTime(&fi1.MTime, &fi2.MTime); |
| 749 | case kpidIsDir: | 749 | case kpidIsDir: |
| 750 | { | 750 | { |
| 751 | bool isDir1 = /* ss1 ? false : */ fi1.IsDir(); | 751 | const bool isDir1 = /* ss1 ? false : */ fi1.IsDir(); |
| 752 | bool isDir2 = /* ss2 ? false : */ fi2.IsDir(); | 752 | const bool isDir2 = /* ss2 ? false : */ fi2.IsDir(); |
| 753 | if (isDir1 == isDir2) | 753 | if (isDir1 == isDir2) |
| 754 | return 0; | 754 | return 0; |
| 755 | return isDir1 ? -1 : 1; | 755 | return isDir1 ? -1 : 1; |
| @@ -798,7 +798,9 @@ Z7_COM7F_IMF2(Int32, CFSFolder::CompareItems(UInt32 index1, UInt32 index2, PROPI | |||
| 798 | return MyStringCompareNoCase(comment1, comment2); | 798 | return MyStringCompareNoCase(comment1, comment2); |
| 799 | } | 799 | } |
| 800 | case kpidPrefix: | 800 | case kpidPrefix: |
| 801 | if (fi1.Parent < 0) return (fi2.Parent < 0) ? 0 : -1; | 801 | if (fi1.Parent == fi2.Parent) |
| 802 | return 0; | ||
| 803 | if (fi1.Parent < 0) return -1; | ||
| 802 | if (fi2.Parent < 0) return 1; | 804 | if (fi2.Parent < 0) return 1; |
| 803 | return CompareFileNames_ForFolderList( | 805 | return CompareFileNames_ForFolderList( |
| 804 | Folders[fi1.Parent], | 806 | Folders[fi1.Parent], |
diff --git a/CPP/7zip/UI/FileManager/LangPage.cpp b/CPP/7zip/UI/FileManager/LangPage.cpp index 3aeaf13..626c91b 100644 --- a/CPP/7zip/UI/FileManager/LangPage.cpp +++ b/CPP/7zip/UI/FileManager/LangPage.cpp | |||
| @@ -253,8 +253,7 @@ bool CLangPage::OnInit() | |||
| 253 | temp += " "; | 253 | temp += " "; |
| 254 | temp += rec.Mark; | 254 | temp += rec.Mark; |
| 255 | } | 255 | } |
| 256 | const int index = (int)_langCombo.AddString(temp); | 256 | const int index = (int)_langCombo.AddString_SetItemData(temp, (LPARAM)rec.LangInfoIndex); |
| 257 | _langCombo.SetItemData(index, (LPARAM)rec.LangInfoIndex); | ||
| 258 | if (rec.IsSelected) | 257 | if (rec.IsSelected) |
| 259 | _langCombo.SetCurSel(index); | 258 | _langCombo.SetCurSel(index); |
| 260 | } | 259 | } |
diff --git a/CPP/7zip/UI/FileManager/MenuPage.cpp b/CPP/7zip/UI/FileManager/MenuPage.cpp index e8736b8..61dd8cb 100644 --- a/CPP/7zip/UI/FileManager/MenuPage.cpp +++ b/CPP/7zip/UI/FileManager/MenuPage.cpp | |||
| @@ -222,8 +222,7 @@ bool CMenuPage::OnInit() | |||
| 222 | s.Add_UInt32(val); | 222 | s.Add_UInt32(val); |
| 223 | if (i == 0) | 223 | if (i == 0) |
| 224 | s.Insert(0, L"* "); | 224 | s.Insert(0, L"* "); |
| 225 | const int index = (int)_zoneCombo.AddString(s); | 225 | const int index = (int)_zoneCombo.AddString_SetItemData(s, (LPARAM)val); |
| 226 | _zoneCombo.SetItemData(index, (LPARAM)val); | ||
| 227 | if (val == wz) | 226 | if (val == wz) |
| 228 | _zoneCombo.SetCurSel(index); | 227 | _zoneCombo.SetCurSel(index); |
| 229 | } | 228 | } |
diff --git a/CPP/7zip/UI/FileManager/PanelItemOpen.cpp b/CPP/7zip/UI/FileManager/PanelItemOpen.cpp index aa56ef5..9d78368 100644 --- a/CPP/7zip/UI/FileManager/PanelItemOpen.cpp +++ b/CPP/7zip/UI/FileManager/PanelItemOpen.cpp | |||
| @@ -825,7 +825,10 @@ void CPanel::EditItem(unsigned index, bool useEditor) | |||
| 825 | return; | 825 | return; |
| 826 | } | 826 | } |
| 827 | CProcess process; | 827 | CProcess process; |
| 828 | StartEditApplication(GetItemFullPath(index), useEditor, (HWND)*this, process); | 828 | StartEditApplication(GetItemFullPath(index), useEditor, |
| 829 | // (HWND)*this, | ||
| 830 | GetParent(), | ||
| 831 | process); | ||
| 829 | } | 832 | } |
| 830 | 833 | ||
| 831 | 834 | ||
| @@ -854,7 +857,10 @@ void CPanel::OpenFolderExternal(unsigned index) | |||
| 854 | path.Add_PathSepar(); | 857 | path.Add_PathSepar(); |
| 855 | } | 858 | } |
| 856 | 859 | ||
| 857 | StartApplicationDontWait(prefix, path, (HWND)*this); | 860 | StartApplicationDontWait(prefix, path, |
| 861 | // (HWND)*this | ||
| 862 | GetParent() | ||
| 863 | ); | ||
| 858 | } | 864 | } |
| 859 | 865 | ||
| 860 | 866 | ||
| @@ -981,7 +987,10 @@ void CPanel::OpenItem(unsigned index, bool tryInternal, bool tryExternal, const | |||
| 981 | { | 987 | { |
| 982 | // SetCurrentDirectory opens HANDLE to folder!!! | 988 | // SetCurrentDirectory opens HANDLE to folder!!! |
| 983 | // NDirectory::MySetCurrentDirectory(prefix); | 989 | // NDirectory::MySetCurrentDirectory(prefix); |
| 984 | StartApplicationDontWait(prefix, fullPath, (HWND)*this); | 990 | StartApplicationDontWait(prefix, fullPath, |
| 991 | // (HWND)*this | ||
| 992 | GetParent() | ||
| 993 | ); | ||
| 985 | } | 994 | } |
| 986 | } | 995 | } |
| 987 | 996 | ||
| @@ -1732,9 +1741,15 @@ void CPanel::OpenItemInArchive(unsigned index, bool tryInternal, bool tryExterna | |||
| 1732 | CProcess process; | 1741 | CProcess process; |
| 1733 | HRESULT res; | 1742 | HRESULT res; |
| 1734 | if (editMode) | 1743 | if (editMode) |
| 1735 | res = StartEditApplication(fs2us(tempFilePath), useEditor, (HWND)*this, process); | 1744 | res = StartEditApplication(fs2us(tempFilePath), useEditor, |
| 1745 | // (HWND)*this, | ||
| 1746 | GetParent(), | ||
| 1747 | process); | ||
| 1736 | else | 1748 | else |
| 1737 | res = StartApplication(fs2us(tempDirNorm), fs2us(tempFilePath), (HWND)*this, process); | 1749 | res = StartApplication(fs2us(tempDirNorm), fs2us(tempFilePath), |
| 1750 | // (HWND)*this, | ||
| 1751 | GetParent(), | ||
| 1752 | process); | ||
| 1738 | 1753 | ||
| 1739 | if ((HANDLE)process == NULL) | 1754 | if ((HANDLE)process == NULL) |
| 1740 | { | 1755 | { |
diff --git a/CPP/7zip/UI/FileManager/PanelMenu.cpp b/CPP/7zip/UI/FileManager/PanelMenu.cpp index 9086996..e655843 100644 --- a/CPP/7zip/UI/FileManager/PanelMenu.cpp +++ b/CPP/7zip/UI/FileManager/PanelMenu.cpp | |||
| @@ -488,7 +488,9 @@ struct CFolderPidls | |||
| 488 | }; | 488 | }; |
| 489 | 489 | ||
| 490 | 490 | ||
| 491 | static HRESULT ShellFolder_ParseDisplayName(IShellFolder *shellFolder, | 491 | HRESULT ShellFolder_ParseDisplayName(IShellFolder *shellFolder, |
| 492 | HWND hwnd, const UString &path, LPITEMIDLIST *ppidl); | ||
| 493 | HRESULT ShellFolder_ParseDisplayName(IShellFolder *shellFolder, | ||
| 492 | HWND hwnd, const UString &path, LPITEMIDLIST *ppidl) | 494 | HWND hwnd, const UString &path, LPITEMIDLIST *ppidl) |
| 493 | { | 495 | { |
| 494 | ULONG eaten = 0; | 496 | ULONG eaten = 0; |
diff --git a/CPP/7zip/UI/FileManager/PanelSort.cpp b/CPP/7zip/UI/FileManager/PanelSort.cpp index f95f8ee..57ac877 100644 --- a/CPP/7zip/UI/FileManager/PanelSort.cpp +++ b/CPP/7zip/UI/FileManager/PanelSort.cpp | |||
| @@ -82,7 +82,7 @@ static inline const wchar_t *GetExtensionPtr(const UString &name) | |||
| 82 | 82 | ||
| 83 | void CPanel::SetSortRawStatus() | 83 | void CPanel::SetSortRawStatus() |
| 84 | { | 84 | { |
| 85 | _isRawSortProp = false; | 85 | _isRawSortProp = 0; // false; |
| 86 | FOR_VECTOR (i, _columns) | 86 | FOR_VECTOR (i, _columns) |
| 87 | { | 87 | { |
| 88 | const CPropColumn &prop = _columns[i]; | 88 | const CPropColumn &prop = _columns[i]; |
| @@ -95,21 +95,15 @@ void CPanel::SetSortRawStatus() | |||
| 95 | } | 95 | } |
| 96 | 96 | ||
| 97 | 97 | ||
| 98 | static int CALLBACK CompareItems2(LPARAM lParam1, LPARAM lParam2, LPARAM lpData) | 98 | static int CALLBACK CompareItems2(const LPARAM lParam1, const LPARAM lParam2, |
| 99 | const CPanel * const panel, const PROPID propID, const Int32 isRawProp) | ||
| 99 | { | 100 | { |
| 100 | if (lpData == 0) | ||
| 101 | return 0; | ||
| 102 | CPanel *panel = (CPanel*)lpData; | ||
| 103 | |||
| 104 | |||
| 105 | PROPID propID = panel->_sortID; | ||
| 106 | |||
| 107 | if (propID == kpidNoProperty) | 101 | if (propID == kpidNoProperty) |
| 108 | return MyCompare(lParam1, lParam2); | 102 | return MyCompare(lParam1, lParam2); |
| 109 | 103 | ||
| 110 | if (panel->_isRawSortProp) | 104 | if (isRawProp) |
| 111 | { | 105 | { |
| 112 | // Sha1, NtSecurity, NtReparse | 106 | // Sha1, Checksum, NtSecurity, NtReparse |
| 113 | const void *data1; | 107 | const void *data1; |
| 114 | const void *data2; | 108 | const void *data2; |
| 115 | UInt32 dataSize1; | 109 | UInt32 dataSize1; |
| @@ -135,7 +129,7 @@ static int CALLBACK CompareItems2(LPARAM lParam1, LPARAM lParam2, LPARAM lpData) | |||
| 135 | } | 129 | } |
| 136 | 130 | ||
| 137 | if (panel->_folderCompare) | 131 | if (panel->_folderCompare) |
| 138 | return panel->_folderCompare->CompareItems((UInt32)lParam1, (UInt32)lParam2, propID, panel->_isRawSortProp); | 132 | return panel->_folderCompare->CompareItems((UInt32)lParam1, (UInt32)lParam2, propID, isRawProp); |
| 139 | 133 | ||
| 140 | switch (propID) | 134 | switch (propID) |
| 141 | { | 135 | { |
| @@ -189,16 +183,41 @@ int CALLBACK CompareItems(LPARAM lParam1, LPARAM lParam2, LPARAM lpData) | |||
| 189 | if (lParam1 == (int)kParentIndex) return -1; | 183 | if (lParam1 == (int)kParentIndex) return -1; |
| 190 | if (lParam2 == (int)kParentIndex) return 1; | 184 | if (lParam2 == (int)kParentIndex) return 1; |
| 191 | 185 | ||
| 192 | CPanel *panel = (CPanel*)lpData; | 186 | const CPanel *panel = (CPanel*)lpData; |
| 193 | 187 | ||
| 194 | const bool isDir1 = panel->IsItem_Folder((unsigned)lParam1); | 188 | const bool isDir1 = panel->IsItem_Folder((unsigned)lParam1); |
| 195 | const bool isDir2 = panel->IsItem_Folder((unsigned)lParam2); | 189 | const bool isDir2 = panel->IsItem_Folder((unsigned)lParam2); |
| 196 | 190 | if (isDir1 != isDir2) | |
| 197 | if (isDir1 && !isDir2) return -1; | 191 | return isDir1 ? -1 : 1; |
| 198 | if (isDir2 && !isDir1) return 1; | ||
| 199 | 192 | ||
| 200 | const int result = CompareItems2(lParam1, lParam2, lpData); | 193 | /* |
| 201 | return panel->_ascending ? result: (-result); | 194 | we have up to 3 iterations: |
| 195 | 1: prop, | ||
| 196 | 2: kpidName, kpidPrefix | ||
| 197 | 3: prop, kpidName, kpidPrefix | ||
| 198 | 3: kpidPrefix, kpidName, kpidPrefix : is some rare case | ||
| 199 | */ | ||
| 200 | PROPID propID = panel->_sortID; | ||
| 201 | int res = 0; | ||
| 202 | for (unsigned iter = 0; iter < 3; iter++) | ||
| 203 | { | ||
| 204 | res = CompareItems2(lParam1, lParam2, panel, propID, | ||
| 205 | iter ? 0 : panel->_isRawSortProp); | ||
| 206 | if (res) | ||
| 207 | break; | ||
| 208 | if (propID == kpidName) | ||
| 209 | { | ||
| 210 | // if (!_flatMode.IsEmpty()) break; // !_flatMode ; | ||
| 211 | propID = kpidPrefix; | ||
| 212 | continue; | ||
| 213 | } | ||
| 214 | if (iter) | ||
| 215 | break; | ||
| 216 | propID = kpidName; | ||
| 217 | } | ||
| 218 | if (res == 0) | ||
| 219 | res = MyCompare(lParam1, lParam2); // order of LoadSubItems() | ||
| 220 | return panel->_ascending ? res: -res; | ||
| 202 | } | 221 | } |
| 203 | 222 | ||
| 204 | 223 | ||
diff --git a/CPP/7zip/UI/GUI/BenchmarkDialog.cpp b/CPP/7zip/UI/GUI/BenchmarkDialog.cpp index 1686c69..980161f 100644 --- a/CPP/7zip/UI/GUI/BenchmarkDialog.cpp +++ b/CPP/7zip/UI/GUI/BenchmarkDialog.cpp | |||
| @@ -440,11 +440,9 @@ static const size_t kMaxDicSize = (size_t)1 << (22 + sizeof(size_t) / 4 * 5); | |||
| 440 | 440 | ||
| 441 | static int ComboBox_Add_UInt32(NWindows::NControl::CComboBox &cb, UInt32 v) | 441 | static int ComboBox_Add_UInt32(NWindows::NControl::CComboBox &cb, UInt32 v) |
| 442 | { | 442 | { |
| 443 | TCHAR s[16]; | 443 | WCHAR s[16]; |
| 444 | ConvertUInt32ToString(v, s); | 444 | ConvertUInt32ToString(v, s); |
| 445 | const int index = (int)cb.AddString(s); | 445 | return (int)cb.AddString_SetItemData(s, (LPARAM)v); |
| 446 | cb.SetItemData(index, (LPARAM)v); | ||
| 447 | return index; | ||
| 448 | } | 446 | } |
| 449 | 447 | ||
| 450 | 448 | ||
| @@ -481,21 +479,17 @@ bool CBenchmarkDialog::OnInit() | |||
| 481 | _consoleEdit.SendMsg(WM_SETFONT, (WPARAM)_font._font, TRUE); | 479 | _consoleEdit.SendMsg(WM_SETFONT, (WPARAM)_font._font, TRUE); |
| 482 | } | 480 | } |
| 483 | 481 | ||
| 484 | UInt32 numCPUs = 1; | 482 | UInt32 numCPUs = 1; // process threads |
| 483 | UInt32 numCPUs_Sys = 1; // system threads | ||
| 485 | 484 | ||
| 486 | { | 485 | { |
| 487 | AString s ("/ "); | ||
| 488 | |||
| 489 | NSystem::CProcessAffinity threadsInfo; | 486 | NSystem::CProcessAffinity threadsInfo; |
| 490 | threadsInfo.InitST(); | 487 | threadsInfo.InitST(); |
| 488 | #ifndef Z7_ST | ||
| 489 | threadsInfo.Get_and_return_NumProcessThreads_and_SysThreads(numCPUs, numCPUs_Sys); | ||
| 490 | #endif | ||
| 491 | 491 | ||
| 492 | #ifndef Z7_ST | 492 | AString s ("/ "); |
| 493 | if (threadsInfo.Get() && threadsInfo.processAffinityMask != 0) | ||
| 494 | numCPUs = threadsInfo.GetNumProcessThreads(); | ||
| 495 | else | ||
| 496 | numCPUs = NSystem::GetNumberOfProcessors(); | ||
| 497 | #endif | ||
| 498 | |||
| 499 | s.Add_UInt32(numCPUs); | 493 | s.Add_UInt32(numCPUs); |
| 500 | s += GetProcessThreadsInfo(threadsInfo); | 494 | s += GetProcessThreadsInfo(threadsInfo); |
| 501 | SetItemTextA(IDT_BENCH_HARDWARE_THREADS, s); | 495 | SetItemTextA(IDT_BENCH_HARDWARE_THREADS, s); |
| @@ -506,10 +500,8 @@ bool CBenchmarkDialog::OnInit() | |||
| 506 | SetItemTextA(IDT_BENCH_SYS1, s); | 500 | SetItemTextA(IDT_BENCH_SYS1, s); |
| 507 | if (s != s2 && !s2.IsEmpty()) | 501 | if (s != s2 && !s2.IsEmpty()) |
| 508 | SetItemTextA(IDT_BENCH_SYS2, s2); | 502 | SetItemTextA(IDT_BENCH_SYS2, s2); |
| 509 | } | 503 | |
| 510 | { | 504 | GetCpuName_MultiLine(s, s2); // s2==registers |
| 511 | AString registers; | ||
| 512 | GetCpuName_MultiLine(s, registers); | ||
| 513 | SetItemTextA(IDT_BENCH_CPU, s); | 505 | SetItemTextA(IDT_BENCH_CPU, s); |
| 514 | } | 506 | } |
| 515 | { | 507 | { |
| @@ -526,22 +518,18 @@ bool CBenchmarkDialog::OnInit() | |||
| 526 | 518 | ||
| 527 | // ----- Num Threads ---------- | 519 | // ----- Num Threads ---------- |
| 528 | 520 | ||
| 529 | if (numCPUs < 1) | ||
| 530 | numCPUs = 1; | ||
| 531 | numCPUs = MyMin(numCPUs, (UInt32)(1 << 6)); // it's WIN32 limit | ||
| 532 | |||
| 533 | UInt32 numThreads = Sync.NumThreads; | 521 | UInt32 numThreads = Sync.NumThreads; |
| 534 | |||
| 535 | if (numThreads == (UInt32)(Int32)-1) | 522 | if (numThreads == (UInt32)(Int32)-1) |
| 536 | numThreads = numCPUs; | 523 | numThreads = numCPUs; |
| 537 | if (numThreads > 1) | 524 | numThreads &= ~(UInt32)1; |
| 538 | numThreads &= ~(UInt32)1; | 525 | if (numThreads == 0) |
| 539 | const UInt32 kNumThreadsMax = (1 << 12); | 526 | numThreads = 1; |
| 540 | if (numThreads > kNumThreadsMax) | 527 | numThreads = MyMin(numThreads, (UInt32)(1u << 14)); |
| 541 | numThreads = kNumThreadsMax; | ||
| 542 | 528 | ||
| 543 | m_NumThreads.Attach(GetItem(IDC_BENCH_NUM_THREADS)); | 529 | m_NumThreads.Attach(GetItem(IDC_BENCH_NUM_THREADS)); |
| 544 | const UInt32 numTheads_Combo = numCPUs * 2; | 530 | if (numCPUs_Sys == 0) |
| 531 | numCPUs_Sys = 1; | ||
| 532 | const UInt32 numTheads_Combo = numCPUs_Sys * 2; | ||
| 545 | UInt32 v = 1; | 533 | UInt32 v = 1; |
| 546 | int cur = 0; | 534 | int cur = 0; |
| 547 | for (; v <= numTheads_Combo;) | 535 | for (; v <= numTheads_Combo;) |
| @@ -1069,16 +1057,17 @@ static void AddUsageString(UString &s, const CTotalBenchRes &info) | |||
| 1069 | numIter = 1000000; | 1057 | numIter = 1000000; |
| 1070 | UInt64 usage = GetUsagePercents(info.Usage / numIter); | 1058 | UInt64 usage = GetUsagePercents(info.Usage / numIter); |
| 1071 | 1059 | ||
| 1072 | wchar_t w[64]; | 1060 | wchar_t w[32]; |
| 1073 | ConvertUInt64ToString(usage, w); | 1061 | wchar_t *p = ConvertUInt64ToString(usage, w); |
| 1074 | unsigned len = MyStringLen(w); | 1062 | p[0] = '%'; |
| 1063 | p[1] = 0; | ||
| 1064 | unsigned len = (unsigned)(size_t)(p - w); | ||
| 1075 | while (len < 5) | 1065 | while (len < 5) |
| 1076 | { | 1066 | { |
| 1077 | s.Add_Space(); | 1067 | s.Add_Space(); |
| 1078 | len++; | 1068 | len++; |
| 1079 | } | 1069 | } |
| 1080 | s += w; | 1070 | s += w; |
| 1081 | s += "%"; | ||
| 1082 | } | 1071 | } |
| 1083 | 1072 | ||
| 1084 | 1073 | ||
diff --git a/CPP/7zip/UI/GUI/CompressDialog.cpp b/CPP/7zip/UI/GUI/CompressDialog.cpp index 85d7186..53e56fe 100644 --- a/CPP/7zip/UI/GUI/CompressDialog.cpp +++ b/CPP/7zip/UI/GUI/CompressDialog.cpp | |||
| @@ -506,8 +506,7 @@ bool CCompressDialog::OnInit() | |||
| 506 | { | 506 | { |
| 507 | const unsigned arcIndex = ArcIndices[i]; | 507 | const unsigned arcIndex = ArcIndices[i]; |
| 508 | const CArcInfoEx &ai = (*ArcFormats)[arcIndex]; | 508 | const CArcInfoEx &ai = (*ArcFormats)[arcIndex]; |
| 509 | const int index = (int)m_Format.AddString(ai.Name); | 509 | const int index = (int)m_Format.AddString_SetItemData(ai.Name, (LPARAM)arcIndex); |
| 510 | m_Format.SetItemData(index, (LPARAM)arcIndex); | ||
| 511 | if (!needSetMain) | 510 | if (!needSetMain) |
| 512 | { | 511 | { |
| 513 | if (Info.FormatIndex == (int)arcIndex) | 512 | if (Info.FormatIndex == (int)arcIndex) |
| @@ -540,11 +539,6 @@ bool CCompressDialog::OnInit() | |||
| 540 | AddComboItems(m_PathMode, k_PathMode_IDs, Z7_ARRAY_SIZE(k_PathMode_IDs), | 539 | AddComboItems(m_PathMode, k_PathMode_IDs, Z7_ARRAY_SIZE(k_PathMode_IDs), |
| 541 | k_PathMode_Vals, Info.PathMode); | 540 | k_PathMode_Vals, Info.PathMode); |
| 542 | 541 | ||
| 543 | |||
| 544 | TCHAR s[32] = { TEXT('/'), TEXT(' '), 0 }; | ||
| 545 | ConvertUInt32ToString(NSystem::GetNumberOfProcessors(), s + 2); | ||
| 546 | SetItemText(IDT_COMPRESS_HARDWARE_THREADS, s); | ||
| 547 | |||
| 548 | CheckButton(IDX_COMPRESS_SHARED, Info.OpenShareForWrite); | 542 | CheckButton(IDX_COMPRESS_SHARED, Info.OpenShareForWrite); |
| 549 | CheckButton(IDX_COMPRESS_DEL, Info.DeleteAfterCompressing); | 543 | CheckButton(IDX_COMPRESS_DEL, Info.DeleteAfterCompressing); |
| 550 | 544 | ||
| @@ -653,7 +647,19 @@ void CCompressDialog::EnableMultiCombo(unsigned id) | |||
| 653 | EnableItem(id, enable); | 647 | EnableItem(id, enable); |
| 654 | } | 648 | } |
| 655 | 649 | ||
| 656 | static LRESULT ComboBox_AddStringAscii(NControl::CComboBox &cb, const char *s); | 650 | static LRESULT ComboBox_AddStringAscii(NControl::CComboBox &cb, const char *s) |
| 651 | { | ||
| 652 | return cb.AddString((CSysString)s); | ||
| 653 | } | ||
| 654 | |||
| 655 | static LRESULT ComboBox_AddStringAscii_SetItemData(NControl::CComboBox &cb, | ||
| 656 | const char *s, LPARAM lParam) | ||
| 657 | { | ||
| 658 | const LRESULT index = ComboBox_AddStringAscii(cb, s); | ||
| 659 | if (index >= 0) // optional check | ||
| 660 | cb.SetItemData((int)index, lParam); | ||
| 661 | return index; | ||
| 662 | } | ||
| 657 | 663 | ||
| 658 | static void Combine_Two_BoolPairs(const CBoolPair &b1, const CBoolPair &b2, CBool1 &res) | 664 | static void Combine_Two_BoolPairs(const CBoolPair &b1, const CBoolPair &b2, CBool1 &res) |
| 659 | { | 665 | { |
| @@ -1604,20 +1610,14 @@ void CCompressDialog::SetLevel2() | |||
| 1604 | AddLangString(s, langID); | 1610 | AddLangString(s, langID); |
| 1605 | } | 1611 | } |
| 1606 | } | 1612 | } |
| 1607 | const int index = (int)m_Level.AddString(s); | 1613 | m_Level.AddString_SetItemData(s, (LPARAM)i); |
| 1608 | m_Level.SetItemData(index, (LPARAM)i); | ||
| 1609 | } | 1614 | } |
| 1610 | } | 1615 | } |
| 1611 | SetNearestSelectComboBox(m_Level, level); | 1616 | SetNearestSelectComboBox(m_Level, level); |
| 1612 | } | 1617 | } |
| 1613 | 1618 | ||
| 1614 | 1619 | ||
| 1615 | static LRESULT ComboBox_AddStringAscii(NControl::CComboBox &cb, const char *s) | 1620 | static const char * const k_Auto_Prefix = "* "; |
| 1616 | { | ||
| 1617 | return cb.AddString((CSysString)s); | ||
| 1618 | } | ||
| 1619 | |||
| 1620 | static const char *k_Auto_Prefix = "* "; | ||
| 1621 | 1621 | ||
| 1622 | static void Modify_Auto(AString &s) | 1622 | static void Modify_Auto(AString &s) |
| 1623 | { | 1623 | { |
| @@ -1690,8 +1690,8 @@ void CCompressDialog::SetMethod2(int keepMethodId) | |||
| 1690 | writtenMethodId = -1; | 1690 | writtenMethodId = -1; |
| 1691 | Modify_Auto(s); | 1691 | Modify_Auto(s); |
| 1692 | } | 1692 | } |
| 1693 | const int itemIndex = (int)ComboBox_AddStringAscii(m_Method, s); | 1693 | const int itemIndex = (int)ComboBox_AddStringAscii_SetItemData(m_Method, |
| 1694 | m_Method.SetItemData(itemIndex, writtenMethodId); | 1694 | s, writtenMethodId); |
| 1695 | if (keepMethodId == methodID) | 1695 | if (keepMethodId == methodID) |
| 1696 | { | 1696 | { |
| 1697 | m_Method.SetCurSel(itemIndex); | 1697 | m_Method.SetCurSel(itemIndex); |
| @@ -1731,7 +1731,7 @@ void CCompressDialog::SetEncryptionMethod() | |||
| 1731 | } | 1731 | } |
| 1732 | else if (ai.Is_Zip()) | 1732 | else if (ai.Is_Zip()) |
| 1733 | { | 1733 | { |
| 1734 | int index = FindRegistryFormat(ai.Name); | 1734 | const int index = FindRegistryFormat(ai.Name); |
| 1735 | UString encryptionMethod; | 1735 | UString encryptionMethod; |
| 1736 | if (index >= 0) | 1736 | if (index >= 0) |
| 1737 | { | 1737 | { |
| @@ -1836,9 +1836,7 @@ static int Combo_AddDict2(NWindows::NControl::CComboBox &cb, size_t sizeReal, si | |||
| 1836 | s.Add_Char('B'); | 1836 | s.Add_Char('B'); |
| 1837 | if (sizeReal == k_Auto_Dict) | 1837 | if (sizeReal == k_Auto_Dict) |
| 1838 | Modify_Auto(s); | 1838 | Modify_Auto(s); |
| 1839 | const int index = (int)ComboBox_AddStringAscii(cb, s); | 1839 | return (int)ComboBox_AddStringAscii_SetItemData(cb, s, (LPARAM)sizeReal); |
| 1840 | cb.SetItemData(index, (LPARAM)sizeReal); | ||
| 1841 | return index; | ||
| 1842 | } | 1840 | } |
| 1843 | 1841 | ||
| 1844 | int CCompressDialog::AddDict2(size_t sizeReal, size_t sizeShow) | 1842 | int CCompressDialog::AddDict2(size_t sizeReal, size_t sizeShow) |
| @@ -2201,9 +2199,7 @@ int CCompressDialog::AddOrder(UInt32 size) | |||
| 2201 | { | 2199 | { |
| 2202 | char s[32]; | 2200 | char s[32]; |
| 2203 | ConvertUInt32ToString(size, s); | 2201 | ConvertUInt32ToString(size, s); |
| 2204 | const int index = (int)ComboBox_AddStringAscii(m_Order, s); | 2202 | return (int)ComboBox_AddStringAscii_SetItemData(m_Order, s, (LPARAM)size); |
| 2205 | m_Order.SetItemData(index, (LPARAM)size); | ||
| 2206 | return index; | ||
| 2207 | } | 2203 | } |
| 2208 | 2204 | ||
| 2209 | int CCompressDialog::AddOrder_Auto() | 2205 | int CCompressDialog::AddOrder_Auto() |
| @@ -2211,9 +2207,7 @@ int CCompressDialog::AddOrder_Auto() | |||
| 2211 | AString s; | 2207 | AString s; |
| 2212 | s.Add_UInt32(_auto_Order); | 2208 | s.Add_UInt32(_auto_Order); |
| 2213 | Modify_Auto(s); | 2209 | Modify_Auto(s); |
| 2214 | int index = (int)ComboBox_AddStringAscii(m_Order, s); | 2210 | return (int)ComboBox_AddStringAscii_SetItemData(m_Order, s, (LPARAM)(INT_PTR)(-1)); |
| 2215 | m_Order.SetItemData(index, (LPARAM)(INT_PTR)(-1)); | ||
| 2216 | return index; | ||
| 2217 | } | 2211 | } |
| 2218 | 2212 | ||
| 2219 | void CCompressDialog::SetOrder2() | 2213 | void CCompressDialog::SetOrder2() |
| @@ -2490,9 +2484,7 @@ void CCompressDialog::SetSolidBlockSize2() | |||
| 2490 | AString s; | 2484 | AString s; |
| 2491 | Add_Size(s, _auto_Solid); | 2485 | Add_Size(s, _auto_Solid); |
| 2492 | Modify_Auto(s); | 2486 | Modify_Auto(s); |
| 2493 | const int index = (int)ComboBox_AddStringAscii(m_Solid, s); | 2487 | curSel = (int)ComboBox_AddStringAscii_SetItemData(m_Solid, s, (LPARAM)(UInt32)(Int32)-1); |
| 2494 | m_Solid.SetItemData(index, (LPARAM)(UInt32)(Int32)-1); | ||
| 2495 | curSel = index; | ||
| 2496 | } | 2488 | } |
| 2497 | 2489 | ||
| 2498 | if (is7z) | 2490 | if (is7z) |
| @@ -2501,8 +2493,7 @@ void CCompressDialog::SetSolidBlockSize2() | |||
| 2501 | // kSolidLog_NoSolid = 0 for xz means default blockSize | 2493 | // kSolidLog_NoSolid = 0 for xz means default blockSize |
| 2502 | if (is7z) | 2494 | if (is7z) |
| 2503 | LangString(IDS_COMPRESS_NON_SOLID, s); | 2495 | LangString(IDS_COMPRESS_NON_SOLID, s); |
| 2504 | const int index = (int)m_Solid.AddString(s); | 2496 | const int index = (int)m_Solid.AddString_SetItemData(s, (LPARAM)(UInt32)kSolidLog_NoSolid); |
| 2505 | m_Solid.SetItemData(index, (LPARAM)(UInt32)kSolidLog_NoSolid); | ||
| 2506 | if (defaultBlockSize == kSolidLog_NoSolid) | 2497 | if (defaultBlockSize == kSolidLog_NoSolid) |
| 2507 | curSel = index; | 2498 | curSel = index; |
| 2508 | } | 2499 | } |
| @@ -2511,16 +2502,15 @@ void CCompressDialog::SetSolidBlockSize2() | |||
| 2511 | { | 2502 | { |
| 2512 | AString s; | 2503 | AString s; |
| 2513 | Add_Size(s, (UInt64)1 << i); | 2504 | Add_Size(s, (UInt64)1 << i); |
| 2514 | const int index = (int)ComboBox_AddStringAscii(m_Solid, s); | 2505 | const int index = (int)ComboBox_AddStringAscii_SetItemData(m_Solid, s, (LPARAM)(UInt32)i); |
| 2515 | m_Solid.SetItemData(index, (LPARAM)(UInt32)i); | ||
| 2516 | if (defaultBlockSize != (UInt32)(Int32)-1) | 2506 | if (defaultBlockSize != (UInt32)(Int32)-1) |
| 2517 | if (i <= defaultBlockSize || index <= 1) | 2507 | if (i <= defaultBlockSize || index <= 1) |
| 2518 | curSel = index; | 2508 | curSel = index; |
| 2519 | } | 2509 | } |
| 2520 | 2510 | ||
| 2521 | { | 2511 | { |
| 2522 | const int index = (int)m_Solid.AddString(LangString(IDS_COMPRESS_SOLID)); | 2512 | const int index = (int)m_Solid.AddString_SetItemData( |
| 2523 | m_Solid.SetItemData(index, (LPARAM)kSolidLog_FullSolid); | 2513 | LangString(IDS_COMPRESS_SOLID), (LPARAM)kSolidLog_FullSolid); |
| 2524 | if (defaultBlockSize == kSolidLog_FullSolid) | 2514 | if (defaultBlockSize == kSolidLog_FullSolid) |
| 2525 | curSel = index; | 2515 | curSel = index; |
| 2526 | } | 2516 | } |
| @@ -2564,7 +2554,7 @@ static bool Is_Zstd_Mt_Supported() | |||
| 2564 | } | 2554 | } |
| 2565 | */ | 2555 | */ |
| 2566 | 2556 | ||
| 2567 | static const char *k_ST_Threads = " (ST)"; | 2557 | static const char * const k_ST_Threads = " (ST)"; |
| 2568 | 2558 | ||
| 2569 | void CCompressDialog::SetNumThreads2() | 2559 | void CCompressDialog::SetNumThreads2() |
| 2570 | { | 2560 | { |
| @@ -2575,15 +2565,31 @@ void CCompressDialog::SetNumThreads2() | |||
| 2575 | if (!fi.MultiThread_()) | 2565 | if (!fi.MultiThread_()) |
| 2576 | return; | 2566 | return; |
| 2577 | 2567 | ||
| 2578 | const UInt32 numHardwareThreads = NSystem::GetNumberOfProcessors(); | 2568 | UInt32 numCPUs = 1; // process threads |
| 2579 | // 64; // for debug: | 2569 | UInt32 numHardwareThreads = 1; // system threads |
| 2570 | NSystem::CProcessAffinity threadsInfo; | ||
| 2571 | threadsInfo.InitST(); | ||
| 2572 | #ifndef Z7_ST | ||
| 2573 | threadsInfo.Get_and_return_NumProcessThreads_and_SysThreads(numCPUs, numHardwareThreads); | ||
| 2574 | #endif | ||
| 2580 | 2575 | ||
| 2581 | UInt32 defaultValue = numHardwareThreads; | 2576 | AString s ("/ "); |
| 2577 | { | ||
| 2578 | s.Add_UInt32(numCPUs); | ||
| 2579 | if (numCPUs != numHardwareThreads) | ||
| 2580 | { | ||
| 2581 | s += " / "; | ||
| 2582 | s.Add_UInt32(numHardwareThreads); | ||
| 2583 | } | ||
| 2584 | SetItemTextA(IDT_COMPRESS_HARDWARE_THREADS, s.Ptr()); | ||
| 2585 | } | ||
| 2586 | |||
| 2587 | UInt32 defaultValue = numCPUs; | ||
| 2582 | bool useAutoThreads = true; | 2588 | bool useAutoThreads = true; |
| 2583 | 2589 | ||
| 2584 | { | 2590 | { |
| 2585 | const CArcInfoEx &ai = Get_ArcInfoEx(); | 2591 | const CArcInfoEx &ai = Get_ArcInfoEx(); |
| 2586 | int index = FindRegistryFormat(ai.Name); | 2592 | const int index = FindRegistryFormat(ai.Name); |
| 2587 | if (index >= 0) | 2593 | if (index >= 0) |
| 2588 | { | 2594 | { |
| 2589 | const NCompression::CFormatOptions &fo = m_RegistryInfo.Formats[index]; | 2595 | const NCompression::CFormatOptions &fo = m_RegistryInfo.Formats[index]; |
| @@ -2597,19 +2603,19 @@ void CCompressDialog::SetNumThreads2() | |||
| 2597 | 2603 | ||
| 2598 | // const UInt32 num_ZSTD_threads_MAX = Is_Zstd_Mt_Supported() ? MY_ZSTDMT_NBWORKERS_MAX : 0; | 2604 | // const UInt32 num_ZSTD_threads_MAX = Is_Zstd_Mt_Supported() ? MY_ZSTDMT_NBWORKERS_MAX : 0; |
| 2599 | 2605 | ||
| 2600 | UInt32 numAlgoThreadsMax = numHardwareThreads * 2; | ||
| 2601 | const int methodID = GetMethodID(); | 2606 | const int methodID = GetMethodID(); |
| 2602 | |||
| 2603 | const bool isZip = IsZipFormat(); | 2607 | const bool isZip = IsZipFormat(); |
| 2608 | |||
| 2609 | UInt32 numAlgoThreadsMax = numHardwareThreads * 2; // for unknow methods | ||
| 2604 | if (isZip) | 2610 | if (isZip) |
| 2605 | numAlgoThreadsMax = | 2611 | numAlgoThreadsMax = |
| 2606 | 8 << (sizeof(size_t) / 2); // 32 threads for 32-bit : 128 threads for 64-bit | 2612 | 8 << (sizeof(size_t) / 2); // 32 threads for 32-bit : 128 threads for 64-bit |
| 2607 | else if (IsXzFormat()) | 2613 | else if (IsXzFormat()) |
| 2608 | numAlgoThreadsMax = 256 * 2; | 2614 | numAlgoThreadsMax = 256 * 2; // MTCODER_THREADS_MAX * 2 |
| 2609 | else switch (methodID) | 2615 | else switch (methodID) |
| 2610 | { | 2616 | { |
| 2611 | case kLZMA: numAlgoThreadsMax = 2; break; | 2617 | case kLZMA: numAlgoThreadsMax = 2; break; |
| 2612 | case kLZMA2: numAlgoThreadsMax = 256; break; | 2618 | case kLZMA2: numAlgoThreadsMax = 256 * 2; break; // MTCODER_THREADS_MAX * 2 |
| 2613 | case kBZip2: numAlgoThreadsMax = 64; break; | 2619 | case kBZip2: numAlgoThreadsMax = 64; break; |
| 2614 | // case kZSTD: numAlgoThreadsMax = num_ZSTD_threads_MAX; break; | 2620 | // case kZSTD: numAlgoThreadsMax = num_ZSTD_threads_MAX; break; |
| 2615 | case kCopy: | 2621 | case kCopy: |
| @@ -2619,9 +2625,9 @@ void CCompressDialog::SetNumThreads2() | |||
| 2619 | case kPPMdZip: | 2625 | case kPPMdZip: |
| 2620 | numAlgoThreadsMax = 1; | 2626 | numAlgoThreadsMax = 1; |
| 2621 | } | 2627 | } |
| 2622 | UInt32 autoThreads = numHardwareThreads; | 2628 | UInt32 autoThreads = numCPUs; |
| 2623 | if (autoThreads > numAlgoThreadsMax) | 2629 | if (autoThreads > numAlgoThreadsMax) |
| 2624 | autoThreads = numAlgoThreadsMax; | 2630 | autoThreads = numAlgoThreadsMax; |
| 2625 | 2631 | ||
| 2626 | const UInt64 memUse_Limit = Get_MemUse_Bytes(); | 2632 | const UInt64 memUse_Limit = Get_MemUse_Bytes(); |
| 2627 | 2633 | ||
| @@ -2676,13 +2682,12 @@ void CCompressDialog::SetNumThreads2() | |||
| 2676 | 2682 | ||
| 2677 | int curSel = -1; | 2683 | int curSel = -1; |
| 2678 | { | 2684 | { |
| 2679 | AString s; | 2685 | s.Empty(); |
| 2680 | s.Add_UInt32(autoThreads); | 2686 | s.Add_UInt32(autoThreads); |
| 2681 | if (autoThreads == 0) s += k_ST_Threads; | 2687 | if (autoThreads == 0) s += k_ST_Threads; |
| 2682 | Modify_Auto(s); | 2688 | Modify_Auto(s); |
| 2683 | const int index = (int)ComboBox_AddStringAscii(m_NumThreads, s); | 2689 | const int index = (int)ComboBox_AddStringAscii_SetItemData(m_NumThreads, |
| 2684 | m_NumThreads.SetItemData(index, (LPARAM)(INT_PTR)(-1)); | 2690 | s, (LPARAM)(INT_PTR)(-1)); |
| 2685 | // m_NumThreads.SetItemData(index, autoThreads); | ||
| 2686 | if (useAutoThreads) | 2691 | if (useAutoThreads) |
| 2687 | curSel = index; | 2692 | curSel = index; |
| 2688 | } | 2693 | } |
| @@ -2693,11 +2698,11 @@ void CCompressDialog::SetNumThreads2() | |||
| 2693 | 1; | 2698 | 1; |
| 2694 | i <= numHardwareThreads * 2 && i <= numAlgoThreadsMax; i++) | 2699 | i <= numHardwareThreads * 2 && i <= numAlgoThreadsMax; i++) |
| 2695 | { | 2700 | { |
| 2696 | AString s; | 2701 | s.Empty(); |
| 2697 | s.Add_UInt32(i); | 2702 | s.Add_UInt32(i); |
| 2698 | if (i == 0) s += k_ST_Threads; | 2703 | if (i == 0) s += k_ST_Threads; |
| 2699 | const int index = (int)ComboBox_AddStringAscii(m_NumThreads, s); | 2704 | const int index = (int)ComboBox_AddStringAscii_SetItemData(m_NumThreads, |
| 2700 | m_NumThreads.SetItemData(index, (LPARAM)(UInt32)i); | 2705 | s, (LPARAM)(UInt32)i); |
| 2701 | if (!useAutoThreads && i == defaultValue) | 2706 | if (!useAutoThreads && i == defaultValue) |
| 2702 | curSel = index; | 2707 | curSel = index; |
| 2703 | } | 2708 | } |
| @@ -2754,9 +2759,7 @@ int CCompressDialog::AddMemComboItem(UInt64 val, bool isPercent, bool isDefault) | |||
| 2754 | sRegistry.DeleteBack(); | 2759 | sRegistry.DeleteBack(); |
| 2755 | } | 2760 | } |
| 2756 | const unsigned dataIndex = _memUse_Strings.Add(sRegistry); | 2761 | const unsigned dataIndex = _memUse_Strings.Add(sRegistry); |
| 2757 | const int index = (int)m_MemUse.AddString(sUser); | 2762 | return (int)m_MemUse.AddString_SetItemData(sUser, (LPARAM)dataIndex); |
| 2758 | m_MemUse.SetItemData(index, (LPARAM)dataIndex); | ||
| 2759 | return index; | ||
| 2760 | } | 2763 | } |
| 2761 | 2764 | ||
| 2762 | 2765 | ||
| @@ -3439,11 +3442,7 @@ static const unsigned kTimePrec_1ns = 3; | |||
| 3439 | static void AddTimeOption(UString &s, UInt32 val, const UString &unit, const char *sys = NULL) | 3442 | static void AddTimeOption(UString &s, UInt32 val, const UString &unit, const char *sys = NULL) |
| 3440 | { | 3443 | { |
| 3441 | // s += " : "; | 3444 | // s += " : "; |
| 3442 | { | 3445 | s.Add_UInt32(val); |
| 3443 | AString s2; | ||
| 3444 | s2.Add_UInt32(val); | ||
| 3445 | s += s2; | ||
| 3446 | } | ||
| 3447 | s.Add_Space(); | 3446 | s.Add_Space(); |
| 3448 | s += unit; | 3447 | s += unit; |
| 3449 | if (sys) | 3448 | if (sys) |
| @@ -3476,9 +3475,7 @@ int COptionsDialog::AddPrec(unsigned prec, bool isDefault) | |||
| 3476 | } | 3475 | } |
| 3477 | else | 3476 | else |
| 3478 | s.Add_UInt32(prec); | 3477 | s.Add_UInt32(prec); |
| 3479 | const int index = (int)m_Prec.AddString(s); | 3478 | return (int)m_Prec.AddString_SetItemData(s, (LPARAM)writePrec); |
| 3480 | m_Prec.SetItemData(index, (LPARAM)writePrec); | ||
| 3481 | return index; | ||
| 3482 | } | 3479 | } |
| 3483 | 3480 | ||
| 3484 | 3481 | ||
diff --git a/CPP/7zip/UI/GUI/CompressDialog.rc b/CPP/7zip/UI/GUI/CompressDialog.rc index 9c3ed88..df1516c 100644 --- a/CPP/7zip/UI/GUI/CompressDialog.rc +++ b/CPP/7zip/UI/GUI/CompressDialog.rc | |||
| @@ -87,8 +87,8 @@ BEGIN | |||
| 87 | COMBOBOX IDC_COMPRESS_SOLID, g1x, 144, g1xs, 140, MY_COMBO | 87 | COMBOBOX IDC_COMPRESS_SOLID, g1x, 144, g1xs, 140, MY_COMBO |
| 88 | 88 | ||
| 89 | LTEXT "Number of CPU &threads:", IDT_COMPRESS_THREADS, m, 167, g0xs, 8 | 89 | LTEXT "Number of CPU &threads:", IDT_COMPRESS_THREADS, m, 167, g0xs, 8 |
| 90 | COMBOBOX IDC_COMPRESS_THREADS, g1x, 165, g1xs - 35, 140, MY_COMBO | 90 | COMBOBOX IDC_COMPRESS_THREADS, g1x, 165, g1xs - 40, 140, MY_COMBO |
| 91 | RTEXT "", IDT_COMPRESS_HARDWARE_THREADS, g1x + g1xs - 35 + 10, 167, 25, MY_TEXT_NOPREFIX | 91 | RTEXT "", IDT_COMPRESS_HARDWARE_THREADS, g1x + g1xs - 40, 167, 40, 16, SS_NOPREFIX |
| 92 | 92 | ||
| 93 | 93 | ||
| 94 | LTEXT "Memory usage for Compressing:", IDT_COMPRESS_MEMORY, m, 184, g2xs, 8 | 94 | LTEXT "Memory usage for Compressing:", IDT_COMPRESS_MEMORY, m, 184, g2xs, 8 |
diff --git a/CPP/7zip/UI/GUI/ExtractDialog.cpp b/CPP/7zip/UI/GUI/ExtractDialog.cpp index 4628482..467cf18 100644 --- a/CPP/7zip/UI/GUI/ExtractDialog.cpp +++ b/CPP/7zip/UI/GUI/ExtractDialog.cpp | |||
| @@ -102,8 +102,7 @@ void AddComboItems(NControl::CComboBox &combo, const UInt32 *langIDs, unsigned n | |||
| 102 | { | 102 | { |
| 103 | UString s = LangString(langIDs[i]); | 103 | UString s = LangString(langIDs[i]); |
| 104 | s.RemoveChar(L'&'); | 104 | s.RemoveChar(L'&'); |
| 105 | const int index = (int)combo.AddString(s); | 105 | combo.AddString_SetItemData(s, (LPARAM)i); |
| 106 | combo.SetItemData(index, (LPARAM)i); | ||
| 107 | if (values[i] == curVal) | 106 | if (values[i] == curVal) |
| 108 | curSel = i; | 107 | curSel = i; |
| 109 | } | 108 | } |
diff --git a/CPP/Common/Common0.h b/CPP/Common/Common0.h index 55606cd..5781a95 100644 --- a/CPP/Common/Common0.h +++ b/CPP/Common/Common0.h | |||
| @@ -126,8 +126,9 @@ if compiled with new GCC libstdc++, GCC libstdc++ can use: | |||
| 126 | #pragma GCC diagnostic ignored "-Wglobal-constructors" | 126 | #pragma GCC diagnostic ignored "-Wglobal-constructors" |
| 127 | #pragma GCC diagnostic ignored "-Wexit-time-destructors" | 127 | #pragma GCC diagnostic ignored "-Wexit-time-destructors" |
| 128 | 128 | ||
| 129 | #if defined(Z7_LLVM_CLANG_VERSION) && __clang_major__ >= 18 // 18.1.0RC | 129 | #if defined(Z7_LLVM_CLANG_VERSION) && __clang_major__ >= 18 /* 18.1.0RC */ \ |
| 130 | #pragma GCC diagnostic ignored "-Wswitch-default" | 130 | || defined(Z7_APPLE_CLANG_VERSION) && __clang_major__ >= 16 // for APPLE=17 (LLVM=19) |
| 131 | #pragma GCC diagnostic ignored "-Wswitch-default" | ||
| 131 | #endif | 132 | #endif |
| 132 | // #pragma GCC diagnostic ignored "-Wunused-private-field" | 133 | // #pragma GCC diagnostic ignored "-Wunused-private-field" |
| 133 | // #pragma GCC diagnostic ignored "-Wnonportable-system-include-path" | 134 | // #pragma GCC diagnostic ignored "-Wnonportable-system-include-path" |
diff --git a/CPP/Common/MyBuffer.h b/CPP/Common/MyBuffer.h index 80f0205..08c10a3 100644 --- a/CPP/Common/MyBuffer.h +++ b/CPP/Common/MyBuffer.h | |||
| @@ -202,7 +202,53 @@ public: | |||
| 202 | } | 202 | } |
| 203 | }; | 203 | }; |
| 204 | 204 | ||
| 205 | typedef CObjArray<Byte> CByteArr; | 205 | |
| 206 | /* CSmallObjArray can be used for Byte arrays | ||
| 207 | or for arrays whose total size in bytes does not exceed size_t ranges. | ||
| 208 | So there is no need to use Z7_ARRAY_NEW macro in CSmallObjArray code. */ | ||
| 209 | template <class T> class CSmallObjArray | ||
| 210 | { | ||
| 211 | protected: | ||
| 212 | T *_items; | ||
| 213 | private: | ||
| 214 | // we disable copy | ||
| 215 | CSmallObjArray(const CSmallObjArray &buffer); | ||
| 216 | void operator=(const CSmallObjArray &buffer); | ||
| 217 | public: | ||
| 218 | void Free() | ||
| 219 | { | ||
| 220 | delete []_items; | ||
| 221 | _items = NULL; | ||
| 222 | } | ||
| 223 | CSmallObjArray(size_t size): _items(NULL) | ||
| 224 | { | ||
| 225 | if (size != 0) | ||
| 226 | { | ||
| 227 | // Z7_ARRAY_NEW(_items, T, size) | ||
| 228 | _items = new T[size]; | ||
| 229 | } | ||
| 230 | } | ||
| 231 | CSmallObjArray(): _items(NULL) {} | ||
| 232 | ~CSmallObjArray() { delete []_items; } | ||
| 233 | |||
| 234 | operator T *() { return _items; } | ||
| 235 | operator const T *() const { return _items; } | ||
| 236 | const T* ConstData() const { return _items; } | ||
| 237 | T* NonConstData() const { return _items; } | ||
| 238 | T* NonConstData() { return _items; } | ||
| 239 | // const T* Data() const { return _items; } | ||
| 240 | // T* Data() { return _items; } | ||
| 241 | |||
| 242 | void Alloc(size_t newSize) | ||
| 243 | { | ||
| 244 | delete []_items; | ||
| 245 | _items = NULL; | ||
| 246 | // Z7_ARRAY_NEW(_items, T, newSize) | ||
| 247 | _items = new T[newSize]; | ||
| 248 | } | ||
| 249 | }; | ||
| 250 | |||
| 251 | typedef CSmallObjArray<Byte> CByteArr; | ||
| 206 | typedef CObjArray<bool> CBoolArr; | 252 | typedef CObjArray<bool> CBoolArr; |
| 207 | typedef CObjArray<int> CIntArr; | 253 | typedef CObjArray<int> CIntArr; |
| 208 | typedef CObjArray<unsigned> CUIntArr; | 254 | typedef CObjArray<unsigned> CUIntArr; |
diff --git a/CPP/Windows/Control/ComboBox.cpp b/CPP/Windows/Control/ComboBox.cpp index 8da487d..2e9c8cb 100644 --- a/CPP/Windows/Control/ComboBox.cpp +++ b/CPP/Windows/Control/ComboBox.cpp | |||
| @@ -63,4 +63,13 @@ LRESULT CComboBox::GetLBText(int index, UString &s) | |||
| 63 | } | 63 | } |
| 64 | #endif | 64 | #endif |
| 65 | 65 | ||
| 66 | LRESULT CComboBox::AddString_SetItemData(LPCWSTR s, LPARAM lParam) | ||
| 67 | { | ||
| 68 | const LRESULT index = AddString(s); | ||
| 69 | // NOTE: SetItemData((int)-1, lParam) works as unexpected. | ||
| 70 | if (index >= 0) // optional check, because (index < 0) is not expected for normal inputs | ||
| 71 | SetItemData((int)index, lParam); | ||
| 72 | return index; | ||
| 73 | } | ||
| 74 | |||
| 66 | }} | 75 | }} |
diff --git a/CPP/Windows/Control/ComboBox.h b/CPP/Windows/Control/ComboBox.h index 2a60b8a..224efca 100644 --- a/CPP/Windows/Control/ComboBox.h +++ b/CPP/Windows/Control/ComboBox.h | |||
| @@ -21,6 +21,8 @@ public: | |||
| 21 | LRESULT AddString(LPCWSTR s); | 21 | LRESULT AddString(LPCWSTR s); |
| 22 | #endif | 22 | #endif |
| 23 | 23 | ||
| 24 | LRESULT AddString_SetItemData(LPCWSTR s, LPARAM lParam); | ||
| 25 | |||
| 24 | /* If this parameter is -1, any current selection in the list is removed and the edit control is cleared.*/ | 26 | /* If this parameter is -1, any current selection in the list is removed and the edit control is cleared.*/ |
| 25 | LRESULT SetCurSel(int index) { return SendMsg(CB_SETCURSEL, MY_int_TO_WPARAM(index), 0); } | 27 | LRESULT SetCurSel(int index) { return SendMsg(CB_SETCURSEL, MY_int_TO_WPARAM(index), 0); } |
| 26 | LRESULT SetCurSel(unsigned index) { return SendMsg(CB_SETCURSEL, index, 0); } | 28 | LRESULT SetCurSel(unsigned index) { return SendMsg(CB_SETCURSEL, index, 0); } |
diff --git a/CPP/Windows/FileFind.cpp b/CPP/Windows/FileFind.cpp index 64075ab..669541e 100644 --- a/CPP/Windows/FileFind.cpp +++ b/CPP/Windows/FileFind.cpp | |||
| @@ -1162,6 +1162,15 @@ void CFileInfoBase::SetFrom_stat(const struct stat &st) | |||
| 1162 | MTime = st.st_mtimespec; | 1162 | MTime = st.st_mtimespec; |
| 1163 | ATime = st.st_atimespec; | 1163 | ATime = st.st_atimespec; |
| 1164 | 1164 | ||
| 1165 | #elif defined(__QNXNTO__) && defined(__ARM__) && !defined(__aarch64__) | ||
| 1166 | |||
| 1167 | // CTime = ST_CTIME(st); | ||
| 1168 | // MTime = ST_MTIME(st); | ||
| 1169 | // ATime = ST_ATIME(st); | ||
| 1170 | CTime.tv_sec = st.st_ctime; CTime.tv_nsec = 0; | ||
| 1171 | MTime.tv_sec = st.st_mtime; MTime.tv_nsec = 0; | ||
| 1172 | ATime.tv_sec = st.st_atime; ATime.tv_nsec = 0; | ||
| 1173 | |||
| 1165 | #else | 1174 | #else |
| 1166 | // timespec_To_FILETIME(st.st_ctim, CTime, &CTime_ns100); | 1175 | // timespec_To_FILETIME(st.st_ctim, CTime, &CTime_ns100); |
| 1167 | // timespec_To_FILETIME(st.st_mtim, MTime, &MTime_ns100); | 1176 | // timespec_To_FILETIME(st.st_mtim, MTime, &MTime_ns100); |
| @@ -1312,7 +1321,7 @@ bool CDirEntry::IsDots() const throw() | |||
| 1312 | /* some systems (like CentOS 7.x on XFS) have (Type == DT_UNKNOWN) | 1321 | /* some systems (like CentOS 7.x on XFS) have (Type == DT_UNKNOWN) |
| 1313 | we can call fstatat() for that case, but we use only (Name) check here */ | 1322 | we can call fstatat() for that case, but we use only (Name) check here */ |
| 1314 | 1323 | ||
| 1315 | #if !defined(_AIX) && !defined(__sun) | 1324 | #if !defined(_AIX) && !defined(__sun) && !defined(__QNXNTO__) |
| 1316 | if (Type != DT_DIR && Type != DT_UNKNOWN) | 1325 | if (Type != DT_DIR && Type != DT_UNKNOWN) |
| 1317 | return false; | 1326 | return false; |
| 1318 | #endif | 1327 | #endif |
| @@ -1352,7 +1361,7 @@ bool CEnumerator::NextAny(CDirEntry &fi, bool &found) | |||
| 1352 | 1361 | ||
| 1353 | fi.iNode = de->d_ino; | 1362 | fi.iNode = de->d_ino; |
| 1354 | 1363 | ||
| 1355 | #if !defined(_AIX) && !defined(__sun) | 1364 | #if !defined(_AIX) && !defined(__sun) && !defined(__QNXNTO__) |
| 1356 | fi.Type = de->d_type; | 1365 | fi.Type = de->d_type; |
| 1357 | /* some systems (like CentOS 7.x on XFS) have (Type == DT_UNKNOWN) | 1366 | /* some systems (like CentOS 7.x on XFS) have (Type == DT_UNKNOWN) |
| 1358 | we can set (Type) from fstatat() in that case. | 1367 | we can set (Type) from fstatat() in that case. |
diff --git a/CPP/Windows/FileFind.h b/CPP/Windows/FileFind.h index f68673a..944bca2 100644 --- a/CPP/Windows/FileFind.h +++ b/CPP/Windows/FileFind.h | |||
| @@ -277,13 +277,13 @@ typedef CFileInfo CDirEntry; | |||
| 277 | struct CDirEntry | 277 | struct CDirEntry |
| 278 | { | 278 | { |
| 279 | ino_t iNode; | 279 | ino_t iNode; |
| 280 | #if !defined(_AIX) && !defined(__sun) | 280 | #if !defined(_AIX) && !defined(__sun) && !defined(__QNXNTO__) |
| 281 | Byte Type; | 281 | Byte Type; |
| 282 | #endif | 282 | #endif |
| 283 | FString Name; | 283 | FString Name; |
| 284 | 284 | ||
| 285 | /* | 285 | /* |
| 286 | #if !defined(_AIX) && !defined(__sun) | 286 | #if !defined(_AIX) && !defined(__sun) && !defined(__QNXNTO__) |
| 287 | bool IsDir() const | 287 | bool IsDir() const |
| 288 | { | 288 | { |
| 289 | // (Type == DT_UNKNOWN) on some systems | 289 | // (Type == DT_UNKNOWN) on some systems |
| @@ -310,7 +310,7 @@ public: | |||
| 310 | bool Fill_FileInfo(const CDirEntry &de, CFileInfo &fileInfo, bool followLink) const; | 310 | bool Fill_FileInfo(const CDirEntry &de, CFileInfo &fileInfo, bool followLink) const; |
| 311 | bool DirEntry_IsDir(const CDirEntry &de, bool followLink) const | 311 | bool DirEntry_IsDir(const CDirEntry &de, bool followLink) const |
| 312 | { | 312 | { |
| 313 | #if !defined(_AIX) && !defined(__sun) | 313 | #if !defined(_AIX) && !defined(__sun) && !defined(__QNXNTO__) |
| 314 | if (de.Type == DT_DIR) | 314 | if (de.Type == DT_DIR) |
| 315 | return true; | 315 | return true; |
| 316 | if (de.Type != DT_UNKNOWN) | 316 | if (de.Type != DT_UNKNOWN) |
diff --git a/CPP/Windows/SecurityUtils.h b/CPP/Windows/SecurityUtils.h index 7219f06..022a8f3 100644 --- a/CPP/Windows/SecurityUtils.h +++ b/CPP/Windows/SecurityUtils.h | |||
| @@ -3,7 +3,11 @@ | |||
| 3 | #ifndef ZIP7_INC_WINDOWS_SECURITY_UTILS_H | 3 | #ifndef ZIP7_INC_WINDOWS_SECURITY_UTILS_H |
| 4 | #define ZIP7_INC_WINDOWS_SECURITY_UTILS_H | 4 | #define ZIP7_INC_WINDOWS_SECURITY_UTILS_H |
| 5 | 5 | ||
| 6 | #if defined(__MINGW32__) || defined(__MINGW64__) | ||
| 7 | #include <ntsecapi.h> | ||
| 8 | #else | ||
| 6 | #include <NTSecAPI.h> | 9 | #include <NTSecAPI.h> |
| 10 | #endif | ||
| 7 | 11 | ||
| 8 | #include "Defs.h" | 12 | #include "Defs.h" |
| 9 | 13 | ||
diff --git a/CPP/Windows/System.cpp b/CPP/Windows/System.cpp index 4745785..6999ef9 100644 --- a/CPP/Windows/System.cpp +++ b/CPP/Windows/System.cpp | |||
| @@ -5,8 +5,9 @@ | |||
| 5 | #ifndef _WIN32 | 5 | #ifndef _WIN32 |
| 6 | #include <unistd.h> | 6 | #include <unistd.h> |
| 7 | #include <limits.h> | 7 | #include <limits.h> |
| 8 | #if defined(__APPLE__) || defined(__DragonFly__) || \ | 8 | #if defined(__APPLE__) || defined(__DragonFly__) \ |
| 9 | defined(BSD) || defined(__FreeBSD__) || defined(__NetBSD__) || defined(__OpenBSD__) | 9 | || defined(BSD) || defined(__FreeBSD__) || defined(__NetBSD__) || defined(__OpenBSD__) \ |
| 10 | || defined(__QNXNTO__) | ||
| 10 | #include <sys/sysctl.h> | 11 | #include <sys/sysctl.h> |
| 11 | #else | 12 | #else |
| 12 | #include <sys/sysinfo.h> | 13 | #include <sys/sysinfo.h> |
| @@ -299,8 +300,9 @@ bool GetRamSize(size_t &size) | |||
| 299 | size = (size_t)sizeof(size_t) << 29; | 300 | size = (size_t)sizeof(size_t) << 29; |
| 300 | size64 = size; | 301 | size64 = size; |
| 301 | 302 | ||
| 302 | #if defined(__APPLE__) || defined(__DragonFly__) || \ | 303 | #if defined(__APPLE__) || defined(__DragonFly__) \ |
| 303 | defined(BSD) || defined(__FreeBSD__) || defined(__NetBSD__) || defined(__OpenBSD__) | 304 | || defined(BSD) || defined(__FreeBSD__) || defined(__NetBSD__) || defined(__OpenBSD__) \ |
| 305 | || defined(__QNXNTO__) | ||
| 304 | 306 | ||
| 305 | uint64_t val = 0; | 307 | uint64_t val = 0; |
| 306 | int mib[2]; | 308 | int mib[2]; |
diff --git a/CPP/Windows/System.h b/CPP/Windows/System.h index 0c80373..041a44d 100644 --- a/CPP/Windows/System.h +++ b/CPP/Windows/System.h | |||
| @@ -15,6 +15,8 @@ | |||
| 15 | namespace NWindows { | 15 | namespace NWindows { |
| 16 | namespace NSystem { | 16 | namespace NSystem { |
| 17 | 17 | ||
| 18 | UInt32 GetNumberOfProcessors(); | ||
| 19 | |||
| 18 | #ifdef _WIN32 | 20 | #ifdef _WIN32 |
| 19 | 21 | ||
| 20 | struct CCpuGroups | 22 | struct CCpuGroups |
| @@ -103,6 +105,25 @@ struct CProcessAffinity | |||
| 103 | return CountAffinity(systemAffinityMask); | 105 | return CountAffinity(systemAffinityMask); |
| 104 | } | 106 | } |
| 105 | 107 | ||
| 108 | // it returns normilized number of threads | ||
| 109 | void Get_and_return_NumProcessThreads_and_SysThreads(UInt32 &numProcessThreads, UInt32 &numSysThreads) | ||
| 110 | { | ||
| 111 | UInt32 num1 = 0, num2 = 0; | ||
| 112 | if (Get()) | ||
| 113 | { | ||
| 114 | num1 = GetNumProcessThreads(); | ||
| 115 | num2 = GetNumSystemThreads(); | ||
| 116 | } | ||
| 117 | if (num1 == 0) | ||
| 118 | num1 = NSystem::GetNumberOfProcessors(); | ||
| 119 | if (num1 == 0) | ||
| 120 | num1 = 1; | ||
| 121 | if (num2 < num1) | ||
| 122 | num2 = num1; | ||
| 123 | numProcessThreads = num1; | ||
| 124 | numSysThreads = num2; | ||
| 125 | } | ||
| 126 | |||
| 106 | BOOL Get(); | 127 | BOOL Get(); |
| 107 | 128 | ||
| 108 | BOOL SetProcAffinity() const | 129 | BOOL SetProcAffinity() const |
| @@ -177,8 +198,6 @@ struct CProcessAffinity | |||
| 177 | #endif // _WIN32 | 198 | #endif // _WIN32 |
| 178 | 199 | ||
| 179 | 200 | ||
| 180 | UInt32 GetNumberOfProcessors(); | ||
| 181 | |||
| 182 | bool GetRamSize(size_t &size); // returns false, if unknown ram size | 201 | bool GetRamSize(size_t &size); // returns false, if unknown ram size |
| 183 | 202 | ||
| 184 | unsigned long Get_File_OPEN_MAX(); | 203 | unsigned long Get_File_OPEN_MAX(); |
diff --git a/CPP/Windows/SystemInfo.cpp b/CPP/Windows/SystemInfo.cpp index 35846e0..2eced2a 100644 --- a/CPP/Windows/SystemInfo.cpp +++ b/CPP/Windows/SystemInfo.cpp | |||
| @@ -22,7 +22,7 @@ | |||
| 22 | 22 | ||
| 23 | #if defined(__GLIBC__) && (__GLIBC__ * 100 + __GLIBC_MINOR__ >= 216) | 23 | #if defined(__GLIBC__) && (__GLIBC__ * 100 + __GLIBC_MINOR__ >= 216) |
| 24 | #define Z7_GETAUXV_AVAILABLE | 24 | #define Z7_GETAUXV_AVAILABLE |
| 25 | #else | 25 | #elif !defined(__QNXNTO__) |
| 26 | // #pragma message("=== is not NEW GLIBC === ") | 26 | // #pragma message("=== is not NEW GLIBC === ") |
| 27 | #if defined __has_include | 27 | #if defined __has_include |
| 28 | #if __has_include (<sys/auxv.h>) | 28 | #if __has_include (<sys/auxv.h>) |
| @@ -58,7 +58,7 @@ | |||
| 58 | 58 | ||
| 59 | #ifdef USE_HWCAP | 59 | #ifdef USE_HWCAP |
| 60 | 60 | ||
| 61 | #if defined(__FreeBSD__) | 61 | #if defined(__FreeBSD__) || defined(__OpenBSD__) |
| 62 | 62 | ||
| 63 | // #if (__FreeBSD__ >= 13) // (FreeBSD 12.01 is required for elf_aux_info() ???) | 63 | // #if (__FreeBSD__ >= 13) // (FreeBSD 12.01 is required for elf_aux_info() ???) |
| 64 | static unsigned long MY_getauxval(int aux) | 64 | static unsigned long MY_getauxval(int aux) |
diff --git a/CPP/Windows/TimeUtils.h b/CPP/Windows/TimeUtils.h index 4a9d0f2..8e1e478 100644 --- a/CPP/Windows/TimeUtils.h +++ b/CPP/Windows/TimeUtils.h | |||
| @@ -65,6 +65,14 @@ inline bool FILETIME_IsZero(const FILETIME &ft) | |||
| 65 | #define ST_MTIME(st) st.st_mtimespec | 65 | #define ST_MTIME(st) st.st_mtimespec |
| 66 | #define ST_ATIME(st) st.st_atimespec | 66 | #define ST_ATIME(st) st.st_atimespec |
| 67 | #define ST_CTIME(st) st.st_ctimespec | 67 | #define ST_CTIME(st) st.st_ctimespec |
| 68 | #elif defined(__QNXNTO__) && defined(__ARM__) && !defined(__aarch64__) | ||
| 69 | // QNX armv7le (32-bit) for "struct stat" timestamps uses time_t instead of timespec | ||
| 70 | inline CFiTime ST_MTIME(const struct stat &st) | ||
| 71 | { timespec ts; ts.tv_sec = st.st_mtime; ts.tv_nsec = 0; return ts; } | ||
| 72 | inline CFiTime ST_ATIME(const struct stat &st) | ||
| 73 | { timespec ts; ts.tv_sec = st.st_atime; ts.tv_nsec = 0; return ts; } | ||
| 74 | inline CFiTime ST_CTIME(const struct stat &st) | ||
| 75 | { timespec ts; ts.tv_sec = st.st_ctime; ts.tv_nsec = 0; return ts; } | ||
| 68 | #else | 76 | #else |
| 69 | #define ST_MTIME(st) st.st_mtim | 77 | #define ST_MTIME(st) st.st_mtim |
| 70 | #define ST_ATIME(st) st.st_atim | 78 | #define ST_ATIME(st) st.st_atim |
diff --git a/DOC/7zip.wxs b/DOC/7zip.wxs index 703e22e..8c6ef4c 100644 --- a/DOC/7zip.wxs +++ b/DOC/7zip.wxs | |||
| @@ -1,7 +1,7 @@ | |||
| 1 | <?xml version="1.0"?> | 1 | <?xml version="1.0"?> |
| 2 | 2 | ||
| 3 | <?define VerMajor = "25" ?> | 3 | <?define VerMajor = "26" ?> |
| 4 | <?define VerMinor = "01" ?> | 4 | <?define VerMinor = "00" ?> |
| 5 | <?define VerBuild = "00" ?> | 5 | <?define VerBuild = "00" ?> |
| 6 | <?define MmVer = "$(var.VerMajor).$(var.VerMinor)" ?> | 6 | <?define MmVer = "$(var.VerMajor).$(var.VerMinor)" ?> |
| 7 | <?define MmHex = "$(var.VerMajor)$(var.VerMinor)" ?> | 7 | <?define MmHex = "$(var.VerMajor)$(var.VerMinor)" ?> |
diff --git a/DOC/License.txt b/DOC/License.txt index bbb56a3..b1a421a 100644 --- a/DOC/License.txt +++ b/DOC/License.txt | |||
| @@ -3,7 +3,7 @@ | |||
| 3 | License for use and distribution | 3 | License for use and distribution |
| 4 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ | 4 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
| 5 | 5 | ||
| 6 | 7-Zip Copyright (C) 1999-2025 Igor Pavlov. | 6 | 7-Zip Copyright (C) 1999-2026 Igor Pavlov. |
| 7 | 7 | ||
| 8 | The licenses for files are: | 8 | The licenses for files are: |
| 9 | 9 | ||
| @@ -58,7 +58,7 @@ BSD 3-clause License in 7-Zip code | |||
| 58 | 58 | ||
| 59 | Copyright (c) 2015-2016, Apple Inc. All rights reserved. | 59 | Copyright (c) 2015-2016, Apple Inc. All rights reserved. |
| 60 | Copyright (c) Facebook, Inc. All rights reserved. | 60 | Copyright (c) Facebook, Inc. All rights reserved. |
| 61 | Copyright (c) 2023-2025 Igor Pavlov. | 61 | Copyright (c) 2023-2026 Igor Pavlov. |
| 62 | 62 | ||
| 63 | Text of the "BSD 3-clause License" | 63 | Text of the "BSD 3-clause License" |
| 64 | ---------------------------------- | 64 | ---------------------------------- |
| @@ -102,7 +102,7 @@ BSD 2-clause License in 7-Zip code | |||
| 102 | XXH64 code in 7-Zip was derived from the original XXH64 code developed by Yann Collet. | 102 | XXH64 code in 7-Zip was derived from the original XXH64 code developed by Yann Collet. |
| 103 | 103 | ||
| 104 | Copyright (c) 2012-2021 Yann Collet. | 104 | Copyright (c) 2012-2021 Yann Collet. |
| 105 | Copyright (c) 2023-2025 Igor Pavlov. | 105 | Copyright (c) 2023-2026 Igor Pavlov. |
| 106 | 106 | ||
| 107 | Text of the "BSD 2-clause License" | 107 | Text of the "BSD 2-clause License" |
| 108 | ---------------------------------- | 108 | ---------------------------------- |
diff --git a/DOC/readme.txt b/DOC/readme.txt index cc89a39..26d0f5a 100644 --- a/DOC/readme.txt +++ b/DOC/readme.txt | |||
| @@ -1,15 +1,15 @@ | |||
| 1 | 7-Zip 25.01 Sources | 1 | 7-Zip 26.00 Sources |
| 2 | ------------------- | 2 | ------------------- |
| 3 | 3 | ||
| 4 | 7-Zip is a file archiver for Windows. | 4 | 7-Zip is a file archiver for Windows. |
| 5 | 5 | ||
| 6 | 7-Zip Copyright (C) 1999-2025 Igor Pavlov. | 6 | 7-Zip Copyright (C) 1999-2026 Igor Pavlov. |
| 7 | 7 | ||
| 8 | 8 | ||
| 9 | License Info | 9 | License Info |
| 10 | ------------ | 10 | ------------ |
| 11 | 11 | ||
| 12 | 7-Zip is free software distributed under the GNU LGPL | 12 | 7-Zip is free software distributed under the GNU LGPL |
| 13 | (except for unRar code). Also some code | 13 | (except for unRar code). Also some code |
| 14 | is licensed under the "BSD 3-clause License". | 14 | is licensed under the "BSD 3-clause License". |
| 15 | Read "License.txt" for more infomation about license. | 15 | Read "License.txt" for more infomation about license. |
| @@ -27,7 +27,7 @@ Please check main restriction from unRar license: | |||
| 27 | not be used to develop a RAR (WinRAR) compatible archiver. | 27 | not be used to develop a RAR (WinRAR) compatible archiver. |
| 28 | 28 | ||
| 29 | In brief it means: | 29 | In brief it means: |
| 30 | 1) You can compile and use compiled files under GNU LGPL rules, since | 30 | 1) You can compile and use compiled files under GNU LGPL rules, since |
| 31 | unRAR license almost has no restrictions for compiled files. | 31 | unRAR license almost has no restrictions for compiled files. |
| 32 | You can link these compiled files to LGPL programs. | 32 | You can link these compiled files to LGPL programs. |
| 33 | 2) You can fix bugs in source code and use compiled fixed version. | 33 | 2) You can fix bugs in source code and use compiled fixed version. |
| @@ -60,7 +60,7 @@ Tools / Options / Directories | |||
| 60 | - Library files | 60 | - Library files |
| 61 | 61 | ||
| 62 | Also you need Microsoft Macro Assembler: | 62 | Also you need Microsoft Macro Assembler: |
| 63 | - ml.exe for x86 | 63 | - ml.exe for x86 |
| 64 | - ml64.exe for x64 | 64 | - ml64.exe for x64 |
| 65 | You can use ml.exe from Windows SDK for Windows Vista or some later versions. | 65 | You can use ml.exe from Windows SDK for Windows Vista or some later versions. |
| 66 | 66 | ||
| @@ -85,7 +85,7 @@ OLD_COMPILER | |||
| 85 | for old VC compiler, like MSCV 6.0. | 85 | for old VC compiler, like MSCV 6.0. |
| 86 | 86 | ||
| 87 | MY_DYNAMIC_LINK | 87 | MY_DYNAMIC_LINK |
| 88 | for dynamic linking to the run-time library (msvcrt.dll). | 88 | for dynamic linking to the run-time library (msvcrt.dll). |
| 89 | The default makefile option is static linking to the run-time library. | 89 | The default makefile option is static linking to the run-time library. |
| 90 | 90 | ||
| 91 | To compile all 7-Zip files for x64 with Visual Studio 2022, | 91 | 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 | |||
| 116 | 116 | ||
| 117 | 7-Zip's assembler code uses the following syntax for different platforms: | 117 | 7-Zip's assembler code uses the following syntax for different platforms: |
| 118 | 118 | ||
| 119 | 1) x86 and x86-64 (AMD64): MASM syntax. | 119 | 1) x86 and x86-64 (AMD64): MASM syntax. |
| 120 | Now there are 3 programs that supports MASM syntax in Linux. | 120 | Now there are 3 programs that supports MASM syntax in Linux. |
| 121 | ' 'Asmc Macro Assembler, JWasm, and UASM. Note that JWasm now doesn't support some | 121 | ' 'Asmc Macro Assembler, JWasm, and UASM. Note that JWasm now doesn't support some |
| 122 | cpu instructions used in 7-Zip. | 122 | cpu instructions used in 7-Zip. |
| 123 | So you must install Asmc Macro Assembler in Linux or UASM, if you want to compile | 123 | So you must install Asmc Macro Assembler in Linux or UASM, if you want to compile |
| 124 | fastest version of 7-Zip x86 and x86-64: | 124 | fastest version of 7-Zip x86 and x86-64: |
| 125 | https://github.com/nidud/asmc | 125 | https://github.com/nidud/asmc |
| 126 | https://github.com/Terraspace/UASM | 126 | https://github.com/Terraspace/UASM |
| 127 | 127 | ||
| 128 | 128 | ||
| 129 | 2) arm64: GNU assembler for ARM64 with preprocessor. | 129 | 2) arm64: GNU assembler for ARM64 with preprocessor. |
| 130 | That systax is supported by GCC and CLANG for ARM64. | 130 | That systax is supported by GCC and CLANG for ARM64. |
| 131 | 131 | ||
| 132 | There are different binaries that can be compiled from 7-Zip source. | 132 | There are different binaries that can be compiled from 7-Zip source. |
| 133 | There are 2 main files in folder for compiling: | 133 | There are 2 main files in folder for compiling: |
| 134 | makefile - that can be used for compiling Windows version of 7-Zip with nmake command | 134 | makefile - that can be used for compiling Windows version of 7-Zip with nmake command |
| 135 | makefile.gcc - that can be used for compiling Linux/macOS versions of 7-Zip or Windows version | 135 | makefile.gcc - that can be used for compiling Linux/macOS versions of 7-Zip or Windows version |
| 136 | with MINGW (GCC) with make command. | 136 | with MINGW (GCC) with make command. |
| 137 | 137 | ||
| 138 | At first you must change the current folder to folder that contains `makefile.gcc`: | 138 | 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: | |||
| 143 | 143 | ||
| 144 | make -j -f makefile.gcc | 144 | make -j -f makefile.gcc |
| 145 | 145 | ||
| 146 | Also there are additional "*.mak" files in folder "CPP/7zip/" that can be used to compile | 146 | Also there are additional "*.mak" files in folder "CPP/7zip/" that can be used to compile |
| 147 | 7-Zip binaries with optimized code and optimzing options. | 147 | 7-Zip binaries with optimized code and optimzing options. |
| 148 | 148 | ||
| 149 | To compile with GCC without assembler: | 149 | To compile with GCC without assembler: |
| @@ -171,10 +171,10 @@ makefile.gcc supports some variables that can change compile options | |||
| 171 | 171 | ||
| 172 | USE_JWASM=1 | 172 | USE_JWASM=1 |
| 173 | use JWasm assembler instead of Asmc. | 173 | use JWasm assembler instead of Asmc. |
| 174 | Note that JWasm doesn't support AES instructions. So AES code from C version AesOpt.c | 174 | Note that JWasm doesn't support AES instructions. So AES code from C version AesOpt.c |
| 175 | will be used instead of assembler code from AesOpt.asm. | 175 | will be used instead of assembler code from AesOpt.asm. |
| 176 | 176 | ||
| 177 | If you want to use UASM for x86-64 compiling, you can change 7zip_gcc.mak, | 177 | If you want to use UASM for x86-64 compiling, you can change 7zip_gcc.mak, |
| 178 | or send IS_X64=1 USE_ASM=1 MY_ASM="$UASM" to make command calling: | 178 | or send IS_X64=1 USE_ASM=1 MY_ASM="$UASM" to make command calling: |
| 179 | UASM="$PWD/GccUnixR/uasm" | 179 | UASM="$PWD/GccUnixR/uasm" |
| 180 | cd "7zip-src/CPP/7zip/Bundles/Alone2" | 180 | cd "7zip-src/CPP/7zip/Bundles/Alone2" |
| @@ -187,11 +187,11 @@ DISABLE_RAR=1 | |||
| 187 | DISABLE_RAR_COMPRESS=1 | 187 | DISABLE_RAR_COMPRESS=1 |
| 188 | removes "not fully free" code of RAR decompression codecs from compilation. | 188 | removes "not fully free" code of RAR decompression codecs from compilation. |
| 189 | 189 | ||
| 190 | RAR decompression codecs in 7-Zip code has some additional license restrictions, | 190 | RAR decompression codecs in 7-Zip code has some additional license restrictions, |
| 191 | that can be treated as not fully compatible with free-software licenses. | 191 | that can be treated as not fully compatible with free-software licenses. |
| 192 | DISABLE_RAR_COMPRESS=1 allows to exclude such "not-fully-free" RAR code from compilation. | 192 | DISABLE_RAR_COMPRESS=1 allows to exclude such "not-fully-free" RAR code from compilation. |
| 193 | if DISABLE_RAR_COMPRESS=1 is specified, 7-zip will not be able to decompress files | 193 | if DISABLE_RAR_COMPRESS=1 is specified, 7-zip will not be able to decompress files |
| 194 | from rar archives, but 7-zip still will be able to open rar archives to get list of | 194 | from rar archives, but 7-zip still will be able to open rar archives to get list of |
| 195 | files or to extract files that are stored without compression. | 195 | files or to extract files that are stored without compression. |
| 196 | if DISABLE_RAR=1 is specified, 7-zip will not be able to work with RAR archives. | 196 | if DISABLE_RAR=1 is specified, 7-zip will not be able to work with RAR archives. |
| 197 | 197 | ||
| @@ -203,11 +203,11 @@ Now there are two different ports of 7-Zip for Linux/macOS: | |||
| 203 | 203 | ||
| 204 | 1) p7zip - another port of 7-Zip for Linux, made by an independent developer. | 204 | 1) p7zip - another port of 7-Zip for Linux, made by an independent developer. |
| 205 | The latest version of p7zip now is 16.02, and that p7zip 16.02 is outdated now. | 205 | The latest version of p7zip now is 16.02, and that p7zip 16.02 is outdated now. |
| 206 | http://sourceforge.net/projects/p7zip/ | 206 | http://sourceforge.net/projects/p7zip/ |
| 207 | 207 | ||
| 208 | 2) 7-Zip for Linux/macOS - this package - it's new code with all changes from latest 7-Zip for Windows. | 208 | 2) 7-Zip for Linux/macOS - this package - it's new code with all changes from latest 7-Zip for Windows. |
| 209 | 209 | ||
| 210 | These two ports are not identical. | 210 | These two ports are not identical. |
| 211 | Note also that some Linux specific things can be implemented better in p7zip than in new 7-Zip for Linux. | 211 | Note also that some Linux specific things can be implemented better in p7zip than in new 7-Zip for Linux. |
| 212 | 212 | ||
| 213 | 213 | ||
| @@ -218,13 +218,13 @@ Notes: | |||
| 218 | 7-Zip consists of COM modules (DLL files). | 218 | 7-Zip consists of COM modules (DLL files). |
| 219 | But 7-Zip doesn't use standard COM interfaces for creating objects. | 219 | But 7-Zip doesn't use standard COM interfaces for creating objects. |
| 220 | Look at | 220 | Look at |
| 221 | 7zip\UI\Client7z folder for example of using DLL files of 7-Zip. | 221 | 7zip\UI\Client7z folder for example of using DLL files of 7-Zip. |
| 222 | Some DLL files can use other DLL files from 7-Zip. | 222 | Some DLL files can use other DLL files from 7-Zip. |
| 223 | If you don't like it, you must use standalone version of DLL. | 223 | If you don't like it, you must use standalone version of DLL. |
| 224 | To compile standalone version of DLL you must include all used parts | 224 | To compile standalone version of DLL you must include all used parts |
| 225 | to project and define some defs. | 225 | to project and define some defs. |
| 226 | For example, 7zip\Bundles\Format7z is a standalone version of 7z.dll | 226 | For example, 7zip\Bundles\Format7z is a standalone version of 7z.dll |
| 227 | that works with 7z format. So you can use such DLL in your project | 227 | that works with 7z format. So you can use such DLL in your project |
| 228 | without additional DLL files. | 228 | without additional DLL files. |
| 229 | 229 | ||
| 230 | 230 | ||
| @@ -284,7 +284,7 @@ Windows common files for Windows related code | |||
| 284 | UI | 284 | UI |
| 285 | 285 | ||
| 286 | Agent Intermediary modules for FAR plugin and Explorer plugin | 286 | Agent Intermediary modules for FAR plugin and Explorer plugin |
| 287 | Client7z Test application for 7za.dll | 287 | Client7z Test application for 7za.dll |
| 288 | Common Common UI files | 288 | Common Common UI files |
| 289 | Console 7z.exe : Console version | 289 | Console 7z.exe : Console version |
| 290 | Explorer 7-zip.dll: 7-Zip Shell extension | 290 | Explorer 7-zip.dll: 7-Zip Shell extension |
diff --git a/DOC/src-history.txt b/DOC/src-history.txt index 48c9647..657f04f 100644 --- a/DOC/src-history.txt +++ b/DOC/src-history.txt | |||
| @@ -1,11 +1,20 @@ | |||
| 1 | HISTORY of the 7-Zip source code | 1 | HISTORY of the 7-Zip source code |
| 2 | -------------------------------- | 2 | -------------------------------- |
| 3 | 3 | ||
| 4 | 26.00 2026-02-12 | ||
| 5 | ------------------------- | ||
| 6 | - improved code for ZIP, CPIO, RAR, UFD, QCOW, Compound. | ||
| 7 | - 7-Zip File Manager: improved sorting order of the file list. It uses file name as secondary sorting key. | ||
| 8 | - 7-Zip File Manager: improved Benchmark to support systems with more than 64 CPU threads. | ||
| 9 | - the bug was fixed: 7-Zip could not correctly extract TAR archives containing sparse files. | ||
| 10 | - some bugs were fixed. | ||
| 11 | |||
| 12 | |||
| 4 | 25.01 2025-08-03 | 13 | 25.01 2025-08-03 |
| 5 | ------------------------- | 14 | ------------------------- |
| 6 | - The code for handling symbolic links has been changed | 15 | - CVE-2025-55188 : The code for handling symbolic links has been changed |
| 7 | to provide greater security when extracting files from archives. | 16 | to provide greater security when extracting files from archives. |
| 8 | Command line switch -snld20 can be used to bypass default security | 17 | Command line switch -snld20 can be used to bypass default security |
| 9 | checks when creating symbolic links. | 18 | checks when creating symbolic links. |
| 10 | 19 | ||
| 11 | 20 | ||
| @@ -18,17 +27,19 @@ HISTORY of the 7-Zip source code | |||
| 18 | - bzip2 compression speed was increased by 15-40%. | 27 | - bzip2 compression speed was increased by 15-40%. |
| 19 | - deflate (zip/gz) compression speed was increased by 1-3%. | 28 | - deflate (zip/gz) compression speed was increased by 1-3%. |
| 20 | - improved support for zip, cpio and fat archives. | 29 | - improved support for zip, cpio and fat archives. |
| 21 | - fixed some bugs and vulnerabilities. | 30 | - fixed some bugs. |
| 22 | - the bug was fixed : CVE-2025-53816 : 7-Zip could work incorrectly for some incorrect RAR archives. | 31 | - CVE-2025-11001 and CVE-2025-11002 : A vulnerability was fixed for symbolic links processing, |
| 23 | - the bug was fixed : CVE-2025-53817 : 7-Zip could crash for some incorrect COM (Compound File) archives. | 32 | when extracting files from archives. |
| 33 | - the bug was fixed : CVE-2025-53816 : 7-Zip could work incorrectly for some incorrect RAR archives. | ||
| 34 | - the bug was fixed : CVE-2025-53817 : 7-Zip could crash for some incorrect COM (Compound File) archives. | ||
| 24 | 35 | ||
| 25 | 36 | ||
| 26 | 24.09 2024-11-29 | 37 | 24.09 2024-11-29 |
| 27 | ------------------------- | 38 | ------------------------- |
| 28 | - The default dictionary size values for LZMA/LZMA2 compression methods were increased: | 39 | - The default dictionary size values for LZMA/LZMA2 compression methods were increased: |
| 29 | dictionary size compression level | 40 | dictionary size compression level |
| 30 | v24.08 v24.09 v24.09 | 41 | v24.08 v24.09 v24.09 |
| 31 | 32-bit 64-bit | 42 | 32-bit 64-bit |
| 32 | 8 MB 16 MB 16 MB -mx4 | 43 | 8 MB 16 MB 16 MB -mx4 |
| 33 | 16 MB 32 MB 32 MB -mx5 : Normal | 44 | 16 MB 32 MB 32 MB -mx5 : Normal |
| 34 | 32 MB 64 MB 64 MB -mx6 | 45 | 32 MB 64 MB 64 MB -mx6 |
| @@ -38,11 +49,11 @@ HISTORY of the 7-Zip source code | |||
| 38 | The default dictionary size values for 32-bit versions of LZMA/LZMA2 don't exceed 64 MB. | 49 | The default dictionary size values for 32-bit versions of LZMA/LZMA2 don't exceed 64 MB. |
| 39 | - 7-Zip now can calculate the following hash checksums: SHA-512, SHA-384, SHA3-256 and MD5. | 50 | - 7-Zip now can calculate the following hash checksums: SHA-512, SHA-384, SHA3-256 and MD5. |
| 40 | - APM and HFS support was improved. | 51 | - APM and HFS support was improved. |
| 41 | - If an archive update operation uses a temporary archive folder and | 52 | - If an archive update operation uses a temporary archive folder and |
| 42 | the archive is moved to the destination folder, 7-Zip shows the progress of moving | 53 | the archive is moved to the destination folder, 7-Zip shows the progress of moving |
| 43 | the archive file, as this operation can take a long time if the archive is large. | 54 | the archive file, as this operation can take a long time if the archive is large. |
| 44 | - The bug was fixed: 7-Zip File Manager didn't propagate Zone.Identifier stream | 55 | - The bug was fixed: 7-Zip File Manager didn't propagate Zone.Identifier stream |
| 45 | for extacted files from nested archives (if there is open archive inside another open archive). | 56 | for extracted files from nested archives (if there is open archive inside another open archive). |
| 46 | - Some bugs were fixed. | 57 | - Some bugs were fixed. |
| 47 | 58 | ||
| 48 | 59 | ||
| @@ -76,7 +87,7 @@ HISTORY of the 7-Zip source code | |||
| 76 | ------------------------- | 87 | ------------------------- |
| 77 | - New switch -myv={MMNN} to set decoder compatibility version for 7z archive creating. | 88 | - New switch -myv={MMNN} to set decoder compatibility version for 7z archive creating. |
| 78 | {MMNN} is 4-digit number that represents the version of 7-Zip without a dot. | 89 | {MMNN} is 4-digit number that represents the version of 7-Zip without a dot. |
| 79 | If -myv={MMNN} switch is specified, 7-Zip will only use compression methods that can | 90 | If -myv={MMNN} switch is specified, 7-Zip will only use compression methods that can |
| 80 | be decoded by the specified version {MMNN} of 7-Zip and newer versions. | 91 | be decoded by the specified version {MMNN} of 7-Zip and newer versions. |
| 81 | If -myv={MMNN} switch is not specified, -myv=2300 is used, and 7-Zip will only | 92 | If -myv={MMNN} switch is not specified, -myv=2300 is used, and 7-Zip will only |
| 82 | use compression methods that can be decoded by 7-Zip 23.00 and newer versions. | 93 | 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 | |||
| 127 | And some warning types are disabled in 2 files: | 138 | And some warning types are disabled in 2 files: |
| 128 | - C/Compiler.h for C/C++ code warnings. | 139 | - C/Compiler.h for C/C++ code warnings. |
| 129 | - CPP/Common/Common.h for C++ code warnings. | 140 | - CPP/Common/Common.h for C++ code warnings. |
| 130 | - Linux/macOS versions of 7-Zip: IUnknown interface in new code doesn't use | 141 | - Linux/macOS versions of 7-Zip: IUnknown interface in new code doesn't use |
| 131 | virtual destructor that was used in previous 7-Zip and p7zip: | 142 | virtual destructor that was used in previous 7-Zip and p7zip: |
| 132 | // virtual ~IUnknown() {} | 143 | // virtual ~IUnknown() {} |
| 133 | So 7-Zip's dynamically linked shared libraries (codecs) are not compatible | 144 | So 7-Zip's dynamically linked shared libraries (codecs) are not compatible |
| 134 | between new 7-Zip for Linux/macOS and old 7-Zip (and p7zip). | 145 | between new 7-Zip for Linux/macOS and old 7-Zip (and p7zip). |
| 135 | - Some optimizations in filters code: BCJ, BCJ2, Swap* and opthers. | 146 | - Some optimizations in filters code: BCJ, BCJ2, Swap* and opthers. |
| 136 | - If 7-Zip uses BCJ2 filter for big datasets compressing, it can use additional temp | 147 | - If 7-Zip uses BCJ2 filter for big datasets compressing, it can use additional temp |
| 137 | files in system's TEMP folder. 7-Zip uses temp file for additional compressed | 148 | files in system's TEMP folder. 7-Zip uses temp file for additional compressed |
| 138 | data stream, if size of such compressed stream is larger than predefined limit: | 149 | data stream, if size of such compressed stream is larger than predefined limit: |
| 139 | 16 MiB in 32-bit version, 4 GiB in 64-bit version. | 150 | 16 MiB in 32-bit version, 4 GiB in 64-bit version. |
| 140 | - Some bugs were fixed. | 151 | - Some bugs were fixed. |
| 141 | 152 | ||
| @@ -157,7 +168,7 @@ HISTORY of the 7-Zip source code | |||
| 157 | 21.06 2021-11-24 | 168 | 21.06 2021-11-24 |
| 158 | ------------------------- | 169 | ------------------------- |
| 159 | - Bug in LZMA encoder in file LzmaEnc.c was fixed: | 170 | - Bug in LZMA encoder in file LzmaEnc.c was fixed: |
| 160 | LzmaEnc_MemEncode(), LzmaEncode() and LzmaCompress() could work incorrectly, | 171 | LzmaEnc_MemEncode(), LzmaEncode() and LzmaCompress() could work incorrectly, |
| 161 | if size value for output buffer is smaller than size required for all compressed data. | 172 | if size value for output buffer is smaller than size required for all compressed data. |
| 162 | LzmaEnc_Encode() could work incorrectly, | 173 | LzmaEnc_Encode() could work incorrectly, |
| 163 | if callback ISeqOutStream::Write() doesn't write all compressed data. | 174 | if callback ISeqOutStream::Write() doesn't write all compressed data. |
| @@ -171,8 +182,8 @@ HISTORY of the 7-Zip source code | |||
| 171 | ------------------------- | 182 | ------------------------- |
| 172 | - 7-Zip now reduces the number of working CPU threads for compression, | 183 | - 7-Zip now reduces the number of working CPU threads for compression, |
| 173 | if RAM size is not enough for compression with big LZMA2 dictionary. | 184 | if RAM size is not enough for compression with big LZMA2 dictionary. |
| 174 | - 7-Zip now can create and check "file.sha256" and "file.sha1" text files | 185 | - 7-Zip now can create and check "file.sha256" and "file.sha1" text files |
| 175 | that contain the list of file names and SHA-1 / SHA-256 checksums in format | 186 | that contain the list of file names and SHA-1 / SHA-256 checksums in format |
| 176 | compatible with sha1sum/sha256sum programs. | 187 | compatible with sha1sum/sha256sum programs. |
| 177 | 188 | ||
| 178 | 189 | ||
| @@ -187,7 +198,7 @@ HISTORY of the 7-Zip source code | |||
| 187 | - 7-Zip now writes additional field for filename in UTF-8 encoding to zip archives. | 198 | - 7-Zip now writes additional field for filename in UTF-8 encoding to zip archives. |
| 188 | It allows to extract correct file name from zip archives on different systems. | 199 | It allows to extract correct file name from zip archives on different systems. |
| 189 | - The command line version of 7-Zip for macOS was released. | 200 | - The command line version of 7-Zip for macOS was released. |
| 190 | - The speed for LZMA and LZMA2 decompression in arm64 versions for macOS and Linux | 201 | - The speed for LZMA and LZMA2 decompression in arm64 versions for macOS and Linux |
| 191 | was increased by 20%-60%. | 202 | was increased by 20%-60%. |
| 192 | - Some changes and improvements in ZIP, TAR and NSIS code. | 203 | - Some changes and improvements in ZIP, TAR and NSIS code. |
| 193 | 204 | ||
| @@ -195,7 +206,7 @@ HISTORY of the 7-Zip source code | |||
| 195 | 21.01 alpha 2021-03-09 | 206 | 21.01 alpha 2021-03-09 |
| 196 | ------------------------- | 207 | ------------------------- |
| 197 | - The command line version of 7-Zip for Linux was released. | 208 | - The command line version of 7-Zip for Linux was released. |
| 198 | - The improvements for speed of ARM64 version using hardware CPU instructions | 209 | - The improvements for speed of ARM64 version using hardware CPU instructions |
| 199 | for AES, CRC-32, SHA-1 and SHA-256. | 210 | for AES, CRC-32, SHA-1 and SHA-256. |
| 200 | - The bug in versions 18.02 - 21.00 was fixed: | 211 | - The bug in versions 18.02 - 21.00 was fixed: |
| 201 | 7-Zip could not correctly extract some ZIP archives created with xz compression method. | 212 | 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 | |||
| 205 | 20.02 alpha 2020-08-08 | 216 | 20.02 alpha 2020-08-08 |
| 206 | ------------------------- | 217 | ------------------------- |
| 207 | - The default number of LZMA2 chunks per solid block in 7z archive was increased to 64. | 218 | - The default number of LZMA2 chunks per solid block in 7z archive was increased to 64. |
| 208 | It allows to increase the compression speed for big 7z archives, if there is a big number | 219 | It allows to increase the compression speed for big 7z archives, if there is a big number |
| 209 | of CPU cores and threads. | 220 | of CPU cores and threads. |
| 210 | - The speed of PPMd compressing/decompressing was increased for 7z/ZIP/RAR archives. | 221 | - The speed of PPMd compressing/decompressing was increased for 7z/ZIP/RAR archives. |
| 211 | - The new -ssp switch. If the switch -ssp is specified, 7-Zip doesn't allow the system | 222 | - The new -ssp switch. If the switch -ssp is specified, 7-Zip doesn't allow the system |
| 212 | to modify "Last Access Time" property of source files for archiving and hashing operations. | 223 | to modify "Last Access Time" property of source files for archiving and hashing operations. |
| 213 | - Some bugs were fixed. | 224 | - Some bugs were fixed. |
| 214 | 225 | ||
| 215 | 226 | ||
| 216 | 20.00 alpha 2020-02-06 | 227 | 20.00 alpha 2020-02-06 |
| 217 | ------------------------- | 228 | ------------------------- |
| 218 | - 7-Zip now supports new optional match finders for LZMA/LZMA2 compression: bt5 and hc5, | 229 | - 7-Zip now supports new optional match finders for LZMA/LZMA2 compression: bt5 and hc5, |
| 219 | that can work faster than bt4 and hc4 match finders for the data with big redundancy. | 230 | that can work faster than bt4 and hc4 match finders for the data with big redundancy. |
| 220 | - The compression ratio was improved for Fast and Fastest compression levels with the | 231 | - The compression ratio was improved for Fast and Fastest compression levels with the |
| 221 | following default settings: | 232 | following default settings: |
| 222 | - Fastest level (-mx1) : hc5 match finder with 256 KB dictionary. | 233 | - Fastest level (-mx1) : hc5 match finder with 256 KB dictionary. |
| 223 | - Fast level (-mx3) : hc5 match finder with 4 MB dictionary. | 234 | - Fast level (-mx3) : hc5 match finder with 4 MB dictionary. |
| 224 | - Minor speed optimizations in multithreaded LZMA/LZMA2 compression for Normal/Maximum/Ultra | 235 | - Minor speed optimizations in multithreaded LZMA/LZMA2 compression for Normal/Maximum/Ultra |
| 225 | compression levels. | 236 | compression levels. |
| 226 | - bzip2 decoding code was updated to support bzip2 archives, created by lbzip2 program. | 237 | - bzip2 decoding code was updated to support bzip2 archives, created by lbzip2 program. |
| 227 | 238 | ||
| 228 | 239 | ||
| 229 | 19.02 2019-09-05 | 240 | 19.02 2019-09-05 |
| 230 | ------------------------- | 241 | ------------------------- |
| 231 | - Support for SHA-1/SHA-256 optimized code in | 242 | - Support for SHA-1/SHA-256 optimized code in |
| 232 | Sha1Opt.c, Sha256Opt.c, Sha256Opt.asm, Sha1Opt.asm. | 243 | Sha1Opt.c, Sha256Opt.c, Sha256Opt.asm, Sha1Opt.asm. |
| 233 | 244 | ||
| 234 | 245 | ||
| @@ -249,7 +260,7 @@ HISTORY of the 7-Zip source code | |||
| 249 | There was memory leak in multithreading xz decoder - XzDecMt_Decode(), | 260 | There was memory leak in multithreading xz decoder - XzDecMt_Decode(), |
| 250 | if xz stream contains only one block. | 261 | if xz stream contains only one block. |
| 251 | - 7-Zip 18.02-18.05 used only one CPU thread for bz2 archive creation. | 262 | - 7-Zip 18.02-18.05 used only one CPU thread for bz2 archive creation. |
| 252 | - The changes for MSVS compiler makefiles: | 263 | - The changes for MSVS compiler makefiles: |
| 253 | - the makefiles now use "PLATFORM" macroname with values (x64, x86, arm64) | 264 | - the makefiles now use "PLATFORM" macroname with values (x64, x86, arm64) |
| 254 | instead of "CPU" macroname with values (AMD64, ARM64). | 265 | instead of "CPU" macroname with values (AMD64, ARM64). |
| 255 | - the makefiles by default now use static version of the run-time library. | 266 | - the makefiles by default now use static version of the run-time library. |
| @@ -257,17 +268,17 @@ HISTORY of the 7-Zip source code | |||
| 257 | 268 | ||
| 258 | 18.05 2018-04-30 | 269 | 18.05 2018-04-30 |
| 259 | ------------------------- | 270 | ------------------------- |
| 260 | - The speed for LZMA/LZMA2 compressing was increased | 271 | - The speed for LZMA/LZMA2 compressing was increased |
| 261 | by 8% for fastest/fast compression levels and | 272 | by 8% for fastest/fast compression levels and |
| 262 | by 3% for normal/maximum compression levels. | 273 | by 3% for normal/maximum compression levels. |
| 263 | - Previous versions of 7-Zip could work incorrectly in "Large memory pages" mode in | 274 | - Previous versions of 7-Zip could work incorrectly in "Large memory pages" mode in |
| 264 | Windows 10 because of some BUG with "Large Pages" in Windows 10. | 275 | Windows 10 because of some BUG with "Large Pages" in Windows 10. |
| 265 | Now 7-Zip doesn't use "Large Pages" on Windows 10 up to revision 1709 (16299). | 276 | Now 7-Zip doesn't use "Large Pages" on Windows 10 up to revision 1709 (16299). |
| 266 | 277 | ||
| 267 | 278 | ||
| 268 | 18.03 beta 2018-03-04 | 279 | 18.03 beta 2018-03-04 |
| 269 | ------------------------- | 280 | ------------------------- |
| 270 | - Asm\x86\LzmaDecOpt.asm: new optimized LZMA decoder written in asm | 281 | - Asm\x86\LzmaDecOpt.asm: new optimized LZMA decoder written in asm |
| 271 | for x64 with about 30% higher speed than main version of LZMA decoder written in C. | 282 | for x64 with about 30% higher speed than main version of LZMA decoder written in C. |
| 272 | - The speed for single-thread LZMA/LZMA2 decoder written in C was increased by 3%. | 283 | - The speed for single-thread LZMA/LZMA2 decoder written in C was increased by 3%. |
| 273 | - 7-Zip now can use multi-threading for 7z/LZMA2 decoding, | 284 | - 7-Zip now can use multi-threading for 7z/LZMA2 decoding, |
| @@ -278,7 +289,7 @@ HISTORY of the 7-Zip source code | |||
| 278 | 289 | ||
| 279 | 17.00 beta 2017-04-29 | 290 | 17.00 beta 2017-04-29 |
| 280 | ------------------------- | 291 | ------------------------- |
| 281 | - NewHandler.h / NewHandler.cpp: | 292 | - NewHandler.h / NewHandler.cpp: |
| 282 | now it redefines operator new() only for old MSVC compilers (_MSC_VER < 1900). | 293 | now it redefines operator new() only for old MSVC compilers (_MSC_VER < 1900). |
| 283 | - C/7zTypes.h : the names of variables in interface structures were changed (vt). | 294 | - C/7zTypes.h : the names of variables in interface structures were changed (vt). |
| 284 | - Some bugs were fixed. 7-Zip could crash in some cases. | 295 | - Some bugs were fixed. 7-Zip could crash in some cases. |
| @@ -288,53 +299,53 @@ HISTORY of the 7-Zip source code | |||
| 288 | 16.02 2016-05-21 | 299 | 16.02 2016-05-21 |
| 289 | ------------------------- | 300 | ------------------------- |
| 290 | - The BUG in 16.00 - 16.01 was fixed: | 301 | - The BUG in 16.00 - 16.01 was fixed: |
| 291 | Split Handler (SplitHandler.cpp) returned incorrect | 302 | Split Handler (SplitHandler.cpp) returned incorrect |
| 292 | total size value (kpidSize) for split archives. | 303 | total size value (kpidSize) for split archives. |
| 293 | 304 | ||
| 294 | 305 | ||
| 295 | 16.01 2016-05-19 | 306 | 16.01 2016-05-19 |
| 296 | ------------------------- | 307 | ------------------------- |
| 297 | - Some bugs were fixed, | 308 | - Some bugs were fixed, |
| 298 | - Some internal changes to reduce the number of compiler warnings. | 309 | - Some internal changes to reduce the number of compiler warnings. |
| 299 | 310 | ||
| 300 | 311 | ||
| 301 | 16.00 2016-05-10 | 312 | 16.00 2016-05-10 |
| 302 | ------------------------- | 313 | ------------------------- |
| 303 | - 7-Zip now can extract multivolume ZIP archives (z01, z02, ... , zip). | 314 | - 7-Zip now can extract multivolume ZIP archives (z01, z02, ... , zip). |
| 304 | - Some bugs were fixed, | 315 | - Some bugs were fixed, |
| 305 | 316 | ||
| 306 | 317 | ||
| 307 | 15.12 2015-11-19 | 318 | 15.12 2015-11-19 |
| 308 | ------------------------- | 319 | ------------------------- |
| 309 | - The BUG in C version of 7z decoder was fixed: | 320 | - The BUG in C version of 7z decoder was fixed: |
| 310 | 7zDec.c : SzDecodeLzma2() | 321 | 7zDec.c : SzDecodeLzma2() |
| 311 | 7z decoder could mistakenly report about decoding error for some 7z archives | 322 | 7z decoder could mistakenly report about decoding error for some 7z archives |
| 312 | that use LZMA2 compression method. | 323 | that use LZMA2 compression method. |
| 313 | The probability to get that mistaken decoding error report was about | 324 | The probability to get that mistaken decoding error report was about |
| 314 | one error per 16384 solid blocks for solid blocks larger than 16 KB (compressed size). | 325 | one error per 16384 solid blocks for solid blocks larger than 16 KB (compressed size). |
| 315 | - The BUG (in 9.26-15.11) in C version of 7z decoder was fixed: | 326 | - The BUG (in 9.26-15.11) in C version of 7z decoder was fixed: |
| 316 | 7zArcIn.c : SzReadHeader2() | 327 | 7zArcIn.c : SzReadHeader2() |
| 317 | 7z decoder worked incorrectly for 7z archives that contain | 328 | 7z decoder worked incorrectly for 7z archives that contain |
| 318 | empty solid blocks, that can be placed to 7z archive, if some file is | 329 | empty solid blocks, that can be placed to 7z archive, if some file is |
| 319 | unavailable for reading during archive creation. | 330 | unavailable for reading during archive creation. |
| 320 | 331 | ||
| 321 | 332 | ||
| 322 | 15.09 beta 2015-10-16 | 333 | 15.09 beta 2015-10-16 |
| 323 | ------------------------- | 334 | ------------------------- |
| 324 | - The BUG in LZMA / LZMA2 encoding code was fixed. | 335 | - The BUG in LZMA / LZMA2 encoding code was fixed. |
| 325 | The BUG in LzFind.c::MatchFinder_ReadBlock() function. | 336 | The BUG in LzFind.c::MatchFinder_ReadBlock() function. |
| 326 | If input data size is larger than (4 GiB - dictionary_size), | 337 | If input data size is larger than (4 GiB - dictionary_size), |
| 327 | the following code worked incorrectly: | 338 | the following code worked incorrectly: |
| 328 | - LZMA : LzmaEnc_MemEncode(), LzmaEncode() : LZMA encoding functions | 339 | - LZMA : LzmaEnc_MemEncode(), LzmaEncode() : LZMA encoding functions |
| 329 | for compressing from memory to memory. | 340 | for compressing from memory to memory. |
| 330 | That BUG is not related to LZMA encoder version that works via streams. | 341 | That BUG is not related to LZMA encoder version that works via streams. |
| 331 | - LZMA2 : multi-threaded version of LZMA2 encoder worked incorrectly, if | 342 | - LZMA2 : multi-threaded version of LZMA2 encoder worked incorrectly, if |
| 332 | default value of chunk size (CLzma2EncProps::blockSize) is changed | 343 | default value of chunk size (CLzma2EncProps::blockSize) is changed |
| 333 | to value larger than (4 GiB - dictionary_size). | 344 | to value larger than (4 GiB - dictionary_size). |
| 334 | 345 | ||
| 335 | 346 | ||
| 336 | 9.38 beta 2015-01-03 | 347 | 9.38 beta 2015-01-03 |
| 337 | ------------------------- | 348 | ------------------------- |
| 338 | - The BUG in 9.31-9.37 was fixed: | 349 | - The BUG in 9.31-9.37 was fixed: |
| 339 | IArchiveGetRawProps interface was disabled for 7z archives. | 350 | IArchiveGetRawProps interface was disabled for 7z archives. |
| 340 | - The BUG in 9.26-9.36 was fixed: | 351 | - The BUG in 9.26-9.36 was fixed: |
| @@ -342,10 +353,10 @@ HISTORY of the 7-Zip source code | |||
| 342 | 353 | ||
| 343 | 354 | ||
| 344 | 9.36 beta 2014-12-26 | 355 | 9.36 beta 2014-12-26 |
| 345 | ------------------------- | 356 | ------------------------- |
| 346 | - The BUG in command line version was fixed: | 357 | - The BUG in command line version was fixed: |
| 347 | 7-Zip created temporary archive in current folder during update archive | 358 | 7-Zip created temporary archive in current folder during update archive |
| 348 | operation, if -w{Path} switch was not specified. | 359 | operation, if -w{Path} switch was not specified. |
| 349 | The fixed 7-Zip creates temporary archive in folder that contains updated archive. | 360 | The fixed 7-Zip creates temporary archive in folder that contains updated archive. |
| 350 | - The BUG in 9.33-9.35 was fixed: | 361 | - The BUG in 9.33-9.35 was fixed: |
| 351 | 7-Zip silently ignored file reading errors during 7z or gz archive creation, | 362 | 7-Zip silently ignored file reading errors during 7z or gz archive creation, |
| @@ -355,8 +366,8 @@ HISTORY of the 7-Zip source code | |||
| 355 | 366 | ||
| 356 | 9.31 2012-10-31 | 367 | 9.31 2012-10-31 |
| 357 | ------------------------- | 368 | ------------------------- |
| 358 | - InBuffer.h : CInBuffer uses ISequentialInStream *_stream; instead of CMyComPtr<ISequentialInStream> | 369 | - InBuffer.h : CInBuffer uses ISequentialInStream *_stream; instead of CMyComPtr<ISequentialInStream> |
| 359 | OutBuffer.h: COutBuffer uses ISequentialOutStream *_stream; instead of CMyComPtr<ISequentialOutStream> | 370 | OutBuffer.h: COutBuffer uses ISequentialOutStream *_stream; instead of CMyComPtr<ISequentialOutStream> |
| 360 | 371 | ||
| 361 | 372 | ||
| 362 | 9.26 2011-04-11 | 373 | 9.26 2011-04-11 |
| @@ -366,13 +377,13 @@ HISTORY of the 7-Zip source code | |||
| 366 | 377 | ||
| 367 | 378 | ||
| 368 | 9.21 2011-04-11 | 379 | 9.21 2011-04-11 |
| 369 | ------------------------- | 380 | ------------------------- |
| 370 | - New class FString for file names at file systems. | 381 | - New class FString for file names at file systems. |
| 371 | - Speed optimization in CRC code for big-endian CPUs. | 382 | - Speed optimization in CRC code for big-endian CPUs. |
| 372 | 383 | ||
| 373 | 384 | ||
| 374 | 9.18 2010-11-02 | 385 | 9.18 2010-11-02 |
| 375 | ------------------------- | 386 | ------------------------- |
| 376 | - New small SFX module for installers (C/Util/SfxSetup). | 387 | - New small SFX module for installers (C/Util/SfxSetup). |
| 377 | 388 | ||
| 378 | 389 | ||
| @@ -409,7 +420,7 @@ HISTORY of the 7-Zip source code | |||
| 409 | 4.61 2008-11-23 | 420 | 4.61 2008-11-23 |
| 410 | ------------------------- | 421 | ------------------------- |
| 411 | - Bug in ver. 4.58+ was fixed: | 422 | - Bug in ver. 4.58+ was fixed: |
| 412 | 7-Zip didn't use any -m* switch after -mtc, -mcl or -mcu for .zip archives. | 423 | 7-Zip didn't use any -m* switch after -mtc, -mcl or -mcu for .zip archives. |
| 413 | - Bug in .CAB code was fixed. 7-Zip didn't show some empty files, | 424 | - Bug in .CAB code was fixed. 7-Zip didn't show some empty files, |
| 414 | if .CAB archive contains more than one empty file. | 425 | if .CAB archive contains more than one empty file. |
| 415 | 426 | ||
| @@ -417,13 +428,13 @@ HISTORY of the 7-Zip source code | |||
| 417 | 4.59 2008-07-27 | 428 | 4.59 2008-07-27 |
| 418 | ------------------------- | 429 | ------------------------- |
| 419 | - Bug was fixed: | 430 | - Bug was fixed: |
| 420 | LZMA Encoder in fast compression mode could access memory outside of | 431 | LZMA Encoder in fast compression mode could access memory outside of |
| 421 | allocated range in some rare cases. | 432 | allocated range in some rare cases. |
| 422 | 433 | ||
| 423 | 434 | ||
| 424 | 4.59 alpha 2008-05-30 | 435 | 4.59 alpha 2008-05-30 |
| 425 | ------------------------- | 436 | ------------------------- |
| 426 | - BUGS was fixed: | 437 | - BUGS was fixed: |
| 427 | 7zOut.cpp: 7-Zip incorrectly wrote size of property records in some cases. | 438 | 7zOut.cpp: 7-Zip incorrectly wrote size of property records in some cases. |
| 428 | 7zIn.cpp: 7-Zip incorrectly work with archive, containg archive properties. | 439 | 7zIn.cpp: 7-Zip incorrectly work with archive, containg archive properties. |
| 429 | 440 | ||
| @@ -440,13 +451,13 @@ HISTORY of the 7-Zip source code | |||
| 440 | 1) Default mode: 7-Zip uses UTF-8, if the local code page doesn't contain required symbols. | 451 | 1) Default mode: 7-Zip uses UTF-8, if the local code page doesn't contain required symbols. |
| 441 | 2) -mcu switch: 7-Zip uses UTF-8, if there are non-ASCII symbols. | 452 | 2) -mcu switch: 7-Zip uses UTF-8, if there are non-ASCII symbols. |
| 442 | 3) -mcl switch: 7-Zip uses local code page. | 453 | 3) -mcl switch: 7-Zip uses local code page. |
| 443 | - Now it's possible to use -mSW- and -mSW+ switches instead of -mSW=off and -mSW=on | 454 | - Now it's possible to use -mSW- and -mSW+ switches instead of -mSW=off and -mSW=on |
| 444 | 455 | ||
| 445 | 456 | ||
| 446 | 4.58 alpha 7 2008-04-08 | 457 | 4.58 alpha 7 2008-04-08 |
| 447 | ------------------------- | 458 | ------------------------- |
| 448 | - BUG was fixed: BZip2Encoder and BZip2Decoder used CEvent objects without | 459 | - BUG was fixed: BZip2Encoder and BZip2Decoder used CEvent objects without |
| 449 | creating, when BZip2 code was called with one thread (with -mmt1 switch or with | 460 | creating, when BZip2 code was called with one thread (with -mmt1 switch or with |
| 450 | default switches on single thread CPU). | 461 | default switches on single thread CPU). |
| 451 | - .lzma support. | 462 | - .lzma support. |
| 452 | - RPM and NSIS support was improved. | 463 | - RPM and NSIS support was improved. |
| @@ -472,7 +483,7 @@ HISTORY of the 7-Zip source code | |||
| 472 | - 7-Zip now has 128 MB dictionary limit for 32-bit version: | 483 | - 7-Zip now has 128 MB dictionary limit for 32-bit version: |
| 473 | It's for speed optimization: kNumLogBits = 9 + sizeof(size_t) / 2; | 484 | It's for speed optimization: kNumLogBits = 9 + sizeof(size_t) / 2; |
| 474 | - TAR: 'D' link flag support. | 485 | - TAR: 'D' link flag support. |
| 475 | - 7-Zip now can unpack multivolume RAR archives created with | 486 | - 7-Zip now can unpack multivolume RAR archives created with |
| 476 | "old style volume names" scheme (-vn switch) and names *.001, *.002, ... | 487 | "old style volume names" scheme (-vn switch) and names *.001, *.002, ... |
| 477 | - Fixed bugs: | 488 | - Fixed bugs: |
| 478 | - 7-Zip FM could not copy / move files to root network folders like \\COMPNAME\FOLDERNAME\ | 489 | - 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 | |||
| 484 | 7-zip tries to delete all extra fileds (except for WzAES). | 495 | 7-zip tries to delete all extra fileds (except for WzAES). |
| 485 | And that code could hang. | 496 | And that code could hang. |
| 486 | - 7-Zip GUI didn't suggest BZip2 dictionary size used in previous run. | 497 | - 7-Zip GUI didn't suggest BZip2 dictionary size used in previous run. |
| 487 | - If creation time stamp was included in .RAR archive, 7-zip used creation time stamp | 498 | - If creation time stamp was included in .RAR archive, 7-zip used creation time stamp |
| 488 | as modification time stamp. | 499 | as modification time stamp. |
| 489 | 500 | ||
| 490 | 4.58 alpha 2 2007-12-31 | 501 | 4.58 alpha 2 2007-12-31 |
| @@ -531,7 +542,7 @@ HISTORY of the 7-Zip source code | |||
| 531 | 542 | ||
| 532 | 4.45 beta 2007-04-16 | 543 | 4.45 beta 2007-04-16 |
| 533 | ------------------------- | 544 | ------------------------- |
| 534 | - 7-Zip now uses C version of CRC, so you must call CrcGenerateTable at | 545 | - 7-Zip now uses C version of CRC, so you must call CrcGenerateTable at |
| 535 | stratup code, or you must add CPP/Common/CRC.cpp to your project. | 546 | stratup code, or you must add CPP/Common/CRC.cpp to your project. |
| 536 | - Method ID in .7z now is 63-bit integer (UInt64). | 547 | - Method ID in .7z now is 63-bit integer (UInt64). |
| 537 | - Open error messages | 548 | - Open error messages |
| @@ -606,7 +617,7 @@ HISTORY of the 7-Zip source code | |||
| 606 | 617 | ||
| 607 | 4.07 beta 2004-10-03 | 618 | 4.07 beta 2004-10-03 |
| 608 | ------------------------- | 619 | ------------------------- |
| 609 | - some interfaces were changed slightly to support | 620 | - some interfaces were changed slightly to support |
| 610 | -stdin -stdout mode. | 621 | -stdin -stdout mode. |
| 611 | - FilterCoder for simple filters | 622 | - FilterCoder for simple filters |
| 612 | - Wildcard censor class was changed. | 623 | - Wildcard censor class was changed. |
| @@ -682,7 +693,7 @@ HISTORY of the 7-Zip source code | |||
| 682 | 693 | ||
| 683 | 2.30 Beta 24 2002-11-01 | 694 | 2.30 Beta 24 2002-11-01 |
| 684 | ------------------------- | 695 | ------------------------- |
| 685 | SDK/Windows/Synchronization.h | 696 | SDK/Windows/Synchronization.h |
| 686 | SDK/Windows/Synchronization.cpp | 697 | SDK/Windows/Synchronization.cpp |
| 687 | - some changes. | 698 | - some changes. |
| 688 | 699 | ||
| @@ -711,9 +722,9 @@ HISTORY of the 7-Zip source code | |||
| 711 | 722 | ||
| 712 | 2.30 Beta 20 2002-07-01 | 723 | 2.30 Beta 20 2002-07-01 |
| 713 | ------------------------- | 724 | ------------------------- |
| 714 | - SDK/Stream/WindowOut.h | 725 | - SDK/Stream/WindowOut.h |
| 715 | now it uses only required memory (dictionary size). | 726 | now it uses only required memory (dictionary size). |
| 716 | - Project/Archiver/Resource | 727 | - Project/Archiver/Resource |
| 717 | contains common resurces | 728 | contains common resurces |
| 718 | 729 | ||
| 719 | 730 | ||
| @@ -727,8 +738,8 @@ HISTORY of the 7-Zip source code | |||
| 727 | - SDK/Archive/Cab/MSZipDecoder.cpp | 738 | - SDK/Archive/Cab/MSZipDecoder.cpp |
| 728 | SDK/Archive/Cab/LZXDecoder.cpp: | 739 | SDK/Archive/Cab/LZXDecoder.cpp: |
| 729 | bug with corrupted archives was fixed | 740 | bug with corrupted archives was fixed |
| 730 | - Project/Compress/LZ/MatchFinder/BinTree/BinTree.h | 741 | - Project/Compress/LZ/MatchFinder/BinTree/BinTree.h |
| 731 | - Project/Compress/LZ/MatchFinder/BinTree/BinTreeMain.h | 742 | - Project/Compress/LZ/MatchFinder/BinTree/BinTreeMain.h |
| 732 | some speed optimization (using prefetching) | 743 | some speed optimization (using prefetching) |
| 733 | 744 | ||
| 734 | 745 | ||
| @@ -743,7 +754,7 @@ HISTORY of the 7-Zip source code | |||
| 743 | Bug was fixed: LZMA could not extract more than 4 GB. | 754 | Bug was fixed: LZMA could not extract more than 4 GB. |
| 744 | - RPM and CPIO formats. | 755 | - RPM and CPIO formats. |
| 745 | - Project/Compress/LZ/LZMA/Encoder.* | 756 | - Project/Compress/LZ/LZMA/Encoder.* |
| 746 | Project/Archiver/Format/7z/OutHandler.cpp | 757 | Project/Archiver/Format/7z/OutHandler.cpp |
| 747 | New fast compression mode for LZMA: -m0a=0. | 758 | New fast compression mode for LZMA: -m0a=0. |
| 748 | - New match finders for LZMA: bt4b, hc3, hc4. | 759 | - New match finders for LZMA: bt4b, hc3, hc4. |
| 749 | 760 | ||
| @@ -752,23 +763,23 @@ HISTORY of the 7-Zip source code | |||
| 752 | ------------------------- | 763 | ------------------------- |
| 753 | - Compression ratio in LZMA was slightly improved: | 764 | - Compression ratio in LZMA was slightly improved: |
| 754 | Project/Compress/LZ/LZMA/Encoder.* | 765 | Project/Compress/LZ/LZMA/Encoder.* |
| 755 | Project/Archiver/Format/7z/OutHandler.cpp | 766 | Project/Archiver/Format/7z/OutHandler.cpp |
| 756 | 767 | ||
| 757 | 768 | ||
| 758 | 2.30 Beta 14 2002-02-10 | 769 | 2.30 Beta 14 2002-02-10 |
| 759 | ------------------------- | 770 | ------------------------- |
| 760 | - Supporting multithreading for LZMA: | 771 | - Supporting multithreading for LZMA: |
| 761 | Project/Compress/LZ/MatchFinder/MT | 772 | Project/Compress/LZ/MatchFinder/MT |
| 762 | - Common/String.h: | 773 | - Common/String.h: |
| 763 | CStringBase::Replace function was fixed. | 774 | CStringBase::Replace function was fixed. |
| 764 | 775 | ||
| 765 | 776 | ||
| 766 | 2.30 Beta 13 2002-01-27 | 777 | 2.30 Beta 13 2002-01-27 |
| 767 | ------------------------- | 778 | ------------------------- |
| 768 | - Compress/LZ/MatchFinder/BinTree3.h: | 779 | - Compress/LZ/MatchFinder/BinTree3.h: |
| 769 | method | 780 | method |
| 770 | - Compress/LZ/MatchFinder/BinTreemain.h: | 781 | - Compress/LZ/MatchFinder/BinTreemain.h: |
| 771 | - one VirtualAlloc array was splitted to | 782 | - one VirtualAlloc array was splitted to |
| 772 | the for 3 arrays. | 783 | the for 3 arrays. |
| 773 | - Hash-functions were changed. | 784 | - Hash-functions were changed. |
| 774 | 785 | ||
| @@ -776,23 +787,23 @@ HISTORY of the 7-Zip source code | |||
| 776 | 787 | ||
| 777 | 2.30 Beta 12 2002-01-16 | 788 | 2.30 Beta 12 2002-01-16 |
| 778 | ------------------------- | 789 | ------------------------- |
| 779 | - Compress/LZ/MatchFinder/BinTreemain.h: | 790 | - Compress/LZ/MatchFinder/BinTreemain.h: |
| 780 | Compress/LZ/MatchFinder/Patricia.h: | 791 | Compress/LZ/MatchFinder/Patricia.h: |
| 781 | Compress/PPM/PPMd/SubAlloc.h: | 792 | Compress/PPM/PPMd/SubAlloc.h: |
| 782 | Beta 11 bugs were fixed: | 793 | Beta 11 bugs were fixed: |
| 783 | - VirtualFree was used incorrectly | 794 | - VirtualFree was used incorrectly |
| 784 | - checking WIN32 instead _WINDOWS. | 795 | - checking WIN32 instead _WINDOWS. |
| 785 | Compress/LZ/MatchFinder/Patricia.h: | 796 | Compress/LZ/MatchFinder/Patricia.h: |
| 786 | Beta 11 bug with deleting m_Hash2Descendants was fixed. | 797 | Beta 11 bug with deleting m_Hash2Descendants was fixed. |
| 787 | 798 | ||
| 788 | 799 | ||
| 789 | 2.30 Beta 11 2002-01-15 | 800 | 2.30 Beta 11 2002-01-15 |
| 790 | ------------------------- | 801 | ------------------------- |
| 791 | - Compress/LZ/MatchFinder/BinTreemain.h: | 802 | - Compress/LZ/MatchFinder/BinTreemain.h: |
| 792 | Compress/LZ/MatchFinder/Patricia.h: | 803 | Compress/LZ/MatchFinder/Patricia.h: |
| 793 | Compress/PPM/PPMd/SubAlloc.h: | 804 | Compress/PPM/PPMd/SubAlloc.h: |
| 794 | using VirtualAlloc for memory allocating | 805 | using VirtualAlloc for memory allocating |
| 795 | - Exlorer/ContextMenu.cpp: | 806 | - Exlorer/ContextMenu.cpp: |
| 796 | Testing supporting. | 807 | Testing supporting. |
| 797 | CreateProcess instead WinExec | 808 | CreateProcess instead WinExec |
| 798 | - Format/Common/IArchiveHandler.h: | 809 | - Format/Common/IArchiveHandler.h: |
| @@ -808,9 +819,9 @@ HISTORY of the 7-Zip source code | |||
| 808 | 819 | ||
| 809 | 2.30 Beta 10 2002-01-11 | 820 | 2.30 Beta 10 2002-01-11 |
| 810 | ------------------------- | 821 | ------------------------- |
| 811 | - Exlorer/ContextMenu.cpp: bug with context menu on | 822 | - Exlorer/ContextMenu.cpp: bug with context menu on |
| 812 | Windows NT4 in Unicode version was fixed. | 823 | Windows NT4 in Unicode version was fixed. |
| 813 | - Format/7z/UpdateArchiveEngine.cpp: bug was fixed - | 824 | - Format/7z/UpdateArchiveEngine.cpp: bug was fixed - |
| 814 | Updating in Beta 8 and 9 didn't work. | 825 | Updating in Beta 8 and 9 didn't work. |
| 815 | - Exlorer/CCompressDialog.cpp: history growing bug was fixed. | 826 | - Exlorer/CCompressDialog.cpp: history growing bug was fixed. |
| 816 | 827 | ||
| @@ -823,4 +834,3 @@ HISTORY of the 7-Zip source code | |||
| 823 | - SDK/Archive/Zip/InEngine.cpp: bug was fixed. | 834 | - SDK/Archive/Zip/InEngine.cpp: bug was fixed. |
| 824 | - SDK/Windows/FileDir.cpp: function CreateComplexDirectory | 835 | - SDK/Windows/FileDir.cpp: function CreateComplexDirectory |
| 825 | was changed. | 836 | was changed. |
| 826 | |||
