diff --git a/C/7zVersion.h b/C/7zVersion.h index 5fc7c9c5a..a8cbdb9c6 100644 --- a/C/7zVersion.h +++ b/C/7zVersion.h @@ -1,7 +1,7 @@ #define MY_VER_MAJOR 21 -#define MY_VER_MINOR 04 +#define MY_VER_MINOR 06 #define MY_VER_BUILD 0 -#define MY_VERSION_NUMBERS "21.04 beta" +#define MY_VERSION_NUMBERS "21.06" #define MY_VERSION MY_VERSION_NUMBERS #ifdef MY_CPU_NAME @@ -10,7 +10,7 @@ #define MY_VERSION_CPU MY_VERSION #endif -#define MY_DATE "2021-11-02" +#define MY_DATE "2021-11-24" #undef MY_COPYRIGHT #undef MY_VERSION_COPYRIGHT_DATE #define MY_AUTHOR_NAME "Igor Pavlov" diff --git a/C/7zip_gcc_c.mak b/C/7zip_gcc_c.mak index 09e66d57b..e88444077 100644 --- a/C/7zip_gcc_c.mak +++ b/C/7zip_gcc_c.mak @@ -5,6 +5,7 @@ MY_ASM = jwasm MY_ASM = asmc PROGPATH = $(O)/$(PROG) +PROGPATH_STATIC = $(O)/$(PROG)s # for object file @@ -53,7 +54,7 @@ endif PROGPATH = $(O)/$(PROG)$(SHARED_EXT) - +PROGPATH_STATIC = $(O)/$(PROG)s$(SHARED_EXT) ifndef O O=_o @@ -82,7 +83,7 @@ MY_MKDIR=mkdir -p # LOCAL_LIBS_DLL=$(LOCAL_LIBS) -ldl LIB2 = -lpthread -ldl -DEL_OBJ_EXE = -$(RM) $(PROGPATH) $(OBJS) +DEL_OBJ_EXE = -$(RM) $(PROGPATH) $(PROGPATH_STATIC) $(OBJS) endif @@ -108,14 +109,23 @@ CXX_WARN_FLAGS = CXXFLAGS = $(LOCAL_FLAGS) $(CXXFLAGS_BASE2) $(CFLAGS_BASE) $(CXXFLAGS_EXTRA) $(CC_SHARED) -o $@ $(CXX_WARN_FLAGS) -all: $(O) $(PROGPATH) +STATIC_TARGET= +ifdef COMPL_STATIC +STATIC_TARGET=$(PROGPATH_STATIC) +endif + + +all: $(O) $(PROGPATH) $(STATIC_TARGET) $(O): $(MY_MKDIR) $(O) +LFLAGS_ALL = -s $(MY_ARCH_2) $(LDFLAGS) $(LD_arch) $(OBJS) $(MY_LIBS) $(LIB2) $(PROGPATH): $(OBJS) - $(CXX) -s -o $(PROGPATH) $(MY_ARCH_2) $(LDFLAGS) $(OBJS) $(MY_LIBS) $(LIB2) + $(CXX) -o $(PROGPATH) $(LFLAGS_ALL) +$(PROGPATH_STATIC): $(OBJS) + $(CXX) -static -o $(PROGPATH_STATIC) $(LFLAGS_ALL) ifndef NO_DEFAULT_RES diff --git a/C/DllSecur.c b/C/DllSecur.c index 4b2c521db..3d2153240 100644 --- a/C/DllSecur.c +++ b/C/DllSecur.c @@ -1,5 +1,5 @@ /* DllSecur.c -- DLL loading security -2018-02-21 : Igor Pavlov : Public domain */ +2021-11-18 : Igor Pavlov : Public domain */ #include "Precomp.h" @@ -43,7 +43,7 @@ void My_SetDefaultDllDirectories() if (!GetVersionEx(&vi) || vi.dwMajorVersion != 6 || vi.dwMinorVersion != 0) { Func_SetDefaultDllDirectories setDllDirs = (Func_SetDefaultDllDirectories) - GetProcAddress(GetModuleHandle(TEXT("kernel32.dll")), "SetDefaultDllDirectories"); + (void(*)())GetProcAddress(GetModuleHandle(TEXT("kernel32.dll")), "SetDefaultDllDirectories"); if (setDllDirs) if (setDllDirs(MY_LOAD_LIBRARY_SEARCH_SYSTEM32 | MY_LOAD_LIBRARY_SEARCH_USER_DIRS)) return; @@ -66,7 +66,7 @@ void LoadSecurityDlls() if (!GetVersionEx(&vi) || vi.dwMajorVersion != 6 || vi.dwMinorVersion != 0) { Func_SetDefaultDllDirectories setDllDirs = (Func_SetDefaultDllDirectories) - GetProcAddress(GetModuleHandle(TEXT("kernel32.dll")), "SetDefaultDllDirectories"); + (void(*)())GetProcAddress(GetModuleHandle(TEXT("kernel32.dll")), "SetDefaultDllDirectories"); if (setDllDirs) if (setDllDirs(MY_LOAD_LIBRARY_SEARCH_SYSTEM32 | MY_LOAD_LIBRARY_SEARCH_USER_DIRS)) return; diff --git a/C/LzmaEnc.c b/C/LzmaEnc.c index 832e41493..b04a7b7b7 100644 --- a/C/LzmaEnc.c +++ b/C/LzmaEnc.c @@ -1,5 +1,5 @@ /* LzmaEnc.c -- LZMA Encoder -2021-07-10: Igor Pavlov : Public domain */ +2021-11-18: Igor Pavlov : Public domain */ #include "Precomp.h" @@ -668,12 +668,11 @@ static int RangeEnc_Alloc(CRangeEnc *p, ISzAllocPtr alloc) static void RangeEnc_Free(CRangeEnc *p, ISzAllocPtr alloc) { ISzAlloc_Free(alloc, p->bufBase); - p->bufBase = 0; + p->bufBase = NULL; } static void RangeEnc_Init(CRangeEnc *p) { - /* Stream.Init(); */ p->range = 0xFFFFFFFF; p->cache = 0; p->low = 0; @@ -687,12 +686,12 @@ static void RangeEnc_Init(CRangeEnc *p) MY_NO_INLINE static void RangeEnc_FlushStream(CRangeEnc *p) { - size_t num; - if (p->res != SZ_OK) - return; - num = (size_t)(p->buf - p->bufBase); - if (num != ISeqOutStream_Write(p->outStream, p->bufBase, num)) - p->res = SZ_ERROR_WRITE; + const size_t num = (size_t)(p->buf - p->bufBase); + if (p->res == SZ_OK) + { + if (num != ISeqOutStream_Write(p->outStream, p->bufBase, num)) + p->res = SZ_ERROR_WRITE; + } p->processed += num; p->buf = p->bufBase; } @@ -2946,9 +2945,12 @@ static size_t SeqOutStreamBuf_Write(const ISeqOutStream *pp, const void *data, s size = p->rem; p->overflow = True; } - memcpy(p->data, data, size); - p->rem -= size; - p->data += size; + if (size != 0) + { + memcpy(p->data, data, size); + p->rem -= size; + p->data += size; + } return size; } diff --git a/C/Util/7zipUninstall/7zipUninstall.c b/C/Util/7zipUninstall/7zipUninstall.c index b02fe5a1c..b4c6ff57f 100644 --- a/C/Util/7zipUninstall/7zipUninstall.c +++ b/C/Util/7zipUninstall/7zipUninstall.c @@ -1,5 +1,5 @@ /* 7zipUninstall.c - 7-Zip Uninstaller -2021-02-23 : Igor Pavlov : Public domain */ +2021-11-24 : Igor Pavlov : Public domain */ #include "Precomp.h" @@ -51,7 +51,7 @@ #endif #endif -#define k_7zip_with_Ver k_7zip_with_Ver_base k_Postfix +#define k_7zip_with_Ver k_7zip_with_Ver_base k_Postfix static LPCWSTR const k_7zip_with_Ver_Uninstall = k_7zip_with_Ver L" Uninstall"; @@ -404,6 +404,17 @@ static LPCWSTR const k_AppPaths_7zFm = L"Software\\Microsoft\\Windows\\CurrentVe static LPCWSTR const k_Uninstall_7zip = k_REG_Uninstall L"7-Zip"; +static void RemoveQuotes(wchar_t *s) +{ + const size_t len = wcslen(s); + size_t i; + if (len == 0 || s[0] != '\"' || s[len - 1] != '\"') + return; + for (i = 0; i < len; i++) + s[i] = s[i + 1]; + s[len - 2] = 0; +} + static BoolInt AreEqual_Path_PrefixName(const wchar_t *s, const wchar_t *prefix, const wchar_t *name) { if (!IsString1PrefixedByString2_NoCase(s, prefix)) @@ -490,12 +501,18 @@ static void WriteCLSID() if (MyRegistry_QueryString2(HKEY_LOCAL_MACHINE, k_AppPaths_7zFm, NULL, s)) + { + // RemoveQuotes(s); if (AreEqual_Path_PrefixName(s, path, L"7zFM.exe")) MyRegistry_DeleteKey(HKEY_LOCAL_MACHINE, k_AppPaths_7zFm); + } if (MyRegistry_QueryString2(HKEY_LOCAL_MACHINE, k_Uninstall_7zip, L"UninstallString", s)) + { + RemoveQuotes(s); if (AreEqual_Path_PrefixName(s, path, kUninstallExe)) MyRegistry_DeleteKey(HKEY_LOCAL_MACHINE, k_Uninstall_7zip); + } } diff --git a/CPP/7zip/7zip_gcc.mak b/CPP/7zip/7zip_gcc.mak index 590742143..b8e5eb3e0 100644 --- a/CPP/7zip/7zip_gcc.mak +++ b/CPP/7zip/7zip_gcc.mak @@ -10,6 +10,7 @@ MY_ASM = jwasm MY_ASM = asmc PROGPATH = $(O)/$(PROG) +PROGPATH_STATIC = $(O)/$(PROG)s ifneq ($(CC), xlc) @@ -88,7 +89,7 @@ endif PROGPATH = $(O)/$(PROG)$(SHARED_EXT) - +PROGPATH_STATIC = $(O)/$(PROG)s$(SHARED_EXT) ifdef IS_MINGW @@ -114,7 +115,7 @@ LIB2 = -lpthread -ldl -DEL_OBJ_EXE = -$(RM) $(PROGPATH) $(OBJS) +DEL_OBJ_EXE = -$(RM) $(PROGPATH) $(PROGPATH_STATIC) $(OBJS) endif @@ -150,13 +151,23 @@ CXX_WARN_FLAGS = CXXFLAGS = $(MY_ARCH_2) $(LOCAL_FLAGS) $(CXXFLAGS_BASE2) $(CFLAGS_BASE) $(CXXFLAGS_EXTRA) $(CC_SHARED) -o $@ $(CXX_WARN_FLAGS) -all: $(O) $(PROGPATH) +STATIC_TARGET= +ifdef COMPL_STATIC +STATIC_TARGET=$(PROGPATH_STATIC) +endif + + +all: $(O) $(PROGPATH) $(STATIC_TARGET) $(O): $(MY_MKDIR) $(O) +LFLAGS_ALL = -s $(MY_ARCH_2) $(LDFLAGS) $(LD_arch) $(OBJS) $(MY_LIBS) $(LIB2) $(PROGPATH): $(OBJS) - $(CXX) -o $(PROGPATH) -s $(MY_ARCH_2) $(LDFLAGS) $(LD_arch) $(OBJS) $(MY_LIBS) $(LIB2) + $(CXX) -o $(PROGPATH) $(LFLAGS_ALL) + +$(PROGPATH_STATIC): $(OBJS) + $(CXX) -static -o $(PROGPATH_STATIC) $(LFLAGS_ALL) # -s strips debug sections from executable in GCC diff --git a/CPP/7zip/Archive/Common/HandlerOut.cpp b/CPP/7zip/Archive/Common/HandlerOut.cpp index bd673fcc5..6c62befa1 100644 --- a/CPP/7zip/Archive/Common/HandlerOut.cpp +++ b/CPP/7zip/Archive/Common/HandlerOut.cpp @@ -27,11 +27,30 @@ bool ParseSizeString(const wchar_t *s, const PROPVARIANT &prop, UInt64 percentsB else if (prop.vt != VT_EMPTY) return false; + bool percentMode = false; + { + const wchar_t c = *s; + if (MyCharLower_Ascii(c) == 'p') + { + percentMode = true; + s++; + } + } + const wchar_t *end; - UInt64 v = ConvertStringToUInt64(s, &end); + const UInt64 v = ConvertStringToUInt64(s, &end); if (s == end) return false; - wchar_t c = *end; + const wchar_t c = *end; + + if (percentMode) + { + if (c != 0) + return false; + res = Calc_From_Val_Percents(percentsBase, v); + return true; + } + if (c == 0) { res = v; @@ -42,7 +61,7 @@ bool ParseSizeString(const wchar_t *s, const PROPVARIANT &prop, UInt64 percentsB if (c == '%') { - res = percentsBase / 100 * v; + res = Calc_From_Val_Percents(percentsBase, v); return true; } @@ -56,7 +75,7 @@ bool ParseSizeString(const wchar_t *s, const PROPVARIANT &prop, UInt64 percentsB case 't': numBits = 40; break; default: return false; } - UInt64 val2 = v << numBits; + const UInt64 val2 = v << numBits; if ((val2 >> numBits) != v) return false; res = val2; diff --git a/CPP/7zip/Archive/Common/HandlerOut.h b/CPP/7zip/Archive/Common/HandlerOut.h index 619def429..b3d07e9e9 100644 --- a/CPP/7zip/Archive/Common/HandlerOut.h +++ b/CPP/7zip/Archive/Common/HandlerOut.h @@ -36,7 +36,10 @@ class CCommonMethodProps if (memAvail > limit2) memAvail = limit2; } - _memUsage_Compress = memAvail / 32 * 28; + // 80% - is auto usage limit in handlers + // _memUsage_Compress = memAvail * 4 / 5; + // _memUsage_Compress = Calc_From_Val_Percents(memAvail, 80); + _memUsage_Compress = Calc_From_Val_Percents_Less100(memAvail, 80); _memUsage_Decompress = memAvail / 32 * 17; } } diff --git a/CPP/7zip/Archive/Nsis/NsisIn.cpp b/CPP/7zip/Archive/Nsis/NsisIn.cpp index 3c1a0f173..4e2d7a9d2 100644 --- a/CPP/7zip/Archive/Nsis/NsisIn.cpp +++ b/CPP/7zip/Archive/Nsis/NsisIn.cpp @@ -82,14 +82,14 @@ enum EW_READENVSTR, // ReadEnvStr, ExpandEnvStrings EW_INTCMP, // IntCmp, IntCmpU EW_INTOP, // IntOp - EW_INTFMT, // IntFmt + EW_INTFMT, // IntFmt/Int64Fmt EW_PUSHPOP, // Push/Pop/Exchange EW_FINDWINDOW, // FindWindow EW_SENDMESSAGE, // SendMessage EW_ISWINDOW, // IsWindow EW_GETDLGITEM, // GetDlgItem EW_SETCTLCOLORS, // SetCtlColors - EW_SETBRANDINGIMAGE, // SetBrandingImage + EW_SETBRANDINGIMAGE, // SetBrandingImage / LoadAndSetImage EW_CREATEFONT, // CreateFont EW_SHOWWINDOW, // ShowWindow, EnableWindow, HideWindow EW_SHELLEXEC, // ExecShell @@ -131,9 +131,16 @@ enum EW_SECTIONSET, // Get*, Set* EW_INSTTYPESET, // InstTypeSetText, InstTypeGetText, SetCurInstType, GetCurInstType + /* + // before v3.06 nsis it was so: // instructions not actually implemented in exehead, but used in compiler. EW_GETLABELADDR, // both of these get converted to EW_ASSIGNVAR EW_GETFUNCTIONADDR, + */ + + // v3.06 and later it was changed to: + EW_GETOSINFO, + EW_RESERVEDOPCODE, EW_LOCKWINDOW, // LockWindow @@ -141,6 +148,13 @@ enum EW_FPUTWS, // FileWriteUTF16LE, FileWriteWord EW_FGETWS, // FileReadUTF16LE, FileReadWord + /* + // since v3.06 the fllowing IDs codes was moved here: + // Opcodes listed here are not actually used in exehead. No exehead opcodes should be present after these! + EW_GETLABELADDR, // --> EW_ASSIGNVAR + EW_GETFUNCTIONADDR, // --> EW_ASSIGNVAR + */ + // The following IDs are not IDs in real order. // We just need some IDs to translate eny extended layout to main layout. @@ -194,20 +208,20 @@ static const CCommandInfo k_Commands[kNumCmds] = { 3 }, // ReadEnvStr, ExpandEnvStrings { 6 }, // "IntCmp" }, { 4 }, // "IntOp" }, - { 3 }, // "IntFmt" }, + { 4 }, // "IntFmt" }, EW_INTFMT { 6 }, // Push, Pop, Exch // it must be 3 params. But some multi-command write garbage. { 5 }, // "FindWindow" }, { 6 }, // "SendMessage" }, { 3 }, // "IsWindow" }, { 3 }, // "GetDlgItem" }, { 2 }, // "SetCtlColors" }, - { 3 }, // "SetBrandingImage" }, + { 4 }, // "SetBrandingImage" } // LoadAndSetImage { 5 }, // "CreateFont" }, { 4 }, // ShowWindow, EnableWindow, HideWindow { 6 }, // "ExecShell" }, { 3 }, // "Exec" }, // Exec, ExecWait { 3 }, // "GetFileTime" }, - { 3 }, // "GetDLLVersion" }, + { 4 }, // "GetDLLVersion" }, { 6 }, // RegDLL, UnRegDLL, CallInstDLL // it must be 5 params. But some multi-command write garbage. { 6 }, // "CreateShortCut" }, { 4 }, // "CopyFiles" }, @@ -229,10 +243,14 @@ static const CCommandInfo k_Commands[kNumCmds] = { 4 }, // "WriteUninstaller" }, { 5 }, // "Section" }, // *** { 4 }, // InstTypeSetText, InstTypeGetText, SetCurInstType, GetCurInstType - { 6 }, // "GetLabelAddr" }, - { 2 }, // "GetFunctionAddress" }, + + // { 6 }, // "GetLabelAddr" }, // before 3.06 + { 6 }, // "GetOsInfo" }, GetKnownFolderPath, ReadMemory, // v3.06+ + + { 2 }, // "GetFunctionAddress" }, // before 3.06 + { 1 }, // "LockWindow" }, - { 3 }, // "FileWrite" }, // FileWriteUTF16LE, FileWriteWord + { 4 }, // "FileWrite" }, // FileWriteUTF16LE, FileWriteWord { 4 }, // "FileRead" }, // FileReadUTF16LE, FileReadWord { 2 }, // "Log" }, // LogSet, LogText @@ -274,9 +292,9 @@ static const char * const k_CommandNames[kNumCmds] = , NULL // StrCpy, GetCurrentAddress , "StrCmp" , NULL // ReadEnvStr, ExpandEnvStrings - , "IntCmp" + , NULL // IntCmp / Int64Cmp / EW_INTCMP , "IntOp" - , "IntFmt" + , NULL // IntFmt / Int64Fmt / EW_INTFMT , NULL // Push, Pop, Exch // it must be 3 params. But some multi-command write garbage. , "FindWindow" , "SendMessage" @@ -311,8 +329,10 @@ static const char * const k_CommandNames[kNumCmds] = , "WriteUninstaller" , "Section" // *** , NULL // InstTypeSetText, InstTypeGetText, SetCurInstType, GetCurInstType - , "GetLabelAddr" + + , NULL // "GetOsInfo" // , "GetLabelAddr" // , "GetFunctionAddress" + , "LockWindow" , "FileWrite" // FileWriteUTF16LE, FileWriteWord , "FileRead" // FileReadUTF16LE, FileReadWord @@ -1715,7 +1735,10 @@ static bool StringToUInt32(const char *s, UInt32 &res) return (*end == 0); } -static const unsigned k_CtlColors_Size = 24; +static const unsigned k_CtlColors32_Size = 24; +static const unsigned k_CtlColors64_Size = 28; + +#define GET_CtlColors_SIZE(is64) ((is64) ? k_CtlColors64_Size : k_CtlColors32_Size) struct CNsis_CtlColors { @@ -1725,16 +1748,27 @@ struct CNsis_CtlColors UInt32 bkb; // HBRUSH Int32 bkmode; Int32 flags; + UInt32 bkb_hi32; - void Parse(const Byte *p); + void Parse(const Byte *p, bool is64); }; -void CNsis_CtlColors::Parse(const Byte *p) +void CNsis_CtlColors::Parse(const Byte *p, bool is64) { text = Get32(p); bkc = Get32(p + 4); - lbStyle = Get32(p + 8); - bkb = Get32(p + 12); + if (is64) + { + bkb = Get32(p + 8); + bkb_hi32 = Get32(p + 12); + lbStyle = Get32(p + 16); + p += 4; + } + else + { + lbStyle = Get32(p + 8); + bkb = Get32(p + 12); + } bkmode = (Int32)Get32(p + 16); flags = (Int32)Get32(p + 20); } @@ -2427,11 +2461,22 @@ void CInArchive::FindBadCmd(const CBlockHeader &bh, const Byte *p) if (BadCmd >= 0 && id >= (unsigned)BadCmd) continue; unsigned i; - if (id == EW_GETLABELADDR || - id == EW_GETFUNCTIONADDR) + if (IsNsis3_OrHigher()) { - BadCmd = id; - continue; + if (id == EW_RESERVEDOPCODE) + { + BadCmd = id; + continue; + } + } + else + { + // if (id == EW_GETLABELADDR || id == EW_GETFUNCTIONADDR) + if (id == EW_RESERVEDOPCODE || id == EW_GETOSINFO) + { + BadCmd = id; + continue; + } } for (i = 6; i != 0; i--) { @@ -3148,7 +3193,7 @@ HRESULT CInArchive::ReadEntries(const CBlockHeader &bh) && CompareCommands(p, k_InitPluginDir_Commands, ARRAY_SIZE(k_InitPluginDir_Commands))) { InitPluginsDir_Start = kkk; - InitPluginsDir_End = kkk + ARRAY_SIZE(k_InitPluginDir_Commands); + InitPluginsDir_End = (int)(kkk + ARRAY_SIZE(k_InitPluginDir_Commands)); labels[kkk] |= CMD_REF_InitPluginDir; break; } @@ -3369,7 +3414,7 @@ HRESULT CInArchive::ReadEntries(const CBlockHeader &bh) #ifdef NSIS_SCRIPT s += isSetOutPath ? "SetOutPath" : "CreateDirectory"; AddParam(params[0]); - if (params[2] != 0) + if (params[2] != 0) // 2.51+ & 3.0b3+ { SmallSpaceComment(); s += "CreateRestrictedDirectory"; @@ -4017,7 +4062,12 @@ HRESULT CInArchive::ReadEntries(const CBlockHeader &bh) case EW_INTCMP: { - if (params[5] != 0) + s += "Int"; + const UInt32 param5 = params[5]; + if (param5 & 0x8000) + s += "64"; // v3.03+ + s += "Cmp"; + if (IsNsis3_OrHigher() ? (param5 & 1) : (param5 != 0)) s += 'U'; AddParams(params, 2); Add_GotoVar1(params[2]); @@ -4029,13 +4079,13 @@ HRESULT CInArchive::ReadEntries(const CBlockHeader &bh) case EW_INTOP: { AddParam_Var(params[0]); - const char * const kOps = "+-*/|&^!|&%<>"; // NSIS 2.01+ + const char * const kOps = "+-*/|&^!|&%<>>"; // NSIS 2.01+ // "+-*/|&^!|&%"; // NSIS 2.0b4+ // "+-*/|&^~!|&%"; // NSIS old - UInt32 opIndex = params[3]; - char c = (opIndex < 13) ? kOps[opIndex] : '?'; - char c2 = (opIndex < 8 || opIndex == 10) ? (char)0 : c; - int numOps = (opIndex == 7) ? 1 : 2; + const UInt32 opIndex = params[3]; + const char c = (opIndex < 14) ? kOps[opIndex] : '?'; + const char c2 = (opIndex < 8 || opIndex == 10) ? (char)0 : c; + const int numOps = (opIndex == 7) ? 1 : 2; AddParam(params[1]); if (numOps == 2 && c == '^' && IsDirectString_Equal(params[2], "0xFFFFFFFF")) s += " ~ ;"; @@ -4043,6 +4093,8 @@ HRESULT CInArchive::ReadEntries(const CBlockHeader &bh) s += c; if (numOps != 1) { + if (opIndex == 13) // v3.03+ : operation ">>>" + s += c; if (c2 != 0) s += c2; AddParam(params[2]); @@ -4052,6 +4104,10 @@ HRESULT CInArchive::ReadEntries(const CBlockHeader &bh) case EW_INTFMT: { + if (params[3]) + s += "Int64Fmt"; // v3.03+ + else + s += "IntFmt"; AddParam_Var(params[0]); AddParams(params + 1, 2); break; @@ -4172,7 +4228,7 @@ HRESULT CInArchive::ReadEntries(const CBlockHeader &bh) if (_size < bhCtlColors.Offset || _size - bhCtlColors.Offset < offset - || _size - bhCtlColors.Offset - offset < k_CtlColors_Size) + || _size - bhCtlColors.Offset - offset < GET_CtlColors_SIZE(Is64Bit)) { AddError("bad offset"); break; @@ -4180,7 +4236,7 @@ HRESULT CInArchive::ReadEntries(const CBlockHeader &bh) const Byte *p2 = _data + bhCtlColors.Offset + offset; CNsis_CtlColors colors; - colors.Parse(p2); + colors.Parse(p2, Is64Bit); if ((colors.flags & kColorsFlags_BK_SYS) != 0 || (colors.flags & kColorsFlags_TEXT_SYS) != 0) @@ -4214,6 +4270,7 @@ HRESULT CInArchive::ReadEntries(const CBlockHeader &bh) break; } + // case EW_LOADANDSETIMAGE: case EW_SETBRANDINGIMAGE: { s += " /IMGID="; @@ -4312,6 +4369,9 @@ HRESULT CInArchive::ReadEntries(const CBlockHeader &bh) case EW_GETFILETIME: case EW_GETDLLVERSION: { + if (commandId == EW_GETDLLVERSION) + if (params[3] == 2) + s += " /ProductVersion"; // v3.08+ AddParam(params[2]); AddParam_Var(params[0]); AddParam_Var(params[1]); @@ -4354,11 +4414,15 @@ HRESULT CInArchive::ReadEntries(const CBlockHeader &bh) case EW_CREATESHORTCUT: { unsigned numParams; + #define IsNsis3d0b3_OrHigher() 0 // change it + const unsigned v3_0b3 = IsNsis3d0b3_OrHigher(); for (numParams = 6; numParams > 2; numParams--) if (params[numParams - 1] != 0) break; - UInt32 spec = params[4]; + const UInt32 spec = params[4]; + const unsigned sw_shift = v3_0b3 ? 12 : 8; + const UInt32 sw_mask = v3_0b3 ? 0x7000 : 0x7F; if (spec & 0x8000) // NSIS 3.0b0 s += " /NoWorkingDir"; @@ -4366,16 +4430,16 @@ HRESULT CInArchive::ReadEntries(const CBlockHeader &bh) if (numParams <= 4) break; - UInt32 icon = (spec & 0xFF); + UInt32 icon = (spec & (v3_0b3 ? 0xFFF : 0xFF)); Space(); if (icon != 0) Add_UInt(icon); else AddQuotes(); - if ((spec >> 8) == 0 && numParams < 6) + if ((spec >> sw_shift) == 0 && numParams < 6) break; - UInt32 sw = (spec >> 8) & 0x7F; + UInt32 sw = (spec >> sw_shift) & sw_mask; Space(); // NSIS encoder replaces these names: if (sw == MY__SW_SHOWMINNOACTIVE) @@ -4485,6 +4549,7 @@ HRESULT CInArchive::ReadEntries(const CBlockHeader &bh) s += "Key"; if (params[4] & 2) s += " /ifempty"; + // TODO: /ifnosubkeys, /ifnovalues } AddRegRoot(params[1]); AddParam(params[2]); @@ -4507,6 +4572,8 @@ HRESULT CInArchive::ReadEntries(const CBlockHeader &bh) } if (params[4] == 1 && params[5] == 2) s2 = "ExpandStr"; + if (params[4] == 3 && params[5] == 7) + s2 = "MultiStr"; // v3.02+ if (s2) s += s2; AddRegRoot(params[0]); @@ -4627,6 +4694,8 @@ HRESULT CInArchive::ReadEntries(const CBlockHeader &bh) s += (params[2] == 0) ? "UTF16LE" : "Word"; else if (params[2] != 0) s += "Byte"; + if (params[2] == 0 && params[3]) + s += " /BOM"; // v3.0b3+ AddParam_Var(params[0]); AddParam(params[1]); break; @@ -4755,6 +4824,34 @@ HRESULT CInArchive::ReadEntries(const CBlockHeader &bh) AddParam_Var(params[1]); break; } + + case EW_GETOSINFO: + { + if (IsNsis3_OrHigher()) + { + // v3.06+ + if (params[3] == 0) // GETOSINFO_KNOWNFOLDER + { + s += "GetKnownFolderPath"; + AddParam_Var(params[1]); + AddParam(params[2]); + break; + } + else if (params[3] == 1) // GETOSINFO_READMEMORY + { + s += "ReadMemory"; + AddParam_Var(params[1]); + AddParam(params[2]); + AddParam(params[4]); + // if (params[2] == "0") AddCommentAndString("GetWinVer"); + } + else + s += "GetOsInfo"; + break; + } + s += "GetLabelAddr"; // before v3.06+ + break; + } case EW_LOCKWINDOW: { @@ -5111,8 +5208,12 @@ HRESULT CInArchive::Parse() } AddLF(); - if (IsUnicode) + if (Is64Bit) + AddStringLF("Target AMD64-Unicode"); // TODO: Read PE machine type and use the correct CPU type + else if (IsUnicode) AddStringLF("Unicode true"); + else if (IsNsis3_OrHigher()) + AddStringLF("Unicode false"); // Unicode is the default in 3.07+ if (Method != NMethodType::kCopy) { diff --git a/CPP/7zip/Archive/Nsis/NsisIn.h b/CPP/7zip/Archive/Nsis/NsisIn.h index 5c88188dc..1d92e12f0 100644 --- a/CPP/7zip/Archive/Nsis/NsisIn.h +++ b/CPP/7zip/Archive/Nsis/NsisIn.h @@ -176,6 +176,7 @@ class CInArchive int BadCmd; // -1: no bad command; in another cases lowest bad command id bool IsPark() const { return NsisType >= k_NsisType_Park1; } + bool IsNsis3_OrHigher() const { return NsisType == k_NsisType_Nsis3; } UInt64 _fileSize; diff --git a/CPP/7zip/Archive/Tar/TarHandler.cpp b/CPP/7zip/Archive/Tar/TarHandler.cpp index c1073092c..6fc38e33d 100644 --- a/CPP/7zip/Archive/Tar/TarHandler.cpp +++ b/CPP/7zip/Archive/Tar/TarHandler.cpp @@ -766,6 +766,9 @@ STDMETHODIMP CHandler::SetProperties(const wchar_t * const *names, const PROPVAR else if (name.IsPrefixedBy_Ascii_NoCase("mt")) { } + else if (name.IsPrefixedBy_Ascii_NoCase("memuse")) + { + } else return E_INVALIDARG; } diff --git a/CPP/7zip/Archive/VdiHandler.cpp b/CPP/7zip/Archive/VdiHandler.cpp index 66cf39cdd..b5e471863 100644 --- a/CPP/7zip/Archive/VdiHandler.cpp +++ b/CPP/7zip/Archive/VdiHandler.cpp @@ -32,7 +32,17 @@ static const Byte k_Signature[] = SIGNATURE; static const unsigned k_ClusterBits = 20; static const UInt32 k_ClusterSize = (UInt32)1 << k_ClusterBits; -static const UInt32 k_UnusedCluster = 0xFFFFFFFF; + + +/* +VDI_IMAGE_BLOCK_FREE = (~0) // returns any random data +VDI_IMAGE_BLOCK_ZERO = (~1) // returns zeros +*/ + +// static const UInt32 k_ClusterType_Free = 0xffffffff; +static const UInt32 k_ClusterType_Zero = 0xfffffffe; + +#define IS_CLUSTER_ALLOCATED(v) ((UInt32)(v) < k_ClusterType_Zero) // static const UInt32 kDiskType_Dynamic = 1; @@ -135,8 +145,8 @@ STDMETHODIMP CHandler::Read(void *data, UInt32 size, UInt32 *processedSize) if (cluster < _table.Size()) { const Byte *p = (const Byte *)_table + (size_t)cluster; - UInt32 v = Get32(p); - if (v != k_UnusedCluster) + const UInt32 v = Get32(p); + if (IS_CLUSTER_ALLOCATED(v)) { UInt64 offset = _dataOffset + ((UInt64)v << k_ClusterBits); offset += lowBits; @@ -374,8 +384,8 @@ HRESULT CHandler::Open2(IInStream *stream, IArchiveOpenCallback * /* openCallbac const Byte *data = _table; for (UInt32 i = 0; i < totalBlocks; i++) { - UInt32 v = Get32(data + (size_t)i * 4); - if (v == k_UnusedCluster) + const UInt32 v = Get32(data + (size_t)i * 4); + if (!IS_CLUSTER_ALLOCATED(v)) continue; if (v >= numAllocatedBlocks) { diff --git a/CPP/7zip/Archive/Wim/WimHandler.cpp b/CPP/7zip/Archive/Wim/WimHandler.cpp index b25d51c24..9e39d028e 100644 --- a/CPP/7zip/Archive/Wim/WimHandler.cpp +++ b/CPP/7zip/Archive/Wim/WimHandler.cpp @@ -1209,6 +1209,12 @@ STDMETHODIMP CHandler::SetProperties(const wchar_t * const *names, const PROPVAR RINOK(ParsePropToUInt32(L"", prop, image)); _defaultImageNumber = image; } + else if (name.IsPrefixedBy_Ascii_NoCase("mt")) + { + } + else if (name.IsPrefixedBy_Ascii_NoCase("memuse")) + { + } else return E_INVALIDARG; } diff --git a/CPP/7zip/Common/MethodProps.cpp b/CPP/7zip/Common/MethodProps.cpp index a55c49f95..0e8ff1c61 100644 --- a/CPP/7zip/Common/MethodProps.cpp +++ b/CPP/7zip/Common/MethodProps.cpp @@ -8,6 +8,36 @@ using namespace NWindows; +UInt64 Calc_From_Val_Percents(UInt64 val, UInt64 percents) +{ + // if (percents == 0) return 0; + const UInt64 q = percents / 100; + const UInt32 r = (UInt32)(percents % 100); + UInt64 res = 0; + + if (q != 0) + { + if (val > (UInt64)(Int64)-1 / q) + return (UInt64)(Int64)-1; + res = val * q; + } + + if (r != 0) + { + UInt64 v2; + if (val <= (UInt64)(Int64)-1 / r) + v2 = val * r / 100; + else + v2 = val / 100 * r; + res += v2; + if (res < v2) + return (UInt64)(Int64)-1; + } + + return res; +} + + bool StringToBool(const wchar_t *s, bool &res) { if (s[0] == 0 || (s[0] == '+' && s[1] == 0) || StringsAreEqualNoCase_Ascii(s, "ON")) @@ -119,7 +149,7 @@ HRESULT ParseMtProp2(const UString &name, const PROPVARIANT &prop, UInt32 &numTh UInt32 v = numThreads; /* we force up, if threads number specified - only `d` will force it down */ + only `d` will force it down */ bool force_loc = true; for (;;) { diff --git a/CPP/7zip/Common/MethodProps.h b/CPP/7zip/Common/MethodProps.h index aea75a3ee..5b5c96a45 100644 --- a/CPP/7zip/Common/MethodProps.h +++ b/CPP/7zip/Common/MethodProps.h @@ -14,6 +14,17 @@ // UInt64 GetMemoryUsage_LZMA(UInt32 dict, bool isBt, UInt32 numThreads); +inline UInt64 Calc_From_Val_Percents_Less100(UInt64 val, UInt64 percents) +{ + if (percents == 0) + return 0; + if (val <= (UInt64)(Int64)-1 / percents) + return val * percents / 100; + return val / 100 * percents; +} + +UInt64 Calc_From_Val_Percents(UInt64 val, UInt64 percents); + bool StringToBool(const wchar_t *s, bool &res); HRESULT PROPVARIANT_to_bool(const PROPVARIANT &prop, bool &dest); unsigned ParseStringToUInt32(const UString &srcString, UInt32 &number); diff --git a/CPP/7zip/UI/Common/ArchiveExtractCallback.cpp b/CPP/7zip/UI/Common/ArchiveExtractCallback.cpp index b85a0ae6a..9fea6dc25 100644 --- a/CPP/7zip/UI/Common/ArchiveExtractCallback.cpp +++ b/CPP/7zip/UI/Common/ArchiveExtractCallback.cpp @@ -348,6 +348,8 @@ STDMETHODIMP CArchiveExtractCallback::SetRatioInfo(const UInt64 *inSize, const U void CArchiveExtractCallback::CreateComplexDirectory(const UStringVector &dirPathParts, FString &fullPath) { + // we use (_item.IsDir) in this function + bool isAbsPath = false; if (!dirPathParts.IsEmpty()) @@ -375,12 +377,41 @@ void CArchiveExtractCallback::CreateComplexDirectory(const UStringVector &dirPat fullPath.Add_PathSepar(); const UString &s = dirPathParts[i]; fullPath += us2fs(s); + + const bool isFinalDir = (i == dirPathParts.Size() - 1 && _item.IsDir); + + if (fullPath.IsEmpty()) + { + if (isFinalDir) + _itemFailure = true; + continue; + } + #if defined(_WIN32) && !defined(UNDER_CE) if (_pathMode == NExtract::NPathMode::kAbsPaths) if (i == 0 && s.Len() == 2 && NName::IsDrivePath2(s)) + { + if (isFinalDir) + { + // we don't want to call SetAttrib() for root drive path + _itemFailure = true; + } continue; + } #endif + + // bool res = CreateDir(fullPath); + // if (!res) + if (isFinalDir) + { + if (!NFile::NFind::DoesDirExist(fullPath)) + { + _itemFailure = true; + SendMessageError("Cannot create folder", fullPath); + // SendMessageError_with_LastError() + } + } } } @@ -655,6 +686,7 @@ HRESULT CArchiveExtractCallback::ReadLink() { IInArchive *archive = _arc->Archive; const UInt32 index = _index; + _link.Clear(); { NCOM::CPropVariant prop; @@ -717,7 +749,8 @@ HRESULT CArchiveExtractCallback::ReadLink() if (propType != NPropDataType::kRaw) return E_FAIL; - #ifdef _WIN32 + // 21.06: we need kpidNtReparse in linux for wim archives created in Windows + // #ifdef _WIN32 NtReparse_Data = data; NtReparse_Size = dataSize; @@ -739,11 +772,14 @@ HRESULT CArchiveExtractCallback::ReadLink() else _link.isRelative = reparse.IsRelative_Win(); + // const AString s = GetAnsiString(_link.linkPath); + // printf("\n_link.linkPath: %s\n", s.Ptr()); + #ifndef _WIN32 _link.linkPath.Replace(L'\\', WCHAR_PATH_SEPARATOR); #endif } - #endif + // #endif } } @@ -908,7 +944,10 @@ void CArchiveExtractCallback::CreateFolders() if (!_item.IsDir) return; - CDirPathTime &pt = _extractedFolders.AddNew(); + if (_itemFailure) + return; + + CDirPathTime pt; pt.CTime = _fi.CTime; pt.CTimeDefined = (WriteCTime && _fi.CTimeDefined); @@ -931,9 +970,13 @@ void CArchiveExtractCallback::CreateFolders() pt.MTimeDefined = true; } } - - pt.Path = fullPathNew; - pt.SetDirTime(); + + if (pt.MTimeDefined || pt.ATimeDefined || pt.CTimeDefined) + { + pt.Path = fullPathNew; + pt.SetDirTime(); + _extractedFolders.Add(pt); + } } @@ -1125,7 +1168,11 @@ HRESULT CArchiveExtractCallback::GetExtractStream(CMyComPtr 0 && _curSize < (1 << 12)) { if (_fi.IsLinuxSymLink()) { - _is_SymLink_in_Data = true; + is_SymLink_in_Data = true; _is_SymLink_in_Data_Linux = true; } else if (_fi.IsReparse()) { - _is_SymLink_in_Data = true; + is_SymLink_in_Data = true; _is_SymLink_in_Data_Linux = false; } } - if (_is_SymLink_in_Data) + + if (is_SymLink_in_Data) { _outMemBuf.Alloc((size_t)_curSize); _bufPtrSeqOutStream_Spec = new CBufPtrSeqOutStream; @@ -1347,17 +1406,36 @@ STDMETHODIMP CArchiveExtractCallback::GetStream(UInt32 index, ISequentialOutStre _diskFilePath.Empty(); _isRenamed = false; + // _fi.Clear(); - _is_SymLink_in_Data = false; - _is_SymLink_in_Data_Linux = false; - _fileWasExtracted = false; + // _is_SymLink_in_Data = false; + _is_SymLink_in_Data_Linux = false; + + _needSetAttrib = false; + _isSymLinkCreated = false; + _itemFailure = false; #ifdef SUPPORT_LINKS // _CopyFile_Path.Empty(); _link.Clear(); #endif + _extractMode = false; + + switch (askExtractMode) + { + case NArchive::NExtract::NAskMode::kExtract: + if (_testMode) + { + // askExtractMode = NArchive::NExtract::NAskMode::kTest; + } + else + _extractMode = true; + break; + }; + + IInArchive *archive = _arc->Archive; RINOK(GetItem(index)); @@ -1832,6 +1910,7 @@ HRESULT CArchiveExtractCallback::SetFromLinkPath( bool CLinkInfo::Parse(const Byte *data, size_t dataSize, bool isLinuxData) { + Clear(); // this->isLinux = isLinuxData; if (isLinuxData) @@ -1955,10 +2034,20 @@ HRESULT CArchiveExtractCallback::CloseReparseAndFile() RINOK(SendMessageError_with_LastError("can't delete file", _diskFilePath)); } { + /* + // for DEBUG ONLY: we can extract sym links as WSL links + // to elimanate (non-admin) errors for sym links. + #ifdef _WIN32 + if (!linkInfo.isHardLink && !linkInfo.isJunction) + linkInfo.isWSL = true; + #endif + */ bool linkWasSet = false; RINOK(SetFromLinkPath(_diskFilePath, linkInfo, linkWasSet)); - if (!linkWasSet) - _fileWasExtracted = false; + if (linkWasSet) + _isSymLinkCreated = linkInfo.IsSymLink(); + else + _needSetAttrib = false; } /* if (!NFile::NIO::SetReparseData(_diskFilePath, _item.IsDir, )) @@ -1974,11 +2063,40 @@ HRESULT CArchiveExtractCallback::CloseReparseAndFile() } +void CArchiveExtractCallback::SetAttrib() +{ + #ifndef _WIN32 + // Linux now doesn't support permissions for symlinks + if (_isSymLinkCreated) + return; + #endif + + if (_itemFailure + || _diskFilePath.IsEmpty() + || _stdOutMode + || !_extractMode + || !_fi.AttribDefined) + return; + + { + // const AString s = GetAnsiString(_diskFilePath); + // printf("\nSetFileAttrib_PosixHighDetect: %s: hex:%x\n", s.Ptr(), _fi.Attrib); + bool res = SetFileAttrib_PosixHighDetect(_diskFilePath, _fi.Attrib); + if (!res) + { + // do we need error message here in Windows and in posix? + SendMessageError_with_LastError("Cannot set file attribute", _diskFilePath); + } + } +} + STDMETHODIMP CArchiveExtractCallback::SetOperationResult(Int32 opRes) { COM_TRY_BEGIN + // printf("\nCArchiveExtractCallback::SetOperationResult: %d %s\n", opRes, GetAnsiString(_diskFilePath)); + #ifndef _SFX if (ExtractToStreamCallback) { @@ -2052,16 +2170,8 @@ STDMETHODIMP CArchiveExtractCallback::SetOperationResult(Int32 opRes) else NumFiles++; - if (_fileWasExtracted) - if (!_stdOutMode && _extractMode && _fi.AttribDefined) - { - bool res = SetFileAttrib_PosixHighDetect(_diskFilePath, _fi.Attrib); - if (!res) - { - // do we need error message here in Windows and in posix? - SendMessageError_with_LastError("Cannot set file attribute", _diskFilePath); - } - } + if (_needSetAttrib) + SetAttrib(); RINOK(_extractCallback2->SetOperationResult(opRes, BoolToInt(_encrypted))); diff --git a/CPP/7zip/UI/Common/ArchiveExtractCallback.h b/CPP/7zip/UI/Common/ArchiveExtractCallback.h index e44801de2..fe9cb32eb 100644 --- a/CPP/7zip/UI/Common/ArchiveExtractCallback.h +++ b/CPP/7zip/UI/Common/ArchiveExtractCallback.h @@ -189,7 +189,17 @@ struct CLinkInfo bool isRelative; bool isWSL; UString linkPath; - + + bool IsSymLink() const { return !isHardLink; } + + CLinkInfo(): + // IsCopyLink(false), + isHardLink(false), + isJunction(false), + isRelative(false), + isWSL(false) + {} + void Clear() { // IsCopyLink = false; @@ -291,10 +301,12 @@ class CArchiveExtractCallback: } } _fi; - bool _is_SymLink_in_Data; + // bool _is_SymLink_in_Data; bool _is_SymLink_in_Data_Linux; // false = WIN32, true = LINUX - bool _fileWasExtracted; + bool _needSetAttrib; + bool _isSymLinkCreated; + bool _itemFailure; UInt32 _index; UInt64 _curSize; @@ -352,6 +364,8 @@ class CArchiveExtractCallback: FString Hash_GetFullFilePath(); + void SetAttrib(); + public: HRESULT SendMessageError(const char *message, const FString &path); HRESULT SendMessageError_with_LastError(const char *message, const FString &path); diff --git a/CPP/7zip/UI/Common/DirItem.h b/CPP/7zip/UI/Common/DirItem.h index 55b2872c0..e5f578dd0 100644 --- a/CPP/7zip/UI/Common/DirItem.h +++ b/CPP/7zip/UI/Common/DirItem.h @@ -118,7 +118,9 @@ struct CDirItem UInt32 GetPosixAttrib() const { UInt32 v = IsDir() ? MY_LIN_S_IFDIR : MY_LIN_S_IFREG; - v |= (IsReadOnly() ? 0555 : 0777); + /* 21.06: as WSL we allow write permissions (0222) for directories even for (FILE_ATTRIBUTE_READONLY). + So extracting at Linux will be allowed to write files inside (0777) directories. */ + v |= ((IsReadOnly() && !IsDir()) ? 0555 : 0777); return v; } #endif diff --git a/CPP/7zip/UI/Common/ZipRegistry.cpp b/CPP/7zip/UI/Common/ZipRegistry.cpp index 558a159ca..ab4871fb3 100644 --- a/CPP/7zip/UI/Common/ZipRegistry.cpp +++ b/CPP/7zip/UI/Common/ZipRegistry.cpp @@ -2,7 +2,10 @@ #include "StdAfx.h" +#include "../../../../C/CpuArch.h" + #include "../../../Common/IntToString.h" +#include "../../../Common/StringToInt.h" #include "../../../Windows/FileDir.h" #include "../../../Windows/Registry.h" @@ -195,6 +198,13 @@ static void GetRegUInt32(CKey &key, LPCTSTR name, UInt32 &value) value = (UInt32)(Int32)-1; } +static LPCWSTR const kMemUse = L"MemUse" + #if defined(MY_CPU_SIZEOF_POINTER) && (MY_CPU_SIZEOF_POINTER == 4) + L"32"; + #else + L"64"; + #endif + void CInfo::Save() const { CS_LOCK @@ -234,6 +244,7 @@ void CInfo::Save() const SetRegString(fk, kMethod, fo.Method); SetRegString(fk, kOptions, fo.Options); SetRegString(fk, kEncryptionMethod, fo.EncryptionMethod); + SetRegString(fk, kMemUse, fo.MemUse); } } } @@ -274,9 +285,10 @@ void CInfo::Load() fo.FormatID = formatIDs[i]; if (fk.Open(optionsKey, fo.FormatID, KEY_READ) == ERROR_SUCCESS) { - GetRegString(fk, kOptions, fo.Options); GetRegString(fk, kMethod, fo.Method); + GetRegString(fk, kOptions, fo.Options); GetRegString(fk, kEncryptionMethod, fo.EncryptionMethod); + GetRegString(fk, kMemUse, fo.MemUse); GetRegUInt32(fk, kLevel, fo.Level); GetRegUInt32(fk, kDictionary, fo.Dictionary); @@ -298,6 +310,116 @@ void CInfo::Load() key.GetValue_IfOk(kEncryptHeaders, EncryptHeaders); } + +static bool ParseMemUse(const wchar_t *s, CMemUse &mu) +{ + mu.Clear(); + + bool percentMode = false; + { + const wchar_t c = *s; + if (MyCharLower_Ascii(c) == 'p') + { + percentMode = true; + s++; + } + } + const wchar_t *end; + UInt64 number = ConvertStringToUInt64(s, &end); + if (end == s) + return false; + + wchar_t c = *end; + + if (percentMode) + { + if (c != 0) + return false; + mu.IsPercent = true; + mu.Val = number; + return true; + } + + if (c == 0) + { + mu.Val = number; + return true; + } + + c = MyCharLower_Ascii(c); + + const wchar_t c1 = end[1]; + + if (c == '%') + { + if (c1 != 0) + return false; + mu.IsPercent = true; + mu.Val = number; + return true; + } + + if (c == 'b') + { + if (c1 != 0) + return false; + mu.Val = number; + return true; + } + + if (c1 != 0) + if (MyCharLower_Ascii(c1) != 'b' || end[2] != 0) + return false; + + unsigned numBits; + switch (c) + { + case 'k': numBits = 10; break; + case 'm': numBits = 20; break; + case 'g': numBits = 30; break; + case 't': numBits = 40; break; + default: return false; + } + if (number >= ((UInt64)1 << (64 - numBits))) + return false; + mu.Val = number << numBits; + return true; +} + + +void CMemUse::Parse(const UString &s) +{ + IsDefined = ParseMemUse(s, *this); +} + +/* +void MemLimit_Save(const UString &s) +{ + CS_LOCK + CKey key; + CreateMainKey(key, kKeyName); + SetRegString(key, kMemUse, s); +} + +bool MemLimit_Load(NCompression::CMemUse &mu) +{ + mu.Clear(); + UString a; + { + CS_LOCK + CKey key; + if (OpenMainKey(key, kKeyName) != ERROR_SUCCESS) + return false; + if (key.QueryValue(kMemUse, a) != ERROR_SUCCESS) + return false; + } + if (a.IsEmpty()) + return false; + mu.Parse(a); + return mu.IsDefined; +} +*/ + } static LPCTSTR const kOptionsInfoKeyName = TEXT("Options"); diff --git a/CPP/7zip/UI/Common/ZipRegistry.h b/CPP/7zip/UI/Common/ZipRegistry.h index 76a98447d..3d2e4b98c 100644 --- a/CPP/7zip/UI/Common/ZipRegistry.h +++ b/CPP/7zip/UI/Common/ZipRegistry.h @@ -6,6 +6,8 @@ #include "../../../Common/MyTypes.h" #include "../../../Common/MyString.h" +#include "../../Common/MethodProps.h" + #include "ExtractMode.h" namespace NExtract @@ -35,6 +37,36 @@ namespace NExtract namespace NCompression { + struct CMemUse + { + // UString Str; + bool IsDefined; + bool IsPercent; + UInt64 Val; + + CMemUse(): + IsDefined(false), + IsPercent(false), + Val(0) + {} + + void Clear() + { + // Str.Empty(); + IsDefined = false; + IsPercent = false; + Val = 0; + } + + UInt64 GetBytes(UInt64 ramSize) const + { + if (!IsPercent) + return Val; + return Calc_From_Val_Percents(ramSize, Val); + } + void Parse(const UString &s); + }; + struct CFormatOptions { UInt32 Level; @@ -47,6 +79,7 @@ namespace NCompression UString Method; UString Options; UString EncryptionMethod; + UString MemUse; void Reset_BlockLogSize() { diff --git a/CPP/7zip/UI/FileManager/App.h b/CPP/7zip/UI/FileManager/App.h index 21b160dc9..3c3c5ef2f 100644 --- a/CPP/7zip/UI/FileManager/App.h +++ b/CPP/7zip/UI/FileManager/App.h @@ -18,8 +18,9 @@ const unsigned kNumPanelsMax = 2; extern bool g_IsSmallScreen; -const int kMenuCmdID_Plugin_Start = 1000; // must be large them context menu IDs -const int kMenuCmdID_Toolbar_Start = 1500; +// must be larger than context menu IDs +const int kMenuCmdID_Toolbar_Start = 1070; +const int kMenuCmdID_Plugin_Start = 1100; enum { diff --git a/CPP/7zip/UI/FileManager/PanelMenu.cpp b/CPP/7zip/UI/FileManager/PanelMenu.cpp index 99a76cfaf..1a09a8f65 100644 --- a/CPP/7zip/UI/FileManager/PanelMenu.cpp +++ b/CPP/7zip/UI/FileManager/PanelMenu.cpp @@ -30,7 +30,7 @@ LONG g_DllRefCount; LONG g_DllRefCount = 0; static const UINT kSevenZipStartMenuID = kMenuCmdID_Plugin_Start; -static const UINT kSystemStartMenuID = kMenuCmdID_Plugin_Start + 100; +static const UINT kSystemStartMenuID = kMenuCmdID_Plugin_Start + 400; void CPanel::InvokeSystemCommand(const char *command) { @@ -993,11 +993,19 @@ bool CPanel::InvokePluginCommand(unsigned id, IContextMenu *sevenZipContextMenu, IContextMenu *systemContextMenu) { UInt32 offset; - bool isSystemMenu = (id >= kSystemStartMenuID); + const bool isSystemMenu = (id >= kSystemStartMenuID); if (isSystemMenu) + { + if (!systemContextMenu) + return false; offset = id - kSystemStartMenuID; + } else + { + if (!sevenZipContextMenu) + return false; offset = id - kSevenZipStartMenuID; + } #ifdef use_CMINVOKECOMMANDINFOEX CMINVOKECOMMANDINFOEX diff --git a/CPP/7zip/UI/FileManager/SettingsPage.cpp b/CPP/7zip/UI/FileManager/SettingsPage.cpp index bdd62f71b..286872174 100644 --- a/CPP/7zip/UI/FileManager/SettingsPage.cpp +++ b/CPP/7zip/UI/FileManager/SettingsPage.cpp @@ -2,17 +2,20 @@ #include "StdAfx.h" -#include "../../../Common/StringConvert.h" +// #include "../../../Common/IntToString.h" +// #include "../../../Common/StringConvert.h" #ifndef UNDER_CE #include "../../../Windows/MemoryLock.h" +// #include "../../../Windows/System.h" #endif +// #include "../Common/ZipRegistry.h" + #include "HelpUtils.h" #include "LangUtils.h" #include "RegistryUtils.h" #include "SettingsPage.h" - #include "SettingsPageRes.h" using namespace NWindows; @@ -27,16 +30,87 @@ static const UInt32 kLangIDs[] = IDX_SETTINGS_SINGLE_CLICK, IDX_SETTINGS_ALTERNATIVE_SELECTION, IDX_SETTINGS_LARGE_PAGES + // , IDT_COMPRESS_MEMORY }; #define kSettingsTopic "FM/options.htm#settings" extern bool IsLargePageSupported(); +/* +static void AddMemSize(UString &res, UInt64 size, bool needRound = false) +{ + char c; + unsigned moveBits = 0; + if (needRound) + { + UInt64 rn = 0; + if (size >= (1 << 31)) + rn = (1 << 28) - 1; + UInt32 kRound = (1 << 20) - 1; + if (rn < kRound) + rn = kRound; + size += rn; + size &= ~rn; + } + if (size >= ((UInt64)1 << 31) && (size & 0x3FFFFFFF) == 0) + { moveBits = 30; c = 'G'; } + else + { moveBits = 20; c = 'M'; } + res.Add_UInt64(size >> moveBits); + res.Add_Space(); + if (moveBits != 0) + res += c; + res += 'B'; +} + + +int CSettingsPage::AddMemComboItem(UInt64 size, UInt64 percents, bool isDefault) +{ + UString sUser; + UString sRegistry; + if (size == 0) + { + UString s; + s.Add_UInt64(percents); + s += '%'; + if (isDefault) + sUser = "* "; + else + sRegistry = s; + sUser += s; + } + else + { + AddMemSize(sUser, size); + sRegistry = sUser; + for (;;) + { + int pos = sRegistry.Find(L' '); + if (pos < 0) + break; + sRegistry.Delete(pos); + } + if (!sRegistry.IsEmpty()) + if (sRegistry.Back() == 'B') + sRegistry.DeleteBack(); + } + const int index = (int)_memCombo.AddString(sUser); + _memCombo.SetItemData(index, _memLimitStrings.Size()); + _memLimitStrings.Add(sRegistry); + return index; +} +*/ + bool CSettingsPage::OnInit() { _wasChanged = false; _largePages_wasChanged = false; + /* + _wasChanged_MemLimit = false; + _memLimitStrings.Clear(); + _memCombo.Attach(GetItem(IDC_SETTINGS_MEM)); + */ LangSetDlgItems(*this, kLangIDs, ARRAY_SIZE(kLangIDs)); @@ -57,6 +131,55 @@ bool CSettingsPage::OnInit() CheckButton(IDX_SETTINGS_LARGE_PAGES, ReadLockMemoryEnable()); else EnableItem(IDX_SETTINGS_LARGE_PAGES, false); + + + /* + NCompression::CMemUse mu; + bool needSetCur = NCompression::MemLimit_Load(mu); + UInt64 curMemLimit; + { + AddMemComboItem(0, 90, true); + _memCombo.SetCurSel(0); + } + if (mu.IsPercent) + { + const int index = AddMemComboItem(0, mu.Val); + _memCombo.SetCurSel(index); + needSetCur = false; + } + { + _ramSize = (UInt64)(sizeof(size_t)) << 29; + _ramSize_Defined = NSystem::GetRamSize(_ramSize); + UString s; + if (_ramSize_Defined) + { + s += "/ "; + AddMemSize(s, _ramSize, true); + } + SetItemText(IDT_SETTINGS_MEM_RAM, s); + + curMemLimit = mu.GetBytes(_ramSize); + + // size = 100 << 20; // for debug only; + for (unsigned i = (27) * 2;; i++) + { + UInt64 size = (UInt64)(2 + (i & 1)) << (i / 2); + if (i > (20 + sizeof(size_t) * 3 * 1 - 1) * 2) + size = (UInt64)(Int64)-1; + if (needSetCur && (size >= curMemLimit)) + { + const int index = AddMemComboItem(curMemLimit); + _memCombo.SetCurSel(index); + needSetCur = false; + if (size == curMemLimit) + continue; + } + if (size == (UInt64)(Int64)-1) + break; + AddMemComboItem(size); + } + } + */ // EnableSubItems(); @@ -70,6 +193,14 @@ void CSettingsPage::EnableSubItems() } */ +/* +static void AddSize_MB(UString &s, UInt64 size) +{ + s.Add_UInt64((size + (1 << 20) - 1) >> 20); + s += " MB"; +} +*/ + LONG CSettingsPage::OnApply() { if (_wasChanged) @@ -86,10 +217,9 @@ LONG CSettingsPage::OnApply() st.ShowSystemMenu = IsButtonCheckedBool(IDX_SETTINGS_SHOW_SYSTEM_MENU); st.Save(); - _wasChanged = false; } - + #ifndef UNDER_CE if (_largePages_wasChanged) { @@ -102,7 +232,66 @@ LONG CSettingsPage::OnApply() _largePages_wasChanged = false; } #endif - + + /* + if (_wasChanged_MemLimit) + { + const unsigned index = (int)_memCombo.GetItemData_of_CurSel(); + const UString str = _memLimitStrings[index]; + + bool needSave = true; + + NCompression::CMemUse mu; + + if (_ramSize_Defined) + mu.Parse(str); + if (mu.IsDefined) + { + const UInt64 usage64 = mu.GetBytes(_ramSize); + if (_ramSize <= usage64) + { + UString s2 = LangString(IDT_COMPRESS_MEMORY); + if (s2.IsEmpty()) + GetItemText(IDT_COMPRESS_MEMORY, s2); + UString s; + + s += "The selected value is not safe for system performance."; + s.Add_LF(); + s += "The memory consumption for compression operation will exceed RAM size."; + s.Add_LF(); + s.Add_LF(); + AddSize_MB(s, usage64); + + if (!s2.IsEmpty()) + { + s += " : "; + s += s2; + } + + s.Add_LF(); + AddSize_MB(s, _ramSize); + s += " : RAM"; + + s.Add_LF(); + s.Add_LF(); + s += "Are you sure you want set that unsafe value for memory usage?"; + + int res = MessageBoxW(*this, s, L"7-Zip", MB_YESNOCANCEL | MB_ICONQUESTION); + if (res != IDYES) + needSave = false; + } + } + + if (needSave) + { + NCompression::MemLimit_Save(str); + _wasChanged_MemLimit = false; + } + else + return PSNRET_INVALID_NOCHANGEPAGE; + } + */ + return PSNRET_NOERROR; } @@ -111,6 +300,25 @@ void CSettingsPage::OnNotifyHelp() ShowHelpWindow(kSettingsTopic); } +/* +bool CSettingsPage::OnCommand(int code, int itemID, LPARAM param) +{ + if (code == CBN_SELCHANGE) + { + switch (itemID) + { + case IDC_SETTINGS_MEM: + { + _wasChanged_MemLimit = true; + Changed(); + break; + } + } + } + return CPropertyPage::OnCommand(code, itemID, param); +} +*/ + bool CSettingsPage::OnButtonClicked(int buttonID, HWND buttonHWND) { switch (buttonID) diff --git a/CPP/7zip/UI/FileManager/SettingsPage.h b/CPP/7zip/UI/FileManager/SettingsPage.h index 77cc67b94..f3f57a4b4 100644 --- a/CPP/7zip/UI/FileManager/SettingsPage.h +++ b/CPP/7zip/UI/FileManager/SettingsPage.h @@ -4,20 +4,30 @@ #define __SETTINGS_PAGE_H #include "../../../Windows/Control/PropertyPage.h" +#include "../../../Windows/Control/ComboBox.h" #include "../../../Windows/Control/Edit.h" class CSettingsPage: public NWindows::NControl::CPropertyPage { bool _wasChanged; - bool _largePages_wasChanged; + /* + bool _wasChanged_MemLimit; + NWindows::NControl::CComboBox _memCombo; + UStringVector _memLimitStrings; + UInt64 _ramSize; + UInt64 _ramSize_Defined; + + int AddMemComboItem(UInt64 size, UInt64 percents = 0, bool isDefault = false); + */ // void EnableSubItems(); + // bool OnCommand(int code, int itemID, LPARAM param); bool OnButtonClicked(int buttonID, HWND buttonHWND); -public: virtual bool OnInit(); virtual void OnNotifyHelp(); virtual LONG OnApply(); +public: }; #endif diff --git a/CPP/7zip/UI/FileManager/SettingsPage.rc b/CPP/7zip/UI/FileManager/SettingsPage.rc index c724fcb71..baab484af 100644 --- a/CPP/7zip/UI/FileManager/SettingsPage.rc +++ b/CPP/7zip/UI/FileManager/SettingsPage.rc @@ -2,7 +2,7 @@ #include "../../GuiCommon.rc" #define xc 240 -#define yc 120 +#define yc 250 IDD_SETTINGS MY_PAGE #include "SettingsPage2.rc" diff --git a/CPP/7zip/UI/FileManager/SettingsPage2.rc b/CPP/7zip/UI/FileManager/SettingsPage2.rc index 277f45d54..cf9074202 100644 --- a/CPP/7zip/UI/FileManager/SettingsPage2.rc +++ b/CPP/7zip/UI/FileManager/SettingsPage2.rc @@ -1,3 +1,5 @@ +// #define g1xs 60 + CAPTION "Settings" BEGIN CONTROL "Show "".."" item", IDX_SETTINGS_SHOW_DOTS, MY_CHECKBOX, m, 8, xc, 10 @@ -10,4 +12,8 @@ BEGIN CONTROL "Show system &menu", IDX_SETTINGS_SHOW_SYSTEM_MENU, MY_CHECKBOX, m, 100, xc, 10 CONTROL "Use &large memory pages", IDX_SETTINGS_LARGE_PAGES, MY_CHECKBOX, m, 122, xc, 10 + + // LTEXT "Memory usage for Compressing:", IDT_COMPRESS_MEMORY, m, 140, xc, 8 + // COMBOBOX IDC_SETTINGS_MEM, m , 152, g1xs, yc - 152, MY_COMBO + // LTEXT "/ RAM", IDT_SETTINGS_MEM_RAM, m + g1xs + m, 154, xc - g1xs - m, MY_TEXT_NOPREFIX END diff --git a/CPP/7zip/UI/FileManager/SettingsPageRes.h b/CPP/7zip/UI/FileManager/SettingsPageRes.h index 712045973..e990babcb 100644 --- a/CPP/7zip/UI/FileManager/SettingsPageRes.h +++ b/CPP/7zip/UI/FileManager/SettingsPageRes.h @@ -9,3 +9,9 @@ #define IDX_SETTINGS_SINGLE_CLICK 2506 #define IDX_SETTINGS_ALTERNATIVE_SELECTION 2507 #define IDX_SETTINGS_LARGE_PAGES 2508 + + +// #define IDT_SETTINGS_MEM 100 +// #define IDC_SETTINGS_MEM 101 +// #define IDT_SETTINGS_MEM_RAM 102 +// #define IDT_COMPRESS_MEMORY 4017 diff --git a/CPP/7zip/UI/FileManager/VerCtrl.cpp b/CPP/7zip/UI/FileManager/VerCtrl.cpp index 7e53d81f4..3eea39427 100644 --- a/CPP/7zip/UI/FileManager/VerCtrl.cpp +++ b/CPP/7zip/UI/FileManager/VerCtrl.cpp @@ -126,6 +126,18 @@ static void WriteFile(const FString &path, bool createAlways, const CFileDataInf } +static UInt64 FILETIME_to_UInt64(const FILETIME &ft) +{ + return ft.dwLowDateTime | ((UInt64)ft.dwHighDateTime << 32); +} + +static void UInt64_TO_FILETIME(UInt64 v, FILETIME &ft) +{ + ft.dwLowDateTime = (DWORD)v; + ft.dwHighDateTime = (DWORD)(v >> 32); +} + + void CApp::VerCtrl(unsigned id) { const CPanel &panel = GetFocusedPanel(); @@ -297,6 +309,55 @@ void CApp::VerCtrl(unsigned id) return; } } + + const UInt64 timeStampOriginal = FILETIME_to_UInt64(fdi.Info.ftLastWriteTime); + UInt64 timeStamp2 = 0; + if (fdi2.IsOpen) + timeStamp2 = FILETIME_to_UInt64(fdi2.Info.ftLastWriteTime); + + if (timeStampOriginal > timeStamp2) + { + const UInt64 k_Ntfs_prec = 10000000; + UInt64 timeStamp = timeStampOriginal; + const UInt32 k_precs[] = { 60 * 60, 60, 2, 1 }; + for (unsigned i = 0; i < ARRAY_SIZE(k_precs); i++) + { + timeStamp = timeStampOriginal; + const UInt64 prec = k_Ntfs_prec * k_precs[i]; + // timeStamp += prec - 1; // for rounding up + timeStamp /= prec; + timeStamp *= prec; + if (timeStamp > timeStamp2) + break; + } + + if (timeStamp != timeStampOriginal + && timeStamp > timeStamp2) + { + FILETIME mTime; + UInt64_TO_FILETIME(timeStamp, mTime); + // NDir::SetFileAttrib(path, 0); + { + NIO::COutFile outFile; + if (!outFile.Open(path, OPEN_EXISTING)) + { + panel.MessageBox_LastError(); + return; + // if (::GetLastError() != ERROR_SUCCESS) + // throw "open error"; + } + else + { + const UInt64 cTime = FILETIME_to_UInt64(fdi.Info.ftCreationTime); + if (cTime > timeStamp) + outFile.SetTime(&mTime, NULL, &mTime); + else + outFile.SetMTime(&mTime); + } + } + } + } + if (!SetFileAttrib(path, fdi.Info.dwFileAttributes | FILE_ATTRIBUTE_READONLY)) { panel.MessageBox_LastError(); diff --git a/CPP/7zip/UI/GUI/BenchmarkDialog.cpp b/CPP/7zip/UI/GUI/BenchmarkDialog.cpp index 41e0927df..44d250358 100644 --- a/CPP/7zip/UI/GUI/BenchmarkDialog.cpp +++ b/CPP/7zip/UI/GUI/BenchmarkDialog.cpp @@ -733,9 +733,7 @@ void CBenchmarkDialog::SetItemText_Number(int itemID, UInt64 val, LPCTSTR post) static void AddSize_MB(UString &s, UInt64 size) { - char temp[32]; - ConvertUInt64ToString((size + (1 << 20) - 1) >> 20, temp); - s += temp; + s.Add_UInt64((size + (1 << 20) - 1) >> 20); s += kMB; } @@ -1555,16 +1553,13 @@ HRESULT CFreqCallback::AddCpuFreq(unsigned numThreads, UInt64 freq, UInt64 usage s.Add_LF(); } s += " "; - char temp[64]; if (numThreads != 1) { - ConvertUInt64ToString(GetUsagePercents(usage), temp); - s += temp; + s.Add_UInt64(GetUsagePercents(usage)); s += '%'; s.Add_Space(); } - ConvertUInt64ToString(GetMips(freq), temp); - s += temp; + s.Add_UInt64(GetMips(freq)); // BenchmarkDialog->Sync.sd.NeedPrint_Freq = true; res = sync.Exit ? E_ABORT : S_OK; } diff --git a/CPP/7zip/UI/GUI/CompressDialog.cpp b/CPP/7zip/UI/GUI/CompressDialog.cpp index 510d1ec31..0ede82920 100644 --- a/CPP/7zip/UI/GUI/CompressDialog.cpp +++ b/CPP/7zip/UI/GUI/CompressDialog.cpp @@ -11,6 +11,8 @@ #include "../../../Windows/FileName.h" #include "../../../Windows/System.h" +#include "../../Common/MethodProps.h" + #include "../FileManager/BrowseDialog.h" #include "../FileManager/FormatUtils.h" #include "../FileManager/HelpUtils.h" @@ -192,19 +194,30 @@ static const EMethodID g_HashMethods[] = // , kCrc64 }; +static const UInt32 kFF_Filter = 1 << 0; +static const UInt32 kFF_Solid = 1 << 1; +static const UInt32 kFF_MultiThread = 1 << 2; +static const UInt32 kFF_Encrypt = 1 << 3; +static const UInt32 kFF_EncryptFileNames = 1 << 4; +static const UInt32 kFF_MemUse = 1 << 5; +static const UInt32 kFF_SFX = 1 << 6; + struct CFormatInfo { LPCSTR Name; UInt32 LevelsMask; unsigned NumMethods; const EMethodID *MethodIDs; - bool Filter; - bool Solid; - bool MultiThread; - bool SFX; - - bool Encrypt; - bool EncryptFileNames; + + UInt32 Flags; + + bool Filter_() const { return (Flags & kFF_Filter) != 0; } + bool Solid_() const { return (Flags & kFF_Solid) != 0; } + bool MultiThread_() const { return (Flags & kFF_MultiThread) != 0; } + bool Encrypt_() const { return (Flags & kFF_Encrypt) != 0; } + bool EncryptFileNames_() const { return (Flags & kFF_EncryptFileNames) != 0; } + bool MemUse_() const { return (Flags & kFF_MemUse) != 0; } + bool SFX_() const { return (Flags & kFF_SFX) != 0; } }; #define METHODS_PAIR(x) ARRAY_SIZE(x), x @@ -216,62 +229,63 @@ static const CFormatInfo g_Formats[] = // (1 << 0) | (1 << 1) | (1 << 3) | (1 << 5) | (1 << 7) | (1 << 9), ((UInt32)1 << 10) - 1, // (UInt32)(Int32)-1, - 0, 0, - false, false, true, false, false, false + 0, NULL, + kFF_MultiThread | kFF_MemUse }, { k7zFormat, (1 << 0) | (1 << 1) | (1 << 3) | (1 << 5) | (1 << 7) | (1 << 9), METHODS_PAIR(g_7zMethods), - true, true, true, true, true, true + kFF_Filter | kFF_Solid | kFF_MultiThread | kFF_Encrypt | + kFF_EncryptFileNames | kFF_MemUse | kFF_SFX }, { "Zip", (1 << 0) | (1 << 1) | (1 << 3) | (1 << 5) | (1 << 7) | (1 << 9), METHODS_PAIR(g_ZipMethods), - false, false, true, false, true, false + kFF_MultiThread | kFF_Encrypt | kFF_MemUse }, { "GZip", (1 << 1) | (1 << 5) | (1 << 7) | (1 << 9), METHODS_PAIR(g_GZipMethods), - false, false, false, false, false, false + kFF_MemUse }, { "BZip2", (1 << 1) | (1 << 3) | (1 << 5) | (1 << 7) | (1 << 9), METHODS_PAIR(g_BZip2Methods), - false, false, true, false, false, false + kFF_MultiThread | kFF_MemUse }, { "xz", (1 << 1) | (1 << 3) | (1 << 5) | (1 << 7) | (1 << 9), METHODS_PAIR(g_XzMethods), - false, true, true, false, false, false + kFF_Solid | kFF_MultiThread | kFF_MemUse }, { "Swfc", (1 << 1) | (1 << 3) | (1 << 5) | (1 << 7) | (1 << 9), METHODS_PAIR(g_SwfcMethods), - false, false, true, false, false, false + 0 }, { "Tar", (1 << 0), - 0, 0, - false, false, false, false, false, false + 0, NULL, + 0 }, { "wim", (1 << 0), - 0, 0, - false, false, false, false, false, false + 0, NULL, + 0 }, { "Hash", (0 << 0), METHODS_PAIR(g_HashMethods), - false, false, false, false, false, false + 0 } }; @@ -372,14 +386,12 @@ bool CCompressDialog::OnInit() { UInt64 size = (UInt64)(sizeof(size_t)) << 29; _ramSize_Defined = NSystem::GetRamSize(size); - // size = 100 << 20; // for debug only; + // size = (UInt64)3 << 62; // for debug only; _ramSize = size; const UInt64 kMinUseSize = (1 << 26); if (size < kMinUseSize) size = kMinUseSize; - _ramUsage_Limit = size / 32 * 30; // it's relaxed limit for user defined settings - unsigned bits = sizeof(size_t) * 8; if (bits == 32) { @@ -388,7 +400,10 @@ bool CCompressDialog::OnInit() size = limit2; } - _ramUsage_Auto = size / 32 * 28; // it's same as in auto usage limit in handlers + _ramSize_Reduced = size; + + // 80% - is auto usage limit in handlers + _ramUsage_Auto = Calc_From_Val_Percents(size, 80); } _password1Control.Attach(GetItem(IDE_COMPRESS_PASSWORD1)); @@ -406,6 +421,7 @@ bool CCompressDialog::OnInit() m_Order.Attach(GetItem(IDC_COMPRESS_ORDER)); m_Solid.Attach(GetItem(IDC_COMPRESS_SOLID)); m_NumThreads.Attach(GetItem(IDC_COMPRESS_THREADS)); + m_MemUse.Attach(GetItem(IDC_COMPRESS_MEM_USE)); m_UpdateMode.Attach(GetItem(IDC_COMPRESS_UPDATE_MODE)); m_PathMode.Attach(GetItem(IDC_COMPRESS_PATH_MODE)); @@ -543,7 +559,7 @@ bool CCompressDialog::OnButtonClicked(int buttonID, HWND buttonHWND) void CCompressDialog::CheckSFXControlsEnable() { const CFormatInfo &fi = g_Formats[GetStaticFormatIndex()]; - bool enable = fi.SFX; + bool enable = fi.SFX_(); if (enable) { const int methodID = GetMethodID(); @@ -578,11 +594,12 @@ void CCompressDialog::FormatChanged() SetLevel(); SetSolidBlockSize(); SetParams(); + SetMemUseCombo(); SetNumThreads(); const CFormatInfo &fi = g_Formats[GetStaticFormatIndex()]; - Info.SolidIsSpecified = fi.Solid; - Info.EncryptHeadersIsAllowed = fi.EncryptFileNames; + Info.SolidIsSpecified = fi.Solid_(); + Info.EncryptHeadersIsAllowed = fi.EncryptFileNames_(); /* const bool multiThreadEnable = fi.MultiThread; @@ -613,19 +630,20 @@ void CCompressDialog::FormatChanged() } // CheckVolumeEnable(); - EnableItem(IDG_COMPRESS_ENCRYPTION, fi.Encrypt); + const bool encrypt = fi.Encrypt_(); + EnableItem(IDG_COMPRESS_ENCRYPTION, encrypt); - EnableItem(IDT_PASSWORD_ENTER, fi.Encrypt); - EnableItem(IDT_PASSWORD_REENTER, fi.Encrypt); - EnableItem(IDE_COMPRESS_PASSWORD1, fi.Encrypt); - EnableItem(IDE_COMPRESS_PASSWORD2, fi.Encrypt); - EnableItem(IDX_PASSWORD_SHOW, fi.Encrypt); + EnableItem(IDT_PASSWORD_ENTER, encrypt); + EnableItem(IDT_PASSWORD_REENTER, encrypt); + EnableItem(IDE_COMPRESS_PASSWORD1, encrypt); + EnableItem(IDE_COMPRESS_PASSWORD2, encrypt); + EnableItem(IDX_PASSWORD_SHOW, encrypt); - EnableItem(IDT_COMPRESS_ENCRYPTION_METHOD, fi.Encrypt); - EnableItem(IDC_COMPRESS_ENCRYPTION_METHOD, fi.Encrypt); - EnableItem(IDX_COMPRESS_ENCRYPT_FILE_NAMES, fi.EncryptFileNames); + EnableItem(IDT_COMPRESS_ENCRYPTION_METHOD, encrypt); + EnableItem(IDC_COMPRESS_ENCRYPTION_METHOD, encrypt); + EnableItem(IDX_COMPRESS_ENCRYPT_FILE_NAMES, fi.EncryptFileNames_()); - ShowItem_Bool(IDX_COMPRESS_ENCRYPT_FILE_NAMES, fi.EncryptFileNames); + ShowItem_Bool(IDX_COMPRESS_ENCRYPT_FILE_NAMES, fi.EncryptFileNames_()); SetEncryptionMethod(); SetMemoryUsage(); @@ -767,9 +785,10 @@ static bool IsAsciiString(const UString &s) static void AddSize_MB(UString &s, UInt64 size) { - char temp[32]; - ConvertUInt64ToString((size + (1 << 20) - 1) >> 20, temp); - s += temp; + const UInt64 v2 = size + ((UInt32)1 << 20) - 1; + if (size <= v2) + size = v2; + s.Add_UInt64(size >> 20); s += " MB"; } @@ -793,7 +812,7 @@ void SetErrorMessage_MemUsage(UString &s, UInt64 reqSize, UInt64 ramSize, UInt64 AddSize_MB(s, ramSize); s += " : RAM"; - if (ramLimit != 0) + // if (ramLimit != 0) { s.Add_LF(); AddSize_MB(s, ramLimit); @@ -841,15 +860,18 @@ void CCompressDialog::OnOK() UInt64 decompressMem; const UInt64 memUsage = GetMemoryUsage_DecompMem(decompressMem); if (memUsage != (UInt64)(Int64)-1) - if (_ramSize_Defined && memUsage > _ramUsage_Limit) { - UString s; - UString s2 = LangString(IDT_COMPRESS_MEMORY); - if (s2.IsEmpty()) - GetItemText(IDT_COMPRESS_MEMORY, s2); - SetErrorMessage_MemUsage(s, memUsage, _ramSize, _ramUsage_Limit, s2); - MessageBoxError(s); - return; + const UInt64 limit = Get_MemUse_Bytes(); + if (memUsage > limit) + { + UString s; + UString s2 = LangString(IDT_COMPRESS_MEMORY); + if (s2.IsEmpty()) + GetItemText(IDT_COMPRESS_MEMORY, s2); + SetErrorMessage_MemUsage(s, memUsage, _ramSize, limit, s2); + MessageBoxError(s); + return; + } } } @@ -876,6 +898,18 @@ void CCompressDialog::OnOK() Info.OrderMode = GetOrderMode(); Info.NumThreads = GetNumThreadsSpec(); + Info.MemUsage.Clear(); + { + const UString mus = Get_MemUse_Spec(); + if (!mus.IsEmpty()) + { + NCompression::CMemUse mu; + mu.Parse(mus); + if (mu.IsDefined) + Info.MemUsage = mu; + } + } + { // Info.SolidIsSpecified = g_Formats[GetStaticFormatIndex()].Solid; const UInt32 solidLogSize = GetBlockSizeSpec(); @@ -1061,6 +1095,18 @@ bool CCompressDialog::OnCommand(int code, int itemID, LPARAM lParam) SetMemoryUsage(); return true; } + + case IDC_COMPRESS_MEM_USE: + { + /* we want to change the reported threads for Auto line + and keep selected NumThreads option + So we save selected NumThreads option in memory */ + SaveOptionsInMem(); + + SetNumThreads(); // we want to change the reported threads for Auto line only + SetMemoryUsage(); + return true; + } } } return CModalDialog::OnCommand(code, itemID, lParam); @@ -1435,22 +1481,19 @@ static const size_t k_Auto_Dict = (size_t)0 - 1; int CCompressDialog::AddDict2(size_t sizeReal, size_t sizeShow) { - Byte c = 0; + char c = 0; unsigned moveBits = 0; if ((sizeShow & 0xFFFFF) == 0) { moveBits = 20; c = 'M'; } else if ((sizeShow & 0x3FF) == 0) { moveBits = 10; c = 'K'; } - char s[32]; - ConvertUInt64ToString(sizeShow >> moveBits, s); - unsigned pos = MyStringLen(s); - s[pos++] = ' '; + AString s; + s.Add_UInt64(sizeShow >> moveBits); + s.Add_Space(); if (moveBits != 0) - s[pos++] = c; - s[pos++] = 'B'; - s[pos++] = 0; - AString s2 (s); + s += c; + s += 'B'; if (sizeReal == k_Auto_Dict) - Modify_Auto(s2); - const int index = (int)ComboBox_AddStringAscii(m_Dictionary, s2); + Modify_Auto(s); + const int index = (int)ComboBox_AddStringAscii(m_Dictionary, s); m_Dictionary.SetItemData(index, sizeReal); return index; } @@ -1831,22 +1874,18 @@ static UInt64 Get_Lzma2_ChunkSize(UInt64 dict) } -static void Add_Size(AString &s2, UInt64 val) +static void Add_Size(AString &s, UInt64 val) { unsigned moveBits = 0; - Byte c = 0; + char c = 0; if ((val & 0x3FFFFFFF) == 0) { moveBits = 30; c = 'G'; } else if ((val & 0xFFFFF) == 0) { moveBits = 20; c = 'M'; } else if ((val & 0x3FF) == 0) { moveBits = 10; c = 'K'; } - char s[32]; - ConvertUInt64ToString(val >> moveBits, s); - unsigned pos = MyStringLen(s); - s[pos++] = ' '; + s.Add_UInt64(val >> moveBits); + s.Add_Space(); if (moveBits != 0) - s[pos++] = c; - s[pos++] = 'B'; - s[pos++] = 0; - s2 += s; + s += c; + s += 'B'; } @@ -1856,7 +1895,7 @@ void CCompressDialog::SetSolidBlockSize2() _auto_Solid = 1 << 20; const CFormatInfo &fi = g_Formats[GetStaticFormatIndex()]; - if (!fi.Solid) + if (!fi.Solid_()) return; const UInt32 level = GetLevel2(); @@ -1977,7 +2016,7 @@ void CCompressDialog::SetNumThreads2() m_NumThreads.ResetContent(); const CFormatInfo &fi = g_Formats[GetStaticFormatIndex()]; - if (!fi.MultiThread) + if (!fi.MultiThread_()) return; const UInt32 numHardwareThreads = NSystem::GetNumberOfProcessors(); @@ -2029,6 +2068,8 @@ void CCompressDialog::SetNumThreads2() if (autoThreads > numAlgoThreadsMax) autoThreads = numAlgoThreadsMax; + const UInt64 memUse_Limit = Get_MemUse_Bytes(); + if (autoThreads > 1 && _ramSize_Defined) { if (isZip) @@ -2038,7 +2079,7 @@ void CCompressDialog::SetNumThreads2() const UInt64 dict64 = GetDict2(); UInt64 decompressMemory; const UInt64 usage = GetMemoryUsage_Threads_Dict_DecompMem(autoThreads, dict64, decompressMemory); - if (usage <= _ramUsage_Auto) + if (usage <= memUse_Limit) break; } } @@ -2052,7 +2093,7 @@ void CCompressDialog::SetNumThreads2() autoThreads = numBlockThreads * numThreads1; UInt64 decompressMemory; const UInt64 usage = GetMemoryUsage_Threads_Dict_DecompMem(autoThreads, dict64, decompressMemory); - if (usage <= _ramUsage_Auto) + if (usage <= memUse_Limit) break; } autoThreads = numBlockThreads * numThreads1; @@ -2088,6 +2129,174 @@ void CCompressDialog::SetNumThreads2() } +static void AddMemSize(UString &res, UInt64 size) +{ + char c; + unsigned moveBits = 0; + if (size >= ((UInt64)1 << 31) && (size & 0x3FFFFFFF) == 0) + { moveBits = 30; c = 'G'; } + else // if (size >= ((UInt32)1 << 21) && (size & 0xFFFFF) == 0) + { moveBits = 20; c = 'M'; } + // else { moveBits = 10; c = 'K'; } + res.Add_UInt64(size >> moveBits); + res.Add_Space(); + if (moveBits != 0) + res += c; + res += 'B'; +} + + +int CCompressDialog::AddMemComboItem(UInt64 val, bool isPercent, bool isDefault) +{ + UString sUser; + UString sRegistry; + if (isPercent) + { + UString s; + s.Add_UInt64(val); + s += '%'; + if (isDefault) + sUser = "* "; + else + sRegistry = s; + sUser += s; + } + else + { + AddMemSize(sUser, val); + sRegistry = sUser; + for (;;) + { + int pos = sRegistry.Find(L' '); + if (pos < 0) + break; + sRegistry.Delete(pos); + } + if (!sRegistry.IsEmpty()) + if (sRegistry.Back() == 'B') + sRegistry.DeleteBack(); + } + const unsigned dataIndex = _memUse_Strings.Add(sRegistry); + const int index = (int)m_MemUse.AddString(sUser); + m_MemUse.SetItemData(index, dataIndex); + return index; +} + + + +void CCompressDialog::SetMemUseCombo() +{ + _memUse_Strings.Clear(); + m_MemUse.ResetContent(); + const CFormatInfo &fi = g_Formats[GetStaticFormatIndex()]; + + { + const bool enable = fi.MemUse_(); + ShowItem_Bool(IDT_COMPRESS_MEMORY, enable); + ShowItem_Bool(IDT_COMPRESS_MEMORY_VALUE, enable); + ShowItem_Bool(IDT_COMPRESS_MEMORY_DE, enable); + ShowItem_Bool(IDT_COMPRESS_MEMORY_DE_VALUE, enable); + ShowItem_Bool(IDC_COMPRESS_MEM_USE, enable); + EnableItem(IDC_COMPRESS_MEM_USE, enable); + if (!enable) + return; + } + + UInt64 curMem_Bytes = 0; + UInt64 curMem_Percents = 0; + bool needSetCur_Bytes = false; + bool needSetCur_Percents = false; + { + const NCompression::CFormatOptions &fo = Get_FormatOptions(); + if (!fo.MemUse.IsEmpty()) + { + NCompression::CMemUse mu; + mu.Parse(fo.MemUse); + if (mu.IsDefined) + { + if (mu.IsPercent) + { + curMem_Percents = mu.Val; + needSetCur_Percents = true; + } + else + { + curMem_Bytes = mu.GetBytes(_ramSize_Reduced); + needSetCur_Bytes = true; + } + } + } + } + + + // 80% - is auto usage limit in handlers + AddMemComboItem(80, true, true); + m_MemUse.SetCurSel(0); + + { + for (unsigned i = 10;; i += 10) + { + UInt64 size = i; + if (i > 100) + size = (UInt64)(Int64)-1; + if (needSetCur_Percents && size >= curMem_Percents) + { + const int index = AddMemComboItem(curMem_Percents, true); + m_MemUse.SetCurSel(index); + needSetCur_Percents = false; + if (size == curMem_Percents) + continue; + } + if (size == (UInt64)(Int64)-1) + break; + AddMemComboItem(size, true); + } + } + { + for (unsigned i = (27) * 2;; i++) + { + UInt64 size = (UInt64)(2 + (i & 1)) << (i / 2); + if (i > (20 + sizeof(size_t) * 3 - 1) * 2) + size = (UInt64)(Int64)-1; + if (needSetCur_Bytes && size >= curMem_Bytes) + { + const int index = AddMemComboItem(curMem_Bytes); + m_MemUse.SetCurSel(index); + needSetCur_Bytes = false; + if (size == curMem_Bytes) + continue; + } + if (size == (UInt64)(Int64)-1) + break; + AddMemComboItem(size); + } + } +} + + +UString CCompressDialog::Get_MemUse_Spec() +{ + if (m_MemUse.GetCount() < 1) + return UString(); + return _memUse_Strings[(unsigned)m_MemUse.GetItemData_of_CurSel()]; +} + + +UInt64 CCompressDialog::Get_MemUse_Bytes() +{ + const UString mus = Get_MemUse_Spec(); + NCompression::CMemUse mu; + if (!mus.IsEmpty()) + { + mu.Parse(mus); + if (mu.IsDefined) + return mu.GetBytes(_ramSize_Reduced); + } + return _ramUsage_Auto; // _ramSize_Reduced; // _ramSize;; +} + + + UInt64 CCompressDialog::GetMemoryUsage_DecompMem(UInt64 &decompressMemory) { return GetMemoryUsage_Dict_DecompMem(GetDict2(), decompressMemory); @@ -2119,7 +2328,7 @@ UInt64 CCompressDialog::GetMemoryUsage_Threads_Dict_DecompMem(UInt32 numThreads, UInt64 size = 0; const CFormatInfo &fi = g_Formats[GetStaticFormatIndex()]; - if (fi.Filter && level >= 9) + if (fi.Filter_() && level >= 9) size += (12 << 20) * 2 + (5 << 20); // UInt32 numThreads = GetNumThreads2(); @@ -2254,28 +2463,69 @@ UInt64 CCompressDialog::GetMemoryUsage_Threads_Dict_DecompMem(UInt32 numThreads, } -void CCompressDialog::PrintMemUsage(UINT res, UInt64 value) + +static void AddMemUsage(UString &s, UInt64 v) { - if (value == (UInt64)(Int64)-1) + const char *post; + if (v <= ((UInt64)16 << 30)) { - SetItemText(res, TEXT("?")); - return; + v = (v + (1 << 20) - 1) >> 20; + post = "MB"; } - TCHAR s[32]; - if (value <= ((UInt64)16 << 30)) + else if (v <= ((UInt64)64 << 40)) { - value = (value + (1 << 20) - 1) >> 20; - ConvertUInt64ToString(value, s); - lstrcat(s, TEXT(" MB")); + v = (v + (1 << 30) - 1) >> 30; + post = "GB"; } else { - value = (value + (1 << 30) - 1) >> 30; - ConvertUInt64ToString(value, s); - lstrcat(s, TEXT(" GB")); + const UInt64 v2 = v + ((UInt64)1 << 40) - 1; + if (v <= v2) + v = v2; + v >>= 40; + post = "TB"; + } + s.Add_UInt64(v); + s.Add_Space(); + s += post; +} + + +void CCompressDialog::PrintMemUsage(UINT res, UInt64 value) +{ + if (value == (UInt64)(Int64)-1) + { + SetItemText(res, TEXT("?")); + return; + } + UString s; + AddMemUsage(s, value); + if (res == IDT_COMPRESS_MEMORY_VALUE) + { + const UString mus = Get_MemUse_Spec(); + NCompression::CMemUse mu; + if (!mus.IsEmpty()) + mu.Parse(mus); + if (mu.IsDefined) + { + s += " / "; + AddMemUsage(s, mu.GetBytes(_ramSize_Reduced)); + } + else if (_ramSize_Defined) + { + s += " / "; + AddMemUsage(s, _ramUsage_Auto); + } + + if (_ramSize_Defined) + { + s += " / "; + AddMemUsage(s, _ramSize); + } } SetItemText(res, s); } + void CCompressDialog::SetMemoryUsage() { @@ -2334,6 +2584,7 @@ void CCompressDialog::SaveOptionsInMem() fo.EncryptionMethod = GetEncryptionMethodSpec(); fo.NumThreads = GetNumThreadsSpec(); fo.BlockLogSize = GetBlockSizeSpec(); + fo.MemUse = Get_MemUse_Spec(); } unsigned CCompressDialog::GetFormatIndex() diff --git a/CPP/7zip/UI/GUI/CompressDialog.h b/CPP/7zip/UI/GUI/CompressDialog.h index d8091b04a..171d1189d 100644 --- a/CPP/7zip/UI/GUI/CompressDialog.h +++ b/CPP/7zip/UI/GUI/CompressDialog.h @@ -38,6 +38,8 @@ namespace NCompressDialog UInt64 SolidBlockSize; UInt32 NumThreads; + NCompression::CMemUse MemUsage; + CRecordVector VolumeSizes; UInt32 Level; @@ -102,8 +104,11 @@ class CCompressDialog: public NWindows::NControl::CModalDialog NWindows::NControl::CComboBox m_Order; NWindows::NControl::CComboBox m_Solid; NWindows::NControl::CComboBox m_NumThreads; + NWindows::NControl::CComboBox m_MemUse; NWindows::NControl::CComboBox m_Volume; + UStringVector _memUse_Strings; + NWindows::NControl::CDialogChildControl m_Params; NWindows::NControl::CComboBox m_UpdateMode; @@ -128,10 +133,9 @@ class CCompressDialog: public NWindows::NControl::CModalDialog UString StartDirPrefix; bool _ramSize_Defined; - UInt64 _ramSize; + UInt64 _ramSize; // full RAM size avail + UInt64 _ramSize_Reduced; // full for 64-bit and reduced for 32-bit UInt64 _ramUsage_Auto; - UInt64 _ramUsage_Limit; - void CheckButton_TwoBools(UINT id, const CBoolPair &b1, const CBoolPair &b2); void GetButton_Bools(UINT id, CBoolPair &b1, CBoolPair &b2); @@ -254,6 +258,10 @@ class CCompressDialog: public NWindows::NControl::CModalDialog EnableMultiCombo(IDC_COMPRESS_THREADS); } + int AddMemComboItem(UInt64 val, bool isPercent = false, bool isDefault = false); + void SetMemUseCombo(); + UString Get_MemUse_Spec(); + UInt64 Get_MemUse_Bytes(); UInt64 GetMemoryUsage_Dict_DecompMem(UInt64 dict, UInt64 &decompressMemory); UInt64 GetMemoryUsage_Threads_Dict_DecompMem(UInt32 numThreads, UInt64 dict, UInt64 &decompressMemory); diff --git a/CPP/7zip/UI/GUI/CompressDialog.rc b/CPP/7zip/UI/GUI/CompressDialog.rc index d6ce5ac09..52c9546a4 100644 --- a/CPP/7zip/UI/GUI/CompressDialog.rc +++ b/CPP/7zip/UI/GUI/CompressDialog.rc @@ -29,7 +29,7 @@ #define g0xs (gSize - g1xs) #define g1x (m + g0xs) -#define g3xs 40 +#define g3xs 52 #define g2xs (gSize - g3xs) #define g3x (m + g2xs) @@ -82,14 +82,15 @@ BEGIN LTEXT "Number of CPU &threads:", IDT_COMPRESS_THREADS, m, 167, g0xs, 8 COMBOBOX IDC_COMPRESS_THREADS, g1x, 165, g1xs - 35, 140, MY_COMBO - RTEXT "", IDT_COMPRESS_HARDWARE_THREADS, g1x + g1xs - 35 + 10, 167, 25, 8 + RTEXT "", IDT_COMPRESS_HARDWARE_THREADS, g1x + g1xs - 35 + 10, 167, 25, MY_TEXT_NOPREFIX - LTEXT "Memory usage for Compressing:", IDT_COMPRESS_MEMORY, m, 190, g2xs, 8 - RTEXT "", IDT_COMPRESS_MEMORY_VALUE, g3x, 190, g3xs, 8 + LTEXT "Memory usage for Compressing:", IDT_COMPRESS_MEMORY, m, 184, g2xs, 8 + COMBOBOX IDC_COMPRESS_MEM_USE, g3x, 188, g3xs, 140, MY_COMBO + LTEXT "", IDT_COMPRESS_MEMORY_VALUE, m, 194, g2xs, MY_TEXT_NOPREFIX - LTEXT "Memory usage for Decompressing:", IDT_COMPRESS_MEMORY_DE, m, 206, g2xs, 8 - RTEXT "", IDT_COMPRESS_MEMORY_DE_VALUE, g3x, 206, g3xs, 8 + LTEXT "Memory usage for Decompressing:", IDT_COMPRESS_MEMORY_DE, m, 208, g2xs, 8 + RTEXT "", IDT_COMPRESS_MEMORY_DE_VALUE, g3x, 208, g3xs, MY_TEXT_NOPREFIX LTEXT "Split to &volumes, bytes:", IDT_SPLIT_TO_VOLUMES, m, 225, gSize, 8 diff --git a/CPP/7zip/UI/GUI/CompressDialogRes.h b/CPP/7zip/UI/GUI/CompressDialogRes.h index ff99fa94c..341b75334 100644 --- a/CPP/7zip/UI/GUI/CompressDialogRes.h +++ b/CPP/7zip/UI/GUI/CompressDialogRes.h @@ -20,6 +20,7 @@ #define IDG_COMPRESS_NTFS 115 #define IDC_COMPRESS_PATH_MODE 116 +#define IDC_COMPRESS_MEM_USE 117 #define IDE_COMPRESS_PASSWORD1 120 #define IDE_COMPRESS_PASSWORD2 121 diff --git a/CPP/7zip/UI/GUI/ExtractGUI.cpp b/CPP/7zip/UI/GUI/ExtractGUI.cpp index 59403ee90..a9191a8be 100644 --- a/CPP/7zip/UI/GUI/ExtractGUI.cpp +++ b/CPP/7zip/UI/GUI/ExtractGUI.cpp @@ -44,9 +44,7 @@ static void AddValuePair(UString &s, UINT resourceID, UInt64 value, bool addColo if (addColon) s += ':'; s.Add_Space(); - char sz[32]; - ConvertUInt64ToString(value, sz); - s += sz; + s.Add_UInt64(value); s.Add_LF(); } diff --git a/CPP/7zip/UI/GUI/HashGUI.cpp b/CPP/7zip/UI/GUI/HashGUI.cpp index 219135fb5..5782f7908 100644 --- a/CPP/7zip/UI/GUI/HashGUI.cpp +++ b/CPP/7zip/UI/GUI/HashGUI.cpp @@ -75,11 +75,10 @@ void AddSizeValue(UString &s, UInt64 value) if (value >= ((UInt64)10 << 30)) { value >>= 30; c = 'G'; } else if (value >= (10 << 20)) { value >>= 20; c = 'M'; } else { value >>= 10; c = 'K'; } - char sz[32]; - ConvertUInt64ToString(value, sz); + s += " ("; - s += sz; - s += " "; + s.Add_UInt64(value); + s.Add_Space(); s += (wchar_t)c; s += "iB)"; } diff --git a/CPP/7zip/UI/GUI/UpdateGUI.cpp b/CPP/7zip/UI/GUI/UpdateGUI.cpp index 1bdc9ffed..6fd1b60b4 100644 --- a/CPP/7zip/UI/GUI/UpdateGUI.cpp +++ b/CPP/7zip/UI/GUI/UpdateGUI.cpp @@ -61,7 +61,7 @@ HRESULT CThreadUpdating::ProcessVirt() return HRESULT_FROM_WIN32(ei.SystemError); } -static void AddProp(CObjectVector &properties, const char *name, const UString &value) +static void AddProp_UString(CObjectVector &properties, const char *name, const UString &value) { CProperty prop; prop.Name = name; @@ -69,16 +69,16 @@ static void AddProp(CObjectVector &properties, const char *name, cons properties.Add(prop); } -static void AddProp(CObjectVector &properties, const char *name, UInt32 value) +static void AddProp_UInt32(CObjectVector &properties, const char *name, UInt32 value) { - char tmp[32]; - ConvertUInt64ToString(value, tmp); - AddProp(properties, name, UString(tmp)); + UString s; + s.Add_UInt32(value); + AddProp_UString(properties, name, s); } -static void AddProp(CObjectVector &properties, const char *name, bool value) +static void AddProp_bool(CObjectVector &properties, const char *name, bool value) { - AddProp(properties, name, UString(value ? "on": "off")); + AddProp_UString(properties, name, UString(value ? "on": "off")); } static bool IsThereMethodOverride(bool is7z, const UString &propertiesString) @@ -126,16 +126,16 @@ static void ParseAndAddPropertires(CObjectVector &properties, } } -static UString GetNumInBytesString(UInt64 v) + +static void AddProp_Size(CObjectVector &properties, const char *name, const UInt64 size) { - char s[32]; - ConvertUInt64ToString(v, s); - size_t len = MyStringLen(s); - s[len++] = 'B'; - s[len] = '\0'; - return UString(s); + UString s; + s.Add_UInt64(size); + s += 'b'; + AddProp_UString(properties, name, s); } + static void SetOutProperties( CObjectVector &properties, bool is7z, @@ -150,21 +150,22 @@ static void SetOutProperties( UInt32 numThreads, const UString &encryptionMethod, bool encryptHeadersIsAllowed, bool encryptHeaders, + const NCompression::CMemUse &memUse, bool /* sfxMode */) { if (level != (UInt32)(Int32)-1) - AddProp(properties, "x", (UInt32)level); + AddProp_UInt32(properties, "x", (UInt32)level); if (setMethod) { if (!method.IsEmpty()) - AddProp(properties, is7z ? "0": "m", method); + AddProp_UString(properties, is7z ? "0": "m", method); if (dict64 != (UInt64)(Int64)-1) { AString name; if (is7z) name = "0"; name += (orderMode ? "mem" : "d"); - AddProp(properties, name, GetNumInBytesString(dict64)); + AddProp_Size(properties, name, dict64); } if (order != (UInt32)(Int32)-1) { @@ -172,21 +173,37 @@ static void SetOutProperties( if (is7z) name = "0"; name += (orderMode ? "o" : "fb"); - AddProp(properties, name, (UInt32)order); + AddProp_UInt32(properties, name, (UInt32)order); } } if (!encryptionMethod.IsEmpty()) - AddProp(properties, "em", encryptionMethod); + AddProp_UString(properties, "em", encryptionMethod); if (encryptHeadersIsAllowed) - AddProp(properties, "he", encryptHeaders); + AddProp_bool(properties, "he", encryptHeaders); if (solidIsSpecified) - AddProp(properties, "s", GetNumInBytesString(solidBlockSize)); + AddProp_Size(properties, "s", solidBlockSize); + if ( // multiThreadIsAllowed && numThreads != (UInt32)(Int32)-1) - AddProp(properties, "mt", numThreads); + AddProp_UInt32(properties, "mt", numThreads); + + if (memUse.IsDefined) + { + const char *kMemUse = "memuse"; + if (memUse.IsPercent) + { + UString s; + // s += 'p'; // for debug: alternate percent method + s.Add_UInt64(memUse.Val); + s += '%'; + AddProp_UString(properties, kMemUse, s); + } + else + AddProp_Size(properties, kMemUse, memUse.Val); + } } struct C_UpdateMode_ToAction_Pair @@ -408,6 +425,7 @@ static HRESULT ShowDialog( di.NumThreads, di.EncryptionMethod, di.EncryptHeadersIsAllowed, di.EncryptHeaders, + di.MemUsage, di.SFXMode); options.OpenShareForWrite = di.OpenShareForWrite; diff --git a/CPP/Common/MyString.cpp b/CPP/Common/MyString.cpp index cef70839e..1a7b7056a 100644 --- a/CPP/Common/MyString.cpp +++ b/CPP/Common/MyString.cpp @@ -661,6 +661,12 @@ void AString::Add_UInt32(UInt32 v) _len = (unsigned)(ConvertUInt32ToString(v, _chars + _len) - _chars); } +void UString::Add_UInt64(UInt64 v) +{ + Grow(20); + _len = (unsigned)(ConvertUInt64ToString(v, _chars + _len) - _chars); +} + void AString::SetFrom(const char *s, unsigned len) // no check { if (len > _limit) @@ -1304,6 +1310,12 @@ void UString::Add_UInt32(UInt32 v) _len = (unsigned)(ConvertUInt32ToString(v, _chars + _len) - _chars); } +void AString::Add_UInt64(UInt64 v) +{ + Grow(20); + _len = (unsigned)(ConvertUInt64ToString(v, _chars + _len) - _chars); +} + int UString::Find(const wchar_t *s, unsigned startIndex) const throw() { diff --git a/CPP/Common/MyString.h b/CPP/Common/MyString.h index 539cb2d46..3325cc542 100644 --- a/CPP/Common/MyString.h +++ b/CPP/Common/MyString.h @@ -367,6 +367,7 @@ class AString AString &operator+=(const AString &s); void Add_UInt32(UInt32 v); + void Add_UInt64(UInt64 v); void SetFrom(const char *s, unsigned len); // no check void SetFrom_CalcLen(const char *s, unsigned len); @@ -633,6 +634,7 @@ class UString UString &operator+=(const AString &s) { return operator+=(s.Ptr()); } void Add_UInt32(UInt32 v); + void Add_UInt64(UInt64 v); UString Mid(unsigned startIndex, unsigned count) const { return UString(count, _chars + startIndex); } UString Left(unsigned count) const { return UString(count, *this); } diff --git a/CPP/Windows/FileDir.cpp b/CPP/Windows/FileDir.cpp index 8193f61f5..8a33fc8ee 100644 --- a/CPP/Windows/FileDir.cpp +++ b/CPP/Windows/FileDir.cpp @@ -1054,6 +1054,7 @@ bool SetFileAttrib_PosixHighDetect(CFSTR path, DWORD attrib) TRACE_SetFileAttrib("bad lstat()"); return false; } + // TRACE_chmod("lstat", st.st_mode); } else { @@ -1066,6 +1067,7 @@ bool SetFileAttrib_PosixHighDetect(CFSTR path, DWORD attrib) if (attrib & FILE_ATTRIBUTE_UNIX_EXTENSION) { + TRACE_SetFileAttrib("attrib & FILE_ATTRIBUTE_UNIX_EXTENSION"); st.st_mode = attrib >> 16; if (S_ISDIR(st.st_mode)) { @@ -1077,12 +1079,15 @@ bool SetFileAttrib_PosixHighDetect(CFSTR path, DWORD attrib) } else if (S_ISLNK(st.st_mode)) { - // change it - SetLastError(ENOSYS); - return false; + /* for most systems: permissions for symlinks are fixed to rwxrwxrwx. + so we don't need chmod() for symlinks. */ + return true; + // SetLastError(ENOSYS); + // return false; } else { + TRACE_SetFileAttrib("Only Windows Attributes"); // Only Windows Attributes if (S_ISDIR(st.st_mode) || (attrib & FILE_ATTRIBUTE_READONLY) == 0) @@ -1090,10 +1095,23 @@ bool SetFileAttrib_PosixHighDetect(CFSTR path, DWORD attrib) st.st_mode &= ~(mode_t)(S_IWUSR | S_IWGRP | S_IWOTH); // octal: ~0222; // disable write permissions } - TRACE_chmod(path, (st.st_mode) & g_umask.mask); - int res = chmod(path, (st.st_mode) & g_umask.mask); - - // TRACE_SetFileAttrib("OK") + int res; + /* + if (S_ISLNK(st.st_mode)) + { + printf("\nfchmodat()\n"); + TRACE_chmod(path, (st.st_mode) & g_umask.mask); + // AT_SYMLINK_NOFOLLOW is not implemted still in Linux. + res = fchmodat(AT_FDCWD, path, (st.st_mode) & g_umask.mask, + S_ISLNK(st.st_mode) ? AT_SYMLINK_NOFOLLOW : 0); + } + else + */ + { + TRACE_chmod(path, (st.st_mode) & g_umask.mask); + res = chmod(path, (st.st_mode) & g_umask.mask); + } + // TRACE_SetFileAttrib("End") return (res == 0); } diff --git a/CPP/Windows/SystemInfo.cpp b/CPP/Windows/SystemInfo.cpp index 82145d9c7..d882a8ee4 100644 --- a/CPP/Windows/SystemInfo.cpp +++ b/CPP/Windows/SystemInfo.cpp @@ -25,7 +25,7 @@ /* the following patch for some debian systems. Is it OK to define AT_HWCAP and AT_HWCAP2 here with these constant numbers? */ - +/* #if defined(__FreeBSD_kernel__) && defined(__GLIBC__) #ifndef AT_HWCAP #define AT_HWCAP 16 @@ -34,7 +34,7 @@ #define AT_HWCAP2 26 #endif #endif - +*/ #ifdef MY_CPU_ARM_OR_ARM64 #include diff --git a/DOC/7zip.wxs b/DOC/7zip.wxs index f636287b5..6792d74e1 100644 --- a/DOC/7zip.wxs +++ b/DOC/7zip.wxs @@ -1,7 +1,7 @@ - + diff --git a/DOC/readme.txt b/DOC/readme.txt index c9896c89e..6c6d3146f 100644 --- a/DOC/readme.txt +++ b/DOC/readme.txt @@ -1,4 +1,4 @@ -7-Zip 21.04 Sources +7-Zip 21.05 Sources ------------------- 7-Zip is a file archiver for Windows. diff --git a/DOC/src-history.txt b/DOC/src-history.txt index 3e7c9dfc4..00004e9dc 100644 --- a/DOC/src-history.txt +++ b/DOC/src-history.txt @@ -1,6 +1,19 @@ HISTORY of the 7-Zip source code -------------------------------- +21.06 2021-11-24 +------------------------- +- Bug in LZMA encoder in file LzmaEnc.c was fixed: + LzmaEnc_MemEncode(), LzmaEncode() and LzmaCompress() could work incorrectly, + if size value for output buffer is smaller than size required for all compressed data. + LzmaEnc_Encode() could work incorrectly, + if callback ISeqOutStream::Write() doesn't write all compressed data. + NCompress::NLzma::CEncoder::Code() could work incorrectly, + if callback ISequentialOutStream::Write() returns error code. +- Bug in versions 21.00-21.05 was fixed: + 7-Zip didn't set attributes of directories during archive extracting. + + 21.04 beta 2021-11-02 ------------------------- - 7-Zip now reduces the number of working CPU threads for compression,