mirror of
https://github.com/ip7z/7zip.git
synced 2025-12-06 07:12:00 +01:00
Compare commits
9 commits
de687fa10d
...
14b9eb8dbc
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
14b9eb8dbc | ||
|
|
5e96a82794 | ||
|
|
e60fa1f578 | ||
|
|
b557f6f6e1 | ||
|
|
e807cf4acc | ||
|
|
7be55ef26c | ||
|
|
299982cc8d | ||
|
|
4f339c675c | ||
|
|
445b1e35e7 |
|
|
@ -1,7 +1,7 @@
|
||||||
#define MY_VER_MAJOR 25
|
#define MY_VER_MAJOR 25
|
||||||
#define MY_VER_MINOR 0
|
#define MY_VER_MINOR 1
|
||||||
#define MY_VER_BUILD 0
|
#define MY_VER_BUILD 0
|
||||||
#define MY_VERSION_NUMBERS "25.00"
|
#define MY_VERSION_NUMBERS "25.01"
|
||||||
#define MY_VERSION MY_VERSION_NUMBERS
|
#define MY_VERSION MY_VERSION_NUMBERS
|
||||||
|
|
||||||
#ifdef MY_CPU_NAME
|
#ifdef MY_CPU_NAME
|
||||||
|
|
@ -10,7 +10,7 @@
|
||||||
#define MY_VERSION_CPU MY_VERSION
|
#define MY_VERSION_CPU MY_VERSION
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#define MY_DATE "2025-07-05"
|
#define MY_DATE "2025-08-03"
|
||||||
#undef MY_COPYRIGHT
|
#undef MY_COPYRIGHT
|
||||||
#undef MY_VERSION_COPYRIGHT_DATE
|
#undef MY_VERSION_COPYRIGHT_DATE
|
||||||
#define MY_AUTHOR_NAME "Igor Pavlov"
|
#define MY_AUTHOR_NAME "Igor Pavlov"
|
||||||
|
|
|
||||||
|
|
@ -598,7 +598,7 @@ void MatchFinder_Init(void *_p)
|
||||||
|
|
||||||
#ifdef MY_CPU_X86_OR_AMD64
|
#ifdef MY_CPU_X86_OR_AMD64
|
||||||
#if defined(__clang__) && (__clang_major__ >= 4) \
|
#if defined(__clang__) && (__clang_major__ >= 4) \
|
||||||
|| defined(Z7_GCC_VERSION) && (Z7_GCC_VERSION >= 40701)
|
|| defined(Z7_GCC_VERSION) && (Z7_GCC_VERSION >= 40900)
|
||||||
// || defined(__INTEL_COMPILER) && (__INTEL_COMPILER >= 1900)
|
// || defined(__INTEL_COMPILER) && (__INTEL_COMPILER >= 1900)
|
||||||
|
|
||||||
#define USE_LZFIND_SATUR_SUB_128
|
#define USE_LZFIND_SATUR_SUB_128
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,12 @@
|
||||||
// Archive/ZipItem.cpp
|
// Archive/ZipItem.cpp
|
||||||
|
|
||||||
|
#ifndef _WIN32
|
||||||
|
#include <iconv.h>
|
||||||
|
#include <locale.h>
|
||||||
|
#include <cstdio>
|
||||||
|
#include <cstdlib>
|
||||||
|
#endif
|
||||||
|
|
||||||
#include "StdAfx.h"
|
#include "StdAfx.h"
|
||||||
|
|
||||||
#include "../../../../C/CpuArch.h"
|
#include "../../../../C/CpuArch.h"
|
||||||
|
|
@ -451,6 +458,184 @@ void CItem::GetUnicodeString(UString &res, const AString &s, bool isComment, boo
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifndef _WIN32
|
||||||
|
|
||||||
|
// Convert OEM char set to UTF-8 if needed
|
||||||
|
// Use system locale to select code page
|
||||||
|
|
||||||
|
// locale -> code page translation tables generated from Wine source code
|
||||||
|
|
||||||
|
const char *lcToOemTable[] = {
|
||||||
|
"af_ZA", "CP850", "ar_SA", "CP720", "ar_LB", "CP720", "ar_EG", "CP720",
|
||||||
|
"ar_DZ", "CP720", "ar_BH", "CP720", "ar_IQ", "CP720", "ar_JO", "CP720",
|
||||||
|
"ar_KW", "CP720", "ar_LY", "CP720", "ar_MA", "CP720", "ar_OM", "CP720",
|
||||||
|
"ar_QA", "CP720", "ar_SY", "CP720", "ar_TN", "CP720", "ar_AE", "CP720",
|
||||||
|
"ar_YE", "CP720", "ast_ES", "CP850", "az_AZ@cyrillic", "CP866", "az_AZ", "CP857",
|
||||||
|
"be_BY", "CP866", "bg_BG", "CP866", "br_FR", "CP850", "ca_ES", "CP850",
|
||||||
|
"zh_CN", "CP936", "zh_TW", "CP950", "kw_GB", "CP850", "cs_CZ", "CP852",
|
||||||
|
"cy_GB", "CP850", "da_DK", "CP850", "de_AT", "CP850", "de_LI", "CP850",
|
||||||
|
"de_LU", "CP850", "de_CH", "CP850", "de_DE", "CP850", "el_GR", "CP737",
|
||||||
|
"en_AU", "CP850", "en_CA", "CP850", "en_GB", "CP850", "en_IE", "CP850",
|
||||||
|
"en_JM", "CP850", "en_BZ", "CP850", "en_PH", "CP437", "en_ZA", "CP437",
|
||||||
|
"en_TT", "CP850", "en_US", "CP437", "en_ZW", "CP437", "en_NZ", "CP850",
|
||||||
|
"es_PA", "CP850", "es_BO", "CP850", "es_CR", "CP850", "es_DO", "CP850",
|
||||||
|
"es_SV", "CP850", "es_EC", "CP850", "es_GT", "CP850", "es_HN", "CP850",
|
||||||
|
"es_NI", "CP850", "es_CL", "CP850", "es_MX", "CP850", "es_ES", "CP850",
|
||||||
|
"es_CO", "CP850", "es_ES", "CP850", "es_PE", "CP850", "es_AR", "CP850",
|
||||||
|
"es_PR", "CP850", "es_VE", "CP850", "es_UY", "CP850", "es_PY", "CP850",
|
||||||
|
"et_EE", "CP775", "eu_ES", "CP850", "fa_IR", "CP720", "fi_FI", "CP850",
|
||||||
|
"fo_FO", "CP850", "fr_FR", "CP850", "fr_BE", "CP850", "fr_CA", "CP850",
|
||||||
|
"fr_LU", "CP850", "fr_MC", "CP850", "fr_CH", "CP850", "ga_IE", "CP437",
|
||||||
|
"gd_GB", "CP850", "gv_IM", "CP850", "gl_ES", "CP850", "he_IL", "CP862",
|
||||||
|
"hr_HR", "CP852", "hu_HU", "CP852", "id_ID", "CP850", "is_IS", "CP850",
|
||||||
|
"it_IT", "CP850", "it_CH", "CP850", "iv_IV", "CP437", "ja_JP", "CP932",
|
||||||
|
"kk_KZ", "CP866", "ko_KR", "CP949", "ky_KG", "CP866", "lt_LT", "CP775",
|
||||||
|
"lv_LV", "CP775", "mk_MK", "CP866", "mn_MN", "CP866", "ms_BN", "CP850",
|
||||||
|
"ms_MY", "CP850", "nl_BE", "CP850", "nl_NL", "CP850", "nl_SR", "CP850",
|
||||||
|
"nn_NO", "CP850", "nb_NO", "CP850", "pl_PL", "CP852", "pt_BR", "CP850",
|
||||||
|
"pt_PT", "CP850", "rm_CH", "CP850", "ro_RO", "CP852", "ru_RU", "CP866",
|
||||||
|
"sk_SK", "CP852", "sl_SI", "CP852", "sq_AL", "CP852", "sr_RS@latin", "CP852",
|
||||||
|
"sr_RS", "CP855", "sv_SE", "CP850", "sv_FI", "CP850", "sw_KE", "CP437",
|
||||||
|
"th_TH", "CP874", "tr_TR", "CP857", "tt_RU", "CP866", "uk_UA", "CP866",
|
||||||
|
"ur_PK", "CP720", "uz_UZ@cyrillic", "CP866", "uz_UZ", "CP857", "vi_VN", "CP1258",
|
||||||
|
"wa_BE", "CP850", "zh_HK", "CP950", "zh_SG", "CP936"};
|
||||||
|
|
||||||
|
const char *lcToAnsiTable[] = {
|
||||||
|
"af_ZA", "CP1252", "ar_SA", "CP1256", "ar_LB", "CP1256", "ar_EG", "CP1256",
|
||||||
|
"ar_DZ", "CP1256", "ar_BH", "CP1256", "ar_IQ", "CP1256", "ar_JO", "CP1256",
|
||||||
|
"ar_KW", "CP1256", "ar_LY", "CP1256", "ar_MA", "CP1256", "ar_OM", "CP1256",
|
||||||
|
"ar_QA", "CP1256", "ar_SY", "CP1256", "ar_TN", "CP1256", "ar_AE", "CP1256",
|
||||||
|
"ar_YE", "CP1256","ast_ES", "CP1252", "az_AZ@cyrillic", "CP1251", "az_AZ", "CP1254",
|
||||||
|
"be_BY", "CP1251", "bg_BG", "CP1251", "br_FR", "CP1252", "ca_ES", "CP1252",
|
||||||
|
"zh_CN", "CP936", "zh_TW", "CP950", "kw_GB", "CP1252", "cs_CZ", "CP1250",
|
||||||
|
"cy_GB", "CP1252", "da_DK", "CP1252", "de_AT", "CP1252", "de_LI", "CP1252",
|
||||||
|
"de_LU", "CP1252", "de_CH", "CP1252", "de_DE", "CP1252", "el_GR", "CP1253",
|
||||||
|
"en_AU", "CP1252", "en_CA", "CP1252", "en_GB", "CP1252", "en_IE", "CP1252",
|
||||||
|
"en_JM", "CP1252", "en_BZ", "CP1252", "en_PH", "CP1252", "en_ZA", "CP1252",
|
||||||
|
"en_TT", "CP1252", "en_US", "CP1252", "en_ZW", "CP1252", "en_NZ", "CP1252",
|
||||||
|
"es_PA", "CP1252", "es_BO", "CP1252", "es_CR", "CP1252", "es_DO", "CP1252",
|
||||||
|
"es_SV", "CP1252", "es_EC", "CP1252", "es_GT", "CP1252", "es_HN", "CP1252",
|
||||||
|
"es_NI", "CP1252", "es_CL", "CP1252", "es_MX", "CP1252", "es_ES", "CP1252",
|
||||||
|
"es_CO", "CP1252", "es_ES", "CP1252", "es_PE", "CP1252", "es_AR", "CP1252",
|
||||||
|
"es_PR", "CP1252", "es_VE", "CP1252", "es_UY", "CP1252", "es_PY", "CP1252",
|
||||||
|
"et_EE", "CP1257", "eu_ES", "CP1252", "fa_IR", "CP1256", "fi_FI", "CP1252",
|
||||||
|
"fo_FO", "CP1252", "fr_FR", "CP1252", "fr_BE", "CP1252", "fr_CA", "CP1252",
|
||||||
|
"fr_LU", "CP1252", "fr_MC", "CP1252", "fr_CH", "CP1252", "ga_IE", "CP1252",
|
||||||
|
"gd_GB", "CP1252", "gv_IM", "CP1252", "gl_ES", "CP1252", "he_IL", "CP1255",
|
||||||
|
"hr_HR", "CP1250", "hu_HU", "CP1250", "id_ID", "CP1252", "is_IS", "CP1252",
|
||||||
|
"it_IT", "CP1252", "it_CH", "CP1252", "iv_IV", "CP1252", "ja_JP", "CP932",
|
||||||
|
"kk_KZ", "CP1251", "ko_KR", "CP949", "ky_KG", "CP1251", "lt_LT", "CP1257",
|
||||||
|
"lv_LV", "CP1257", "mk_MK", "CP1251", "mn_MN", "CP1251", "ms_BN", "CP1252",
|
||||||
|
"ms_MY", "CP1252", "nl_BE", "CP1252", "nl_NL", "CP1252", "nl_SR", "CP1252",
|
||||||
|
"nn_NO", "CP1252", "nb_NO", "CP1252", "pl_PL", "CP1250", "pt_BR", "CP1252",
|
||||||
|
"pt_PT", "CP1252", "rm_CH", "CP1252", "ro_RO", "CP1250", "ru_RU", "CP1251",
|
||||||
|
"sk_SK", "CP1250", "sl_SI", "CP1250", "sq_AL", "CP1250", "sr_RS@latin", "CP1250",
|
||||||
|
"sr_RS", "CP1251", "sv_SE", "CP1252", "sv_FI", "CP1252", "sw_KE", "CP1252",
|
||||||
|
"th_TH", "CP874", "tr_TR", "CP1254", "tt_RU", "CP1251", "uk_UA", "CP1251",
|
||||||
|
"ur_PK", "CP1256", "uz_UZ@cyrillic", "CP1251", "uz_UZ", "CP1254", "vi_VN", "CP1258",
|
||||||
|
"wa_BE", "CP1252", "zh_HK", "CP950", "zh_SG", "CP936"};
|
||||||
|
|
||||||
|
bool isOem = false;
|
||||||
|
bool isAnsi = false;
|
||||||
|
|
||||||
|
if (!isUtf8 &&
|
||||||
|
MadeByVersion.HostOS == NFileHeader::NHostOS::kNTFS &&
|
||||||
|
MadeByVersion.Version >= 20) {
|
||||||
|
isAnsi = true;
|
||||||
|
} else
|
||||||
|
if (!isUtf8 &&
|
||||||
|
(MadeByVersion.HostOS == NFileHeader::NHostOS::kNTFS ||
|
||||||
|
MadeByVersion.HostOS == NFileHeader::NHostOS::kFAT)) {
|
||||||
|
isOem = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
const char *legacyCp = nullptr;
|
||||||
|
const char *legacyCpAnsi = nullptr;
|
||||||
|
|
||||||
|
if (isOem || isAnsi || (useSpecifiedCodePage && (codePage != 65001))) {
|
||||||
|
|
||||||
|
int tableLen = sizeof(lcToOemTable) / sizeof(lcToOemTable[0]);
|
||||||
|
int lcLen = 0, i;
|
||||||
|
|
||||||
|
// Detect required code page name from current locale
|
||||||
|
char *lc = getenv("LC_ALL");
|
||||||
|
if (!lc || !lc[0]) {
|
||||||
|
lc = getenv("LC_CTYPE");
|
||||||
|
}
|
||||||
|
if (!lc || !lc[0]) {
|
||||||
|
lc = getenv("LANG");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (lc && lc[0]) {
|
||||||
|
// Compare up to the dot, if it exists, e.g. en_US.UTF-8
|
||||||
|
for (lcLen = 0; lc[lcLen] != '.' && lc[lcLen] != ':' && lc[lcLen] != '\0'; ++lcLen);
|
||||||
|
|
||||||
|
for (i = 0; i < tableLen; i += 2)
|
||||||
|
if (strncmp(lc, (lcToOemTable[i]), lcLen) == 0) {
|
||||||
|
legacyCp = lcToOemTable[i + 1];
|
||||||
|
legacyCpAnsi = lcToAnsiTable[i + 1];
|
||||||
|
break; // Stop searching once a match is found
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!legacyCp) {
|
||||||
|
legacyCp = "CP437";
|
||||||
|
legacyCpAnsi = "CP1252";
|
||||||
|
}
|
||||||
|
|
||||||
|
char specCP[20];
|
||||||
|
if (useSpecifiedCodePage) {
|
||||||
|
if (codePage == 0) {
|
||||||
|
strncpy(specCP, legacyCpAnsi, sizeof(legacyCpAnsi) - 1);
|
||||||
|
specCP[sizeof(legacyCpAnsi) - 1] = '\0';
|
||||||
|
}
|
||||||
|
else if (codePage == 1) {
|
||||||
|
strncpy(specCP, legacyCp, sizeof(legacyCp) - 1);
|
||||||
|
specCP[sizeof(legacyCp) - 1] = '\0'; }
|
||||||
|
else {
|
||||||
|
snprintf(specCP, sizeof(specCP), "CP%d", codePage);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
iconv_t cd;
|
||||||
|
if ((cd = iconv_open("UTF-8", useSpecifiedCodePage ? specCP : (isOem ? legacyCp : legacyCpAnsi))) != (iconv_t)-1) {
|
||||||
|
|
||||||
|
AString sUtf8;
|
||||||
|
|
||||||
|
unsigned slen = s.Len();
|
||||||
|
char* src = s.Ptr_non_const();
|
||||||
|
|
||||||
|
unsigned dlen = slen * 4 + 1; // (source length * 4) + null termination
|
||||||
|
char* dst = sUtf8.GetBuf_SetEnd(dlen);
|
||||||
|
const char* dstStart = dst;
|
||||||
|
|
||||||
|
memset(dst, 0, dlen);
|
||||||
|
|
||||||
|
size_t slen_size_t = static_cast<size_t>(slen);
|
||||||
|
size_t dlen_size_t = static_cast<size_t>(dlen);
|
||||||
|
size_t done = iconv(cd, &src, &slen_size_t, &dst, &dlen_size_t);
|
||||||
|
|
||||||
|
if (done == (size_t)-1) {
|
||||||
|
iconv_close(cd);
|
||||||
|
|
||||||
|
// iconv failed. Falling back to default behavior
|
||||||
|
MultiByteToUnicodeString2(res, s, useSpecifiedCodePage ? codePage : GetCodePage());
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Null-terminate the result
|
||||||
|
*dst = '\0';
|
||||||
|
|
||||||
|
iconv_close(cd);
|
||||||
|
|
||||||
|
size_t dstCorrectLength = dst - dstStart;
|
||||||
|
sUtf8.ReleaseBuf_SetEnd(static_cast<unsigned>(dstCorrectLength));
|
||||||
|
|
||||||
|
if (ConvertUTF8ToUnicode(sUtf8, res) /*|| ignore_Utf8_Errors*/)
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
if (isUtf8)
|
if (isUtf8)
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -1148,26 +1148,6 @@ SOURCE=..\..\Compress\PpmdZip.cpp
|
||||||
SOURCE=..\..\Compress\PpmdZip.h
|
SOURCE=..\..\Compress\PpmdZip.h
|
||||||
# End Source File
|
# End Source File
|
||||||
# End Group
|
# End Group
|
||||||
# Begin Group "RangeCoder"
|
|
||||||
|
|
||||||
# PROP Default_Filter ""
|
|
||||||
# Begin Source File
|
|
||||||
|
|
||||||
SOURCE=..\..\Compress\RangeCoder.h
|
|
||||||
# End Source File
|
|
||||||
# Begin Source File
|
|
||||||
|
|
||||||
SOURCE=..\..\Compress\RangeCoderBit.h
|
|
||||||
# End Source File
|
|
||||||
# Begin Source File
|
|
||||||
|
|
||||||
SOURCE=..\..\Compress\RangeCoderBitTree.h
|
|
||||||
# End Source File
|
|
||||||
# Begin Source File
|
|
||||||
|
|
||||||
SOURCE=..\..\Compress\RangeCoderOpt.h
|
|
||||||
# End Source File
|
|
||||||
# End Group
|
|
||||||
# Begin Group "Shrink"
|
# Begin Group "Shrink"
|
||||||
|
|
||||||
# PROP Default_Filter ""
|
# PROP Default_Filter ""
|
||||||
|
|
|
||||||
|
|
@ -66,18 +66,14 @@ HRESULT CThreadInfo::Create()
|
||||||
if (wres == 0) { wres = CanWriteEvent.Create();
|
if (wres == 0) { wres = CanWriteEvent.Create();
|
||||||
if (wres == 0)
|
if (wres == 0)
|
||||||
{
|
{
|
||||||
|
wres =
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
if (Encoder->_props.NumThreadGroups != 0)
|
Encoder->_props.NumThreadGroups > 1 ?
|
||||||
{
|
Thread.Create_With_Group(MFThread, this, ThreadNextGroup_GetNext(&Encoder->ThreadNextGroup), 0) : // affinity
|
||||||
const UInt32 group = ThreadNextGroup_GetNext(&Encoder->ThreadNextGroup);
|
|
||||||
wres = Thread.Create_With_Group(MFThread, this, group, 0); // affinity
|
|
||||||
}
|
|
||||||
else
|
|
||||||
#endif
|
#endif
|
||||||
if (Encoder->_props.Affinity != 0)
|
Encoder->_props.Affinity != 0 ?
|
||||||
wres = Thread.Create_With_Affinity(MFThread, this, (CAffinityMask)Encoder->_props.Affinity);
|
Thread.Create_With_Affinity(MFThread, this, (CAffinityMask)Encoder->_props.Affinity) :
|
||||||
else
|
Thread.Create(MFThread, this);
|
||||||
wres = Thread.Create(MFThread, this);
|
|
||||||
}}}
|
}}}
|
||||||
return HRESULT_FROM_WIN32(wres);
|
return HRESULT_FROM_WIN32(wres);
|
||||||
}
|
}
|
||||||
|
|
@ -935,14 +931,13 @@ void CEncoder::WriteBytes(const Byte *data, UInt32 sizeInBits, unsigned lastByte
|
||||||
HRESULT CEncoder::CodeReal(ISequentialInStream *inStream, ISequentialOutStream *outStream,
|
HRESULT CEncoder::CodeReal(ISequentialInStream *inStream, ISequentialOutStream *outStream,
|
||||||
const UInt64 * /* inSize */, const UInt64 * /* outSize */, ICompressProgressInfo *progress)
|
const UInt64 * /* inSize */, const UInt64 * /* outSize */, ICompressProgressInfo *progress)
|
||||||
{
|
{
|
||||||
ThreadNextGroup_Init(&ThreadNextGroup, _props.NumThreadGroups, 0); // startGroup
|
|
||||||
|
|
||||||
NumBlocks = 0;
|
NumBlocks = 0;
|
||||||
#ifndef Z7_ST
|
#ifndef Z7_ST
|
||||||
Progress = progress;
|
Progress = progress;
|
||||||
|
ThreadNextGroup_Init(&ThreadNextGroup, _props.NumThreadGroups, 0); // startGroup
|
||||||
RINOK(Create())
|
RINOK(Create())
|
||||||
for (UInt32 t = 0; t < NumThreads; t++)
|
for (UInt32 t = 0; t < NumThreads; t++)
|
||||||
#endif
|
#endif
|
||||||
{
|
{
|
||||||
#ifndef Z7_ST
|
#ifndef Z7_ST
|
||||||
CThreadInfo &ti = ThreadsInfo[t];
|
CThreadInfo &ti = ThreadsInfo[t];
|
||||||
|
|
|
||||||
|
|
@ -636,7 +636,7 @@ HRESULT CProxyArc2::Load(const CArc &arc, IProgress *progress)
|
||||||
file.Name = (const wchar_t *)p;
|
file.Name = (const wchar_t *)p;
|
||||||
file.NameLen = 0;
|
file.NameLen = 0;
|
||||||
if (size >= sizeof(wchar_t))
|
if (size >= sizeof(wchar_t))
|
||||||
file.NameLen = size / sizeof(wchar_t) - 1;
|
file.NameLen = size / (unsigned)sizeof(wchar_t) - 1;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
#endif
|
#endif
|
||||||
|
|
|
||||||
|
|
@ -24,7 +24,6 @@ else
|
||||||
|
|
||||||
SYS_OBJS = \
|
SYS_OBJS = \
|
||||||
$O/MyWindows.o \
|
$O/MyWindows.o \
|
||||||
$O/TimeUtils.o \
|
|
||||||
|
|
||||||
endif
|
endif
|
||||||
|
|
||||||
|
|
@ -53,6 +52,7 @@ WIN_OBJS = \
|
||||||
$O/FileName.o \
|
$O/FileName.o \
|
||||||
$O/PropVariant.o \
|
$O/PropVariant.o \
|
||||||
$O/PropVariantConv.o \
|
$O/PropVariantConv.o \
|
||||||
|
$O/TimeUtils.o \
|
||||||
|
|
||||||
7ZIP_COMMON_OBJS = \
|
7ZIP_COMMON_OBJS = \
|
||||||
$O/FileStreams.o \
|
$O/FileStreams.o \
|
||||||
|
|
|
||||||
|
|
@ -341,7 +341,7 @@ static const CSwitchForm kSwitchForms[] =
|
||||||
{ "spf", SWFRM_STRING_SINGL(0) },
|
{ "spf", SWFRM_STRING_SINGL(0) },
|
||||||
|
|
||||||
{ "snh", SWFRM_MINUS },
|
{ "snh", SWFRM_MINUS },
|
||||||
{ "snld", SWFRM_MINUS },
|
{ "snld", SWFRM_STRING },
|
||||||
{ "snl", SWFRM_MINUS },
|
{ "snl", SWFRM_MINUS },
|
||||||
{ "sni", SWFRM_SIMPLE },
|
{ "sni", SWFRM_SIMPLE },
|
||||||
|
|
||||||
|
|
@ -1479,14 +1479,8 @@ void CArcCmdLineParser::Parse2(CArcCmdLineOptions &options)
|
||||||
|
|
||||||
SetBoolPair(parser, NKey::kStoreOwnerId, options.StoreOwnerId);
|
SetBoolPair(parser, NKey::kStoreOwnerId, options.StoreOwnerId);
|
||||||
SetBoolPair(parser, NKey::kStoreOwnerName, options.StoreOwnerName);
|
SetBoolPair(parser, NKey::kStoreOwnerName, options.StoreOwnerName);
|
||||||
|
|
||||||
CBoolPair symLinks_AllowDangerous;
|
|
||||||
SetBoolPair(parser, NKey::kSymLinks_AllowDangerous, symLinks_AllowDangerous);
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
bool supportSymLink = options.SymLinks.Val;
|
bool supportSymLink = options.SymLinks.Val;
|
||||||
|
|
||||||
if (!options.SymLinks.Def)
|
if (!options.SymLinks.Def)
|
||||||
{
|
{
|
||||||
if (isExtractOrList)
|
if (isExtractOrList)
|
||||||
|
|
@ -1494,7 +1488,6 @@ void CArcCmdLineParser::Parse2(CArcCmdLineOptions &options)
|
||||||
else
|
else
|
||||||
supportSymLink = false;
|
supportSymLink = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef ENV_HAVE_LSTAT
|
#ifdef ENV_HAVE_LSTAT
|
||||||
if (supportSymLink)
|
if (supportSymLink)
|
||||||
global_use_lstat = 1;
|
global_use_lstat = 1;
|
||||||
|
|
@ -1503,7 +1496,6 @@ void CArcCmdLineParser::Parse2(CArcCmdLineOptions &options)
|
||||||
#endif
|
#endif
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
||||||
if (isExtractOrList)
|
if (isExtractOrList)
|
||||||
{
|
{
|
||||||
CExtractOptionsBase &eo = options.ExtractOptions;
|
CExtractOptionsBase &eo = options.ExtractOptions;
|
||||||
|
|
@ -1527,7 +1519,15 @@ void CArcCmdLineParser::Parse2(CArcCmdLineOptions &options)
|
||||||
if (!options.SymLinks.Def)
|
if (!options.SymLinks.Def)
|
||||||
nt.SymLinks.Val = true;
|
nt.SymLinks.Val = true;
|
||||||
|
|
||||||
nt.SymLinks_AllowDangerous = symLinks_AllowDangerous;
|
if (parser[NKey::kSymLinks_AllowDangerous].ThereIs)
|
||||||
|
{
|
||||||
|
const UString &s = parser[NKey::kSymLinks_AllowDangerous].PostStrings[0];
|
||||||
|
UInt32 v = 9; // default value for "-snld" instead of default = 5 without "-snld".
|
||||||
|
if (!s.IsEmpty())
|
||||||
|
if (!StringToUInt32(s, v))
|
||||||
|
throw CArcCmdLineException("Unsupported switch postfix -snld", s);
|
||||||
|
nt.SymLinks_DangerousLevel = (unsigned)v;
|
||||||
|
}
|
||||||
|
|
||||||
nt.ReplaceColonForAltStream = parser[NKey::kReplaceColonForAltStream].ThereIs;
|
nt.ReplaceColonForAltStream = parser[NKey::kReplaceColonForAltStream].ThereIs;
|
||||||
nt.WriteToAltStreamIfColon = parser[NKey::kWriteToAltStreamIfColon].ThereIs;
|
nt.WriteToAltStreamIfColon = parser[NKey::kWriteToAltStreamIfColon].ThereIs;
|
||||||
|
|
|
||||||
|
|
@ -54,10 +54,14 @@ static const char * const kCantSetFileLen = "Cannot set length for output file";
|
||||||
#ifdef SUPPORT_LINKS
|
#ifdef SUPPORT_LINKS
|
||||||
static const char * const kCantCreateHardLink = "Cannot create hard link";
|
static const char * const kCantCreateHardLink = "Cannot create hard link";
|
||||||
static const char * const kCantCreateSymLink = "Cannot create symbolic link";
|
static const char * const kCantCreateSymLink = "Cannot create symbolic link";
|
||||||
|
static const char * const k_HardLink_to_SymLink_Ignored = "Hard link to symbolic link was ignored";
|
||||||
|
static const char * const k_CantDelete_File_for_SymLink = "Cannot delete file for symbolic link creation";
|
||||||
|
static const char * const k_CantDelete_Dir_for_SymLink = "Cannot delete directory for symbolic link creation";
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
static const unsigned k_LinkDataSize_LIMIT = 1 << 12;
|
static const unsigned k_LinkDataSize_LIMIT = 1 << 12;
|
||||||
|
|
||||||
|
#ifdef SUPPORT_LINKS
|
||||||
#if WCHAR_PATH_SEPARATOR != L'/'
|
#if WCHAR_PATH_SEPARATOR != L'/'
|
||||||
// we convert linux slashes to windows slashes for further processing.
|
// we convert linux slashes to windows slashes for further processing.
|
||||||
// also we convert linux backslashes to BackslashReplacement character.
|
// also we convert linux backslashes to BackslashReplacement character.
|
||||||
|
|
@ -67,7 +71,7 @@ static const unsigned k_LinkDataSize_LIMIT = 1 << 12;
|
||||||
#else
|
#else
|
||||||
#define REPLACE_SLASHES_from_Linux_to_Sys(s)
|
#define REPLACE_SLASHES_from_Linux_to_Sys(s)
|
||||||
#endif
|
#endif
|
||||||
|
#endif
|
||||||
|
|
||||||
#ifndef Z7_SFX
|
#ifndef Z7_SFX
|
||||||
|
|
||||||
|
|
@ -326,13 +330,14 @@ void CArchiveExtractCallback::Init(
|
||||||
_outFileStream.Release();
|
_outFileStream.Release();
|
||||||
_bufPtrSeqOutStream.Release();
|
_bufPtrSeqOutStream.Release();
|
||||||
|
|
||||||
#ifdef SUPPORT_LINKS
|
#ifdef SUPPORT_LINKS
|
||||||
_hardLinks.Clear();
|
_hardLinks.Clear();
|
||||||
#endif
|
_postLinks.Clear();
|
||||||
|
#endif
|
||||||
|
|
||||||
#ifdef SUPPORT_ALT_STREAMS
|
#ifdef SUPPORT_ALT_STREAMS
|
||||||
_renamedFiles.Clear();
|
_renamedFiles.Clear();
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
_ntOptions = ntOptions;
|
_ntOptions = ntOptions;
|
||||||
_wildcardCensor = wildcardCensor;
|
_wildcardCensor = wildcardCensor;
|
||||||
|
|
@ -455,7 +460,8 @@ Z7_COM7F_IMF(CArchiveExtractCallback::SetRatioInfo(const UInt64 *inSize, const U
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void CArchiveExtractCallback::CreateComplexDirectory(const UStringVector &dirPathParts, FString &fullPath)
|
void CArchiveExtractCallback::CreateComplexDirectory(
|
||||||
|
const UStringVector &dirPathParts, bool isFinal, FString &fullPath)
|
||||||
{
|
{
|
||||||
// we use (_item.IsDir) in this function
|
// we use (_item.IsDir) in this function
|
||||||
|
|
||||||
|
|
@ -487,7 +493,7 @@ void CArchiveExtractCallback::CreateComplexDirectory(const UStringVector &dirPat
|
||||||
const UString &s = dirPathParts[i];
|
const UString &s = dirPathParts[i];
|
||||||
fullPath += us2fs(s);
|
fullPath += us2fs(s);
|
||||||
|
|
||||||
const bool isFinalDir = (i == dirPathParts.Size() - 1 && _item.IsDir);
|
const bool isFinalDir = (i == dirPathParts.Size() - 1 && isFinal && _item.IsDir);
|
||||||
|
|
||||||
if (fullPath.IsEmpty())
|
if (fullPath.IsEmpty())
|
||||||
{
|
{
|
||||||
|
|
@ -548,7 +554,7 @@ static void AddPathToMessage(UString &s, const FString &path)
|
||||||
s += fs2us(path);
|
s += fs2us(path);
|
||||||
}
|
}
|
||||||
|
|
||||||
HRESULT CArchiveExtractCallback::SendMessageError(const char *message, const FString &path)
|
HRESULT CArchiveExtractCallback::SendMessageError(const char *message, const FString &path) const
|
||||||
{
|
{
|
||||||
UString s (message);
|
UString s (message);
|
||||||
AddPathToMessage(s, path);
|
AddPathToMessage(s, path);
|
||||||
|
|
@ -556,7 +562,7 @@ HRESULT CArchiveExtractCallback::SendMessageError(const char *message, const FSt
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
HRESULT CArchiveExtractCallback::SendMessageError_with_Error(HRESULT errorCode, const char *message, const FString &path)
|
HRESULT CArchiveExtractCallback::SendMessageError_with_Error(HRESULT errorCode, const char *message, const FString &path) const
|
||||||
{
|
{
|
||||||
UString s (message);
|
UString s (message);
|
||||||
if (errorCode != S_OK)
|
if (errorCode != S_OK)
|
||||||
|
|
@ -568,13 +574,13 @@ HRESULT CArchiveExtractCallback::SendMessageError_with_Error(HRESULT errorCode,
|
||||||
return _extractCallback2->MessageError(s);
|
return _extractCallback2->MessageError(s);
|
||||||
}
|
}
|
||||||
|
|
||||||
HRESULT CArchiveExtractCallback::SendMessageError_with_LastError(const char *message, const FString &path)
|
HRESULT CArchiveExtractCallback::SendMessageError_with_LastError(const char *message, const FString &path) const
|
||||||
{
|
{
|
||||||
const HRESULT errorCode = GetLastError_noZero_HRESULT();
|
const HRESULT errorCode = GetLastError_noZero_HRESULT();
|
||||||
return SendMessageError_with_Error(errorCode, message, path);
|
return SendMessageError_with_Error(errorCode, message, path);
|
||||||
}
|
}
|
||||||
|
|
||||||
HRESULT CArchiveExtractCallback::SendMessageError2(HRESULT errorCode, const char *message, const FString &path1, const FString &path2)
|
HRESULT CArchiveExtractCallback::SendMessageError2(HRESULT errorCode, const char *message, const FString &path1, const FString &path2) const
|
||||||
{
|
{
|
||||||
UString s (message);
|
UString s (message);
|
||||||
if (errorCode != 0)
|
if (errorCode != 0)
|
||||||
|
|
@ -588,7 +594,7 @@ HRESULT CArchiveExtractCallback::SendMessageError2(HRESULT errorCode, const char
|
||||||
}
|
}
|
||||||
|
|
||||||
HRESULT CArchiveExtractCallback::SendMessageError2_with_LastError(
|
HRESULT CArchiveExtractCallback::SendMessageError2_with_LastError(
|
||||||
const char *message, const FString &path1, const FString &path2)
|
const char *message, const FString &path1, const FString &path2) const
|
||||||
{
|
{
|
||||||
const HRESULT errorCode = GetLastError_noZero_HRESULT();
|
const HRESULT errorCode = GetLastError_noZero_HRESULT();
|
||||||
return SendMessageError2(errorCode, message, path1, path2);
|
return SendMessageError2(errorCode, message, path1, path2);
|
||||||
|
|
@ -627,6 +633,7 @@ Z7_COM7F_IMF(CGetProp::GetProp(PROPID propID, PROPVARIANT *value))
|
||||||
struct CLinkLevelsInfo
|
struct CLinkLevelsInfo
|
||||||
{
|
{
|
||||||
bool IsAbsolute;
|
bool IsAbsolute;
|
||||||
|
bool ParentDirDots_after_NonParent;
|
||||||
int LowLevel;
|
int LowLevel;
|
||||||
int FinalLevel;
|
int FinalLevel;
|
||||||
|
|
||||||
|
|
@ -640,6 +647,8 @@ void CLinkLevelsInfo::Parse(const UString &path, bool isWSL)
|
||||||
NName::IsAbsolutePath(path);
|
NName::IsAbsolutePath(path);
|
||||||
LowLevel = 0;
|
LowLevel = 0;
|
||||||
FinalLevel = 0;
|
FinalLevel = 0;
|
||||||
|
ParentDirDots_after_NonParent = false;
|
||||||
|
bool nonParentDir = false;
|
||||||
|
|
||||||
UStringVector parts;
|
UStringVector parts;
|
||||||
SplitPathToParts(path, parts);
|
SplitPathToParts(path, parts);
|
||||||
|
|
@ -658,12 +667,17 @@ void CLinkLevelsInfo::Parse(const UString &path, bool isWSL)
|
||||||
continue;
|
continue;
|
||||||
if (s.IsEqualTo(".."))
|
if (s.IsEqualTo(".."))
|
||||||
{
|
{
|
||||||
|
if (IsAbsolute || nonParentDir)
|
||||||
|
ParentDirDots_after_NonParent = true;
|
||||||
level--;
|
level--;
|
||||||
if (LowLevel > level)
|
if (LowLevel > level)
|
||||||
LowLevel = level;
|
LowLevel = level;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
{
|
||||||
|
nonParentDir = true;
|
||||||
level++;
|
level++;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
FinalLevel = level;
|
FinalLevel = level;
|
||||||
|
|
@ -915,7 +929,7 @@ HRESULT CArchiveExtractCallback::ReadLink()
|
||||||
#ifndef _WIN32
|
#ifndef _WIN32
|
||||||
|
|
||||||
static HRESULT GetOwner(IInArchive *archive,
|
static HRESULT GetOwner(IInArchive *archive,
|
||||||
UInt32 index, UInt32 pidName, UInt32 pidId, COwnerInfo &res)
|
UInt32 index, UInt32 pidName, UInt32 pidId, CProcessedFileInfo::COwnerInfo &res)
|
||||||
{
|
{
|
||||||
{
|
{
|
||||||
NWindows::NCOM::CPropVariant prop;
|
NWindows::NCOM::CPropVariant prop;
|
||||||
|
|
@ -1047,7 +1061,7 @@ void CArchiveExtractCallback::CorrectPathParts()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void CArchiveExtractCallback::GetFiTimesCAM(CFiTimesCAM &pt)
|
static void GetFiTimesCAM(const CProcessedFileInfo &fi, CFiTimesCAM &pt, const CArc &arc)
|
||||||
{
|
{
|
||||||
pt.CTime_Defined = false;
|
pt.CTime_Defined = false;
|
||||||
pt.ATime_Defined = false;
|
pt.ATime_Defined = false;
|
||||||
|
|
@ -1055,27 +1069,27 @@ void CArchiveExtractCallback::GetFiTimesCAM(CFiTimesCAM &pt)
|
||||||
|
|
||||||
// if (Write_MTime)
|
// if (Write_MTime)
|
||||||
{
|
{
|
||||||
if (_fi.MTime.Def)
|
if (fi.MTime.Def)
|
||||||
{
|
{
|
||||||
_fi.MTime.Write_To_FiTime(pt.MTime);
|
fi.MTime.Write_To_FiTime(pt.MTime);
|
||||||
pt.MTime_Defined = true;
|
pt.MTime_Defined = true;
|
||||||
}
|
}
|
||||||
else if (_arc->MTime.Def)
|
else if (arc.MTime.Def)
|
||||||
{
|
{
|
||||||
_arc->MTime.Write_To_FiTime(pt.MTime);
|
arc.MTime.Write_To_FiTime(pt.MTime);
|
||||||
pt.MTime_Defined = true;
|
pt.MTime_Defined = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (/* Write_CTime && */ _fi.CTime.Def)
|
if (/* Write_CTime && */ fi.CTime.Def)
|
||||||
{
|
{
|
||||||
_fi.CTime.Write_To_FiTime(pt.CTime);
|
fi.CTime.Write_To_FiTime(pt.CTime);
|
||||||
pt.CTime_Defined = true;
|
pt.CTime_Defined = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (/* Write_ATime && */ _fi.ATime.Def)
|
if (/* Write_ATime && */ fi.ATime.Def)
|
||||||
{
|
{
|
||||||
_fi.ATime.Write_To_FiTime(pt.ATime);
|
fi.ATime.Write_To_FiTime(pt.ATime);
|
||||||
pt.ATime_Defined = true;
|
pt.ATime_Defined = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -1086,6 +1100,7 @@ void CArchiveExtractCallback::CreateFolders()
|
||||||
// 21.04 : we don't change original (_item.PathParts) here
|
// 21.04 : we don't change original (_item.PathParts) here
|
||||||
UStringVector pathParts = _item.PathParts;
|
UStringVector pathParts = _item.PathParts;
|
||||||
|
|
||||||
|
bool isFinal = true;
|
||||||
// bool is_DirOp = false;
|
// bool is_DirOp = false;
|
||||||
if (!pathParts.IsEmpty())
|
if (!pathParts.IsEmpty())
|
||||||
{
|
{
|
||||||
|
|
@ -1095,12 +1110,15 @@ void CArchiveExtractCallback::CreateFolders()
|
||||||
but if we create dir item here, it's not problem. */
|
but if we create dir item here, it's not problem. */
|
||||||
if (!_item.IsDir
|
if (!_item.IsDir
|
||||||
#ifdef SUPPORT_LINKS
|
#ifdef SUPPORT_LINKS
|
||||||
#ifndef WIN32
|
// #ifndef WIN32
|
||||||
|| !_link.LinkPath.IsEmpty()
|
|| !_link.LinkPath.IsEmpty()
|
||||||
#endif
|
// #endif
|
||||||
#endif
|
#endif
|
||||||
)
|
)
|
||||||
|
{
|
||||||
pathParts.DeleteBack();
|
pathParts.DeleteBack();
|
||||||
|
isFinal = false; // last path part was excluded
|
||||||
|
}
|
||||||
// else is_DirOp = true;
|
// else is_DirOp = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1124,7 +1142,7 @@ void CArchiveExtractCallback::CreateFolders()
|
||||||
*/
|
*/
|
||||||
|
|
||||||
FString fullPathNew;
|
FString fullPathNew;
|
||||||
CreateComplexDirectory(pathParts, fullPathNew);
|
CreateComplexDirectory(pathParts, isFinal, fullPathNew);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
if (is_DirOp)
|
if (is_DirOp)
|
||||||
|
|
@ -1145,12 +1163,12 @@ void CArchiveExtractCallback::CreateFolders()
|
||||||
return;
|
return;
|
||||||
|
|
||||||
CDirPathTime pt;
|
CDirPathTime pt;
|
||||||
GetFiTimesCAM(pt);
|
GetFiTimesCAM(_fi, pt, *_arc);
|
||||||
|
|
||||||
if (pt.IsSomeTimeDefined())
|
if (pt.IsSomeTimeDefined())
|
||||||
{
|
{
|
||||||
pt.Path = fullPathNew;
|
pt.Path = fullPathNew;
|
||||||
pt.SetDirTime();
|
pt.SetDirTime_to_FS_2();
|
||||||
_extractedFolders.Add(pt);
|
_extractedFolders.Add(pt);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -1292,9 +1310,11 @@ HRESULT CArchiveExtractCallback::CheckExistFile(FString &fullProcessedPath, bool
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
return:
|
||||||
|
needExit = false: caller will use (outStreamLoc) and _hashStreamSpec
|
||||||
|
needExit = true : caller will not use (outStreamLoc) and _hashStreamSpec.
|
||||||
|
*/
|
||||||
HRESULT CArchiveExtractCallback::GetExtractStream(CMyComPtr<ISequentialOutStream> &outStreamLoc, bool &needExit)
|
HRESULT CArchiveExtractCallback::GetExtractStream(CMyComPtr<ISequentialOutStream> &outStreamLoc, bool &needExit)
|
||||||
{
|
{
|
||||||
needExit = true;
|
needExit = true;
|
||||||
|
|
@ -1383,12 +1403,15 @@ HRESULT CArchiveExtractCallback::GetExtractStream(CMyComPtr<ISequentialOutStream
|
||||||
{
|
{
|
||||||
bool linkWasSet = false;
|
bool linkWasSet = false;
|
||||||
RINOK(SetLink(fullProcessedPath, _link, linkWasSet))
|
RINOK(SetLink(fullProcessedPath, _link, linkWasSet))
|
||||||
|
/*
|
||||||
|
// we don't set attributes for placeholder.
|
||||||
if (linkWasSet)
|
if (linkWasSet)
|
||||||
{
|
{
|
||||||
_isSymLinkCreated = _link.Is_AnySymLink();
|
_isSymLinkCreated = _link.Is_AnySymLink();
|
||||||
SetAttrib();
|
SetAttrib();
|
||||||
// printf("\nlinkWasSet %s\n", GetAnsiString(_diskFilePath));
|
// printf("\nlinkWasSet %s\n", GetAnsiString(_diskFilePath));
|
||||||
}
|
}
|
||||||
|
*/
|
||||||
}
|
}
|
||||||
#endif // UNDER_CE
|
#endif // UNDER_CE
|
||||||
|
|
||||||
|
|
@ -1414,11 +1437,17 @@ HRESULT CArchiveExtractCallback::GetExtractStream(CMyComPtr<ISequentialOutStream
|
||||||
hl = fullProcessedPath;
|
hl = fullProcessedPath;
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if (!MyCreateHardLink(fullProcessedPath, hl))
|
bool link_was_Created = false;
|
||||||
return SendMessageError2_with_LastError(kCantCreateHardLink, fullProcessedPath, hl);
|
RINOK(CreateHardLink2(fullProcessedPath, hl, link_was_Created))
|
||||||
|
if (!link_was_Created)
|
||||||
|
return S_OK;
|
||||||
// printf("\nHard linkWasSet Archive_Get_HardLinkNode %s\n", GetAnsiString(_diskFilePath));
|
// printf("\nHard linkWasSet Archive_Get_HardLinkNode %s\n", GetAnsiString(_diskFilePath));
|
||||||
// _needSetAttrib = true; // do we need to set attribute ?
|
// _needSetAttrib = true; // do we need to set attribute ?
|
||||||
SetAttrib();
|
SetAttrib();
|
||||||
|
/* if we set (needExit = false) here, _hashStreamSpec will be used,
|
||||||
|
and hash will be calulated for all hard links files (it's slower).
|
||||||
|
But "Test" operation also calculates hashes.
|
||||||
|
*/
|
||||||
needExit = false;
|
needExit = false;
|
||||||
return S_OK;
|
return S_OK;
|
||||||
}
|
}
|
||||||
|
|
@ -1943,7 +1972,7 @@ HRESULT CArchiveExtractCallback::CloseFile()
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
CFiTimesCAM t;
|
CFiTimesCAM t;
|
||||||
GetFiTimesCAM(t);
|
GetFiTimesCAM(_fi, t, *_arc);
|
||||||
|
|
||||||
// #ifdef _WIN32
|
// #ifdef _WIN32
|
||||||
if (t.IsSomeTimeDefined())
|
if (t.IsSomeTimeDefined())
|
||||||
|
|
@ -1970,52 +1999,219 @@ HRESULT CArchiveExtractCallback::CloseFile()
|
||||||
|
|
||||||
#ifdef SUPPORT_LINKS
|
#ifdef SUPPORT_LINKS
|
||||||
|
|
||||||
|
static bool CheckLinkPath_in_FS_for_pathParts(const FString &path, const UStringVector &v)
|
||||||
|
{
|
||||||
|
FString path2 = path;
|
||||||
|
FOR_VECTOR (i, v)
|
||||||
|
{
|
||||||
|
// if (i == v.Size() - 1) path = path2; // we don't need last part in returned path
|
||||||
|
path2 += us2fs(v[i]);
|
||||||
|
NFind::CFileInfo fi;
|
||||||
|
// printf("\nCheckLinkPath_in_FS_for_pathParts(): %s\n", GetOemString(path2).Ptr());
|
||||||
|
if (fi.Find(path2) && fi.IsOsSymLink())
|
||||||
|
return false;
|
||||||
|
path2.Add_PathSepar();
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
in:
|
link.isRelative / relative_item_PathPrefix
|
||||||
link.LinkPath : must be relative (non-absolute) path in any case !!!
|
false / empty
|
||||||
link.isRelative / target path that must stored as created link:
|
true / item path without last part
|
||||||
== false / _dirPathPrefix_Full + link.LinkPath
|
|
||||||
== true / link.LinkPath
|
|
||||||
*/
|
*/
|
||||||
|
static bool CheckLinkPath_in_FS(
|
||||||
|
const FString &pathPrefix_in_FS,
|
||||||
|
const CPostLink &postLink,
|
||||||
|
const UString &relative_item_PathPrefix)
|
||||||
|
{
|
||||||
|
const CLinkInfo &link = postLink.LinkInfo;
|
||||||
|
if (postLink.item_PathParts.IsEmpty() || link.LinkPath.IsEmpty())
|
||||||
|
return false;
|
||||||
|
FString path;
|
||||||
|
{
|
||||||
|
const UString &s = postLink.item_PathParts[0];
|
||||||
|
if (!s.IsEmpty() && !NName::IsAbsolutePath(s))
|
||||||
|
path = pathPrefix_in_FS; // item_PathParts is relative. So we use absolutre prefix
|
||||||
|
}
|
||||||
|
if (!CheckLinkPath_in_FS_for_pathParts(path, postLink.item_PathParts))
|
||||||
|
return false;
|
||||||
|
path += us2fs(relative_item_PathPrefix);
|
||||||
|
UStringVector v;
|
||||||
|
SplitPathToParts(link.LinkPath, v);
|
||||||
|
// we check target paths:
|
||||||
|
return CheckLinkPath_in_FS_for_pathParts(path, v);
|
||||||
|
}
|
||||||
|
|
||||||
|
static const unsigned k_DangLevel_MAX_for_Link_over_Link = 9;
|
||||||
|
|
||||||
|
HRESULT CArchiveExtractCallback::CreateHardLink2(
|
||||||
|
const FString &newFilePath, const FString &existFilePath, bool &link_was_Created) const
|
||||||
|
{
|
||||||
|
link_was_Created = false;
|
||||||
|
if (_ntOptions.SymLinks_DangerousLevel <= k_DangLevel_MAX_for_Link_over_Link)
|
||||||
|
{
|
||||||
|
NFind::CFileInfo fi;
|
||||||
|
if (fi.Find(existFilePath) && fi.IsOsSymLink())
|
||||||
|
return SendMessageError2(0, k_HardLink_to_SymLink_Ignored, newFilePath, existFilePath);
|
||||||
|
}
|
||||||
|
if (!MyCreateHardLink(newFilePath, existFilePath))
|
||||||
|
return SendMessageError2_with_LastError(kCantCreateHardLink, newFilePath, existFilePath);
|
||||||
|
link_was_Created = true;
|
||||||
|
return S_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
HRESULT CArchiveExtractCallback::SetLink(
|
HRESULT CArchiveExtractCallback::SetLink(
|
||||||
const FString &fullProcessedPath_from,
|
const FString &fullProcessedPath_from,
|
||||||
const CLinkInfo &link,
|
const CLinkInfo &link,
|
||||||
bool &linkWasSet)
|
bool &linkWasSet) // placeholder was created
|
||||||
{
|
{
|
||||||
linkWasSet = false;
|
linkWasSet = false;
|
||||||
if (link.LinkPath.IsEmpty())
|
if (link.LinkPath.IsEmpty())
|
||||||
return S_OK;
|
return S_OK;
|
||||||
if (!_ntOptions.SymLinks.Val && link.Is_AnySymLink())
|
if (!_ntOptions.SymLinks.Val && link.Is_AnySymLink())
|
||||||
return S_OK;
|
return S_OK;
|
||||||
|
CPostLink postLink;
|
||||||
|
postLink.Index_in_Arc = _index;
|
||||||
|
postLink.item_IsDir = _item.IsDir;
|
||||||
|
postLink.item_Path = _item.Path;
|
||||||
|
postLink.item_PathParts = _item.PathParts;
|
||||||
|
postLink.item_FileInfo = _fi;
|
||||||
|
postLink.fullProcessedPath_from = fullProcessedPath_from;
|
||||||
|
postLink.LinkInfo = link;
|
||||||
|
_postLinks.Add(postLink);
|
||||||
|
|
||||||
|
// file doesn't exist in most cases. So we don't check for error.
|
||||||
|
DeleteLinkFileAlways_or_RemoveEmptyDir(fullProcessedPath_from, false); // checkThatFileIsEmpty = false
|
||||||
|
|
||||||
|
NIO::COutFile outFile;
|
||||||
|
if (!outFile.Create_NEW(fullProcessedPath_from))
|
||||||
|
return SendMessageError("Cannot create temporary link file", fullProcessedPath_from);
|
||||||
|
#if 0 // 1 for debug
|
||||||
|
// here we can write link path to temporary link file placeholder,
|
||||||
|
// but empty placeholder is better, because we don't want to get any non-eampty data instead of link file.
|
||||||
|
AString s;
|
||||||
|
ConvertUnicodeToUTF8(link.LinkPath, s);
|
||||||
|
outFile.WriteFull(s, s.Len());
|
||||||
|
#endif
|
||||||
|
linkWasSet = true;
|
||||||
|
return S_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// if file/dir is symbolic link it will remove only link itself
|
||||||
|
HRESULT CArchiveExtractCallback::DeleteLinkFileAlways_or_RemoveEmptyDir(
|
||||||
|
const FString &path, bool checkThatFileIsEmpty) const
|
||||||
|
{
|
||||||
|
NFile::NFind::CFileInfo fi;
|
||||||
|
if (fi.Find(path)) // followLink = false
|
||||||
{
|
{
|
||||||
UString path;
|
if (fi.IsDir())
|
||||||
if (link.isRelative)
|
|
||||||
{
|
{
|
||||||
// _item.PathParts : parts that will be created in output folder.
|
if (RemoveDirAlways_if_Empty(path))
|
||||||
// we want to get directory prefix of link item.
|
return S_OK;
|
||||||
// so we remove file name (last non-empty part) from PathParts:
|
|
||||||
UStringVector v = _item.PathParts;
|
|
||||||
while (!v.IsEmpty())
|
|
||||||
{
|
|
||||||
const unsigned len = v.Back().Len();
|
|
||||||
v.DeleteBack();
|
|
||||||
if (len)
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
path = MakePathFromParts(v);
|
|
||||||
NName::NormalizeDirPathPrefix(path);
|
|
||||||
}
|
}
|
||||||
path += link.LinkPath;
|
else
|
||||||
|
{
|
||||||
|
// link file placeholder must be empty
|
||||||
|
if (checkThatFileIsEmpty && !fi.IsOsSymLink() && fi.Size != 0)
|
||||||
|
return SendMessageError("Temporary link file is not empty", path);
|
||||||
|
if (DeleteFileAlways(path))
|
||||||
|
return S_OK;
|
||||||
|
}
|
||||||
|
if (GetLastError() != ERROR_FILE_NOT_FOUND)
|
||||||
|
return SendMessageError_with_LastError(
|
||||||
|
fi.IsDir() ?
|
||||||
|
k_CantDelete_Dir_for_SymLink:
|
||||||
|
k_CantDelete_File_for_SymLink,
|
||||||
|
path);
|
||||||
|
}
|
||||||
|
return S_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
in:
|
||||||
|
link.LinkPath : must be relative (non-absolute) path in any case !!!
|
||||||
|
link.isRelative / target path that must stored as created link:
|
||||||
|
== false / _dirPathPrefix_Full + link.LinkPath
|
||||||
|
== true / link.LinkPath
|
||||||
|
*/
|
||||||
|
static HRESULT SetLink2(const CArchiveExtractCallback &callback,
|
||||||
|
const CPostLink &postLink, bool &linkWasSet)
|
||||||
|
{
|
||||||
|
const CLinkInfo &link = postLink.LinkInfo;
|
||||||
|
const FString &fullProcessedPath_from = postLink.fullProcessedPath_from; // full file path in FS (fullProcessedPath_from)
|
||||||
|
|
||||||
|
const unsigned level = callback._ntOptions.SymLinks_DangerousLevel;
|
||||||
|
if (level < 20)
|
||||||
|
{
|
||||||
/*
|
/*
|
||||||
path is calculated virtual target path of link
|
We want to use additional check for links that can link to directory.
|
||||||
path is relative to root folder of extracted items
|
- linux: all symbolic links are files.
|
||||||
if (!link.isRelative), then (path == link.LinkPath)
|
- windows: we can have file/directory symbolic link,
|
||||||
|
but file symbolic link works like directory link in windows.
|
||||||
|
So we use additional check for all relative links.
|
||||||
|
|
||||||
|
We don't allow decreasing of final level of link.
|
||||||
|
So if some another extracted file will use this link,
|
||||||
|
then number of real path parts (after link redirection) cannot be
|
||||||
|
smaller than number of requested path parts from archive records.
|
||||||
|
|
||||||
|
here we check only (link.LinkPath) without (_item.PathParts).
|
||||||
*/
|
*/
|
||||||
if (!IsSafePath(path, link.Is_WSL()))
|
CLinkLevelsInfo li;
|
||||||
return SendMessageError2(0, // errorCode
|
li.Parse(link.LinkPath, link.Is_WSL());
|
||||||
"Dangerous link path was ignored",
|
bool isDang;
|
||||||
us2fs(_item.Path), us2fs(link.LinkPath));
|
UString relativePathPrefix;
|
||||||
|
if (li.IsAbsolute // unexpected
|
||||||
|
|| li.ParentDirDots_after_NonParent
|
||||||
|
|| (level <= 5 && link.isRelative && li.FinalLevel < 1) // final level lower
|
||||||
|
|| (level <= 5 && link.isRelative && li.LowLevel < 0) // negative temporary levels
|
||||||
|
)
|
||||||
|
isDang = true;
|
||||||
|
else // if (!isDang)
|
||||||
|
{
|
||||||
|
UString path;
|
||||||
|
if (link.isRelative)
|
||||||
|
{
|
||||||
|
// item_PathParts : parts that will be created in output folder.
|
||||||
|
// we want to get directory prefix of link item.
|
||||||
|
// so we remove file name (last non-empty part) from PathParts:
|
||||||
|
UStringVector v = postLink.item_PathParts;
|
||||||
|
while (!v.IsEmpty())
|
||||||
|
{
|
||||||
|
const unsigned len = v.Back().Len();
|
||||||
|
v.DeleteBack();
|
||||||
|
if (len)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
path = MakePathFromParts(v);
|
||||||
|
NName::NormalizeDirPathPrefix(path);
|
||||||
|
relativePathPrefix = path;
|
||||||
|
}
|
||||||
|
path += link.LinkPath;
|
||||||
|
/*
|
||||||
|
path is calculated virtual target path of link
|
||||||
|
path is relative to root folder of extracted items
|
||||||
|
if (!link.isRelative), then (path == link.LinkPath)
|
||||||
|
*/
|
||||||
|
isDang = false;
|
||||||
|
if (!IsSafePath(path, link.Is_WSL()))
|
||||||
|
isDang = true;
|
||||||
|
}
|
||||||
|
const char *message = NULL;
|
||||||
|
if (isDang)
|
||||||
|
message = "Dangerous link path was ignored";
|
||||||
|
else if (level <= k_DangLevel_MAX_for_Link_over_Link
|
||||||
|
&& !CheckLinkPath_in_FS(callback._dirPathPrefix_Full,
|
||||||
|
postLink, relativePathPrefix))
|
||||||
|
message = "Dangerous link via another link was ignored";
|
||||||
|
if (message)
|
||||||
|
return callback.SendMessageError2(0, // errorCode
|
||||||
|
message, us2fs(postLink.item_Path), us2fs(link.LinkPath));
|
||||||
}
|
}
|
||||||
|
|
||||||
FString target; // target path that will be stored to link field
|
FString target; // target path that will be stored to link field
|
||||||
|
|
@ -2025,8 +2221,8 @@ HRESULT CArchiveExtractCallback::SetLink(
|
||||||
// all hard links and absolute symbolic links
|
// all hard links and absolute symbolic links
|
||||||
// relatPath == link.LinkPath
|
// relatPath == link.LinkPath
|
||||||
// we get absolute link path for target:
|
// we get absolute link path for target:
|
||||||
if (!NName::GetFullPath(_dirPathPrefix_Full, us2fs(link.LinkPath), target))
|
if (!NName::GetFullPath(callback._dirPathPrefix_Full, us2fs(link.LinkPath), target))
|
||||||
return SendMessageError("Incorrect link path", us2fs(link.LinkPath));
|
return callback.SendMessageError("Incorrect link path", us2fs(link.LinkPath));
|
||||||
// (target) is (_dirPathPrefix_Full + relatPath)
|
// (target) is (_dirPathPrefix_Full + relatPath)
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
|
@ -2036,21 +2232,24 @@ HRESULT CArchiveExtractCallback::SetLink(
|
||||||
target = us2fs(link.LinkPath);
|
target = us2fs(link.LinkPath);
|
||||||
}
|
}
|
||||||
if (target.IsEmpty())
|
if (target.IsEmpty())
|
||||||
return SendMessageError("Empty link", fullProcessedPath_from);
|
return callback.SendMessageError("Empty link", fullProcessedPath_from);
|
||||||
|
|
||||||
if (link.Is_HardLink() /* || link.IsCopyLink */)
|
if (link.Is_HardLink() /* || link.IsCopyLink */)
|
||||||
{
|
{
|
||||||
// if (link.isHardLink)
|
// if (link.isHardLink)
|
||||||
{
|
{
|
||||||
if (!MyCreateHardLink(fullProcessedPath_from, target))
|
RINOK(callback.DeleteLinkFileAlways_or_RemoveEmptyDir(fullProcessedPath_from, true)) // checkThatFileIsEmpty
|
||||||
return SendMessageError2_with_LastError(kCantCreateHardLink, fullProcessedPath_from, target);
|
{
|
||||||
|
// RINOK(SendMessageError_with_LastError(k_Cant_DeleteTempLinkFile, fullProcessedPath_from))
|
||||||
|
}
|
||||||
|
return callback.CreateHardLink2(fullProcessedPath_from, target, linkWasSet);
|
||||||
/*
|
/*
|
||||||
RINOK(PrepareOperation(NArchive::NExtract::NAskMode::kExtract))
|
RINOK(PrepareOperation(NArchive::NExtract::NAskMode::kExtract))
|
||||||
_op_WasReported = true;
|
_op_WasReported = true;
|
||||||
RINOK(SetOperationResult(NArchive::NExtract::NOperationResult::kOK))
|
RINOK(SetOperationResult(NArchive::NExtract::NOperationResult::kOK))
|
||||||
*/
|
|
||||||
linkWasSet = true;
|
linkWasSet = true;
|
||||||
return S_OK;
|
return S_OK;
|
||||||
|
*/
|
||||||
}
|
}
|
||||||
/*
|
/*
|
||||||
// IsCopyLink
|
// IsCopyLink
|
||||||
|
|
@ -2086,36 +2285,10 @@ HRESULT CArchiveExtractCallback::SetLink(
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
const bool isDir = (_item.IsDir || link.LinkType == k_LinkType_Junction);
|
const bool isDir = (postLink.item_IsDir || link.LinkType == k_LinkType_Junction);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if (!_ntOptions.SymLinks_AllowDangerous.Val && link.isRelative)
|
|
||||||
{
|
|
||||||
/*
|
|
||||||
We want to use additional check for links that can link to directory.
|
|
||||||
- linux: all symbolic links are files.
|
|
||||||
- windows: we can have file/directory symbolic link,
|
|
||||||
but file symbolic link works like directory link in windows.
|
|
||||||
So we use additional check for all relative links.
|
|
||||||
|
|
||||||
We don't allow decreasing of final level of link.
|
|
||||||
So if some another extracted file will use this link,
|
|
||||||
then number of real path parts (after link redirection) cannot be
|
|
||||||
smaller than number of requested path parts from archive records.
|
|
||||||
|
|
||||||
Now we check only (link.LinkPath) without (_item.PathParts).
|
|
||||||
*/
|
|
||||||
CLinkLevelsInfo levelsInfo;
|
|
||||||
levelsInfo.Parse(link.LinkPath, link.Is_WSL());
|
|
||||||
if (levelsInfo.FinalLevel < 1
|
|
||||||
// || levelsInfo.LowLevel < 0 // we allow negative temporary levels
|
|
||||||
|| levelsInfo.IsAbsolute)
|
|
||||||
return SendMessageError2(0, // errorCode
|
|
||||||
"Dangerous symbolic link path was ignored",
|
|
||||||
us2fs(_item.Path), us2fs(link.LinkPath));
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
CByteBuffer data;
|
CByteBuffer data;
|
||||||
// printf("\nFillLinkData(): %s\n", GetOemString(target).Ptr());
|
// printf("\nFillLinkData(): %s\n", GetOemString(target).Ptr());
|
||||||
|
|
@ -2127,7 +2300,7 @@ HRESULT CArchiveExtractCallback::SetLink(
|
||||||
else
|
else
|
||||||
FillLinkData_WinLink(data, fs2us(target), link.LinkType != k_LinkType_Junction);
|
FillLinkData_WinLink(data, fs2us(target), link.LinkType != k_LinkType_Junction);
|
||||||
if (data.Size() == 0)
|
if (data.Size() == 0)
|
||||||
return SendMessageError("Cannot fill link data", us2fs(_item.Path));
|
return callback.SendMessageError("Cannot fill link data", us2fs(postLink.item_Path));
|
||||||
/*
|
/*
|
||||||
if (NtReparse_Size != data.Size() || memcmp(NtReparse_Data, data, data.Size()) != 0)
|
if (NtReparse_Size != data.Size() || memcmp(NtReparse_Data, data, data.Size()) != 0)
|
||||||
SendMessageError("reconstructed Reparse is different", fs2us(target));
|
SendMessageError("reconstructed Reparse is different", fs2us(target));
|
||||||
|
|
@ -2136,14 +2309,18 @@ HRESULT CArchiveExtractCallback::SetLink(
|
||||||
// we check that reparse data is correct, but we ignore attr.MinorError.
|
// we check that reparse data is correct, but we ignore attr.MinorError.
|
||||||
CReparseAttr attr;
|
CReparseAttr attr;
|
||||||
if (!attr.Parse(data, data.Size()))
|
if (!attr.Parse(data, data.Size()))
|
||||||
return SendMessageError("Internal error for symbolic link file", us2fs(_item.Path));
|
return callback.SendMessageError("Internal error for symbolic link file", us2fs(postLink.item_Path));
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
RINOK(callback.DeleteLinkFileAlways_or_RemoveEmptyDir(fullProcessedPath_from, true)) // checkThatFileIsEmpty
|
||||||
|
#ifdef _WIN32
|
||||||
if (!NFile::NIO::SetReparseData(fullProcessedPath_from, isDir, data, (DWORD)data.Size()))
|
if (!NFile::NIO::SetReparseData(fullProcessedPath_from, isDir, data, (DWORD)data.Size()))
|
||||||
#else // ! _WIN32
|
#else // ! _WIN32
|
||||||
if (!NFile::NIO::SetSymLink(fullProcessedPath_from, target))
|
if (!NFile::NIO::SetSymLink(fullProcessedPath_from, target))
|
||||||
#endif // ! _WIN32
|
#endif // ! _WIN32
|
||||||
{
|
{
|
||||||
return SendMessageError_with_LastError(kCantCreateSymLink, fullProcessedPath_from);
|
return callback.SendMessageError_with_LastError(kCantCreateSymLink, fullProcessedPath_from);
|
||||||
}
|
}
|
||||||
linkWasSet = true;
|
linkWasSet = true;
|
||||||
return S_OK;
|
return S_OK;
|
||||||
|
|
@ -2392,6 +2569,7 @@ HRESULT CArchiveExtractCallback::CloseReparseAndFile()
|
||||||
_curSize_Defined = true;
|
_curSize_Defined = true;
|
||||||
if (needSetReparse)
|
if (needSetReparse)
|
||||||
{
|
{
|
||||||
|
// empty file was created so we must delete it.
|
||||||
// in Linux : we must delete empty file before symbolic link creation
|
// in Linux : we must delete empty file before symbolic link creation
|
||||||
// in Windows : we can create symbolic link even without file deleting
|
// in Windows : we can create symbolic link even without file deleting
|
||||||
if (!DeleteFileAlways(_diskFilePath))
|
if (!DeleteFileAlways(_diskFilePath))
|
||||||
|
|
@ -2404,9 +2582,12 @@ HRESULT CArchiveExtractCallback::CloseReparseAndFile()
|
||||||
// link.isJunction = true; // for debug
|
// link.isJunction = true; // for debug
|
||||||
link.Normalize_to_RelativeSafe(_removePathParts);
|
link.Normalize_to_RelativeSafe(_removePathParts);
|
||||||
RINOK(SetLink(_diskFilePath, link, linkWasSet))
|
RINOK(SetLink(_diskFilePath, link, linkWasSet))
|
||||||
|
/*
|
||||||
|
// we don't set attributes for placeholder.
|
||||||
if (linkWasSet)
|
if (linkWasSet)
|
||||||
_isSymLinkCreated = true; // link.IsSymLink();
|
_isSymLinkCreated = true; // link.IsSymLink();
|
||||||
else
|
else
|
||||||
|
*/
|
||||||
_needSetAttrib = false;
|
_needSetAttrib = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -2416,13 +2597,37 @@ HRESULT CArchiveExtractCallback::CloseReparseAndFile()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void CArchiveExtractCallback::SetAttrib()
|
static void SetAttrib_Base(const FString &path, const CProcessedFileInfo &fi,
|
||||||
|
const CArchiveExtractCallback &callback)
|
||||||
{
|
{
|
||||||
#ifndef _WIN32
|
#ifndef _WIN32
|
||||||
|
if (fi.Owner.Id_Defined &&
|
||||||
|
fi.Group.Id_Defined)
|
||||||
|
{
|
||||||
|
if (my_chown(path, fi.Owner.Id, fi.Group.Id) != 0)
|
||||||
|
callback.SendMessageError_with_LastError("Cannot set owner", path);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
if (fi.Attrib_Defined)
|
||||||
|
{
|
||||||
|
// const AString s = GetAnsiString(_diskFilePath);
|
||||||
|
// printf("\nSetFileAttrib_PosixHighDetect: %s: hex:%x\n", s.Ptr(), _fi.Attrib);
|
||||||
|
if (!SetFileAttrib_PosixHighDetect(path, fi.Attrib))
|
||||||
|
{
|
||||||
|
// do we need error message here in Windows and in posix?
|
||||||
|
callback.SendMessageError_with_LastError("Cannot set file attribute", path);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void CArchiveExtractCallback::SetAttrib() const
|
||||||
|
{
|
||||||
|
#ifndef _WIN32
|
||||||
// Linux now doesn't support permissions for symlinks
|
// Linux now doesn't support permissions for symlinks
|
||||||
if (_isSymLinkCreated)
|
if (_isSymLinkCreated)
|
||||||
return;
|
return;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if (_itemFailure
|
if (_itemFailure
|
||||||
|| _diskFilePath.IsEmpty()
|
|| _diskFilePath.IsEmpty()
|
||||||
|
|
@ -2430,31 +2635,41 @@ void CArchiveExtractCallback::SetAttrib()
|
||||||
|| !_extractMode)
|
|| !_extractMode)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
#ifndef _WIN32
|
SetAttrib_Base(_diskFilePath, _fi, *this);
|
||||||
if (_fi.Owner.Id_Defined &&
|
|
||||||
_fi.Group.Id_Defined)
|
|
||||||
{
|
|
||||||
if (my_chown(_diskFilePath, _fi.Owner.Id, _fi.Group.Id) != 0)
|
|
||||||
{
|
|
||||||
SendMessageError_with_LastError("Cannot set owner", _diskFilePath);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
if (_fi.Attrib_Defined)
|
|
||||||
{
|
|
||||||
// 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);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#ifdef Z7_USE_SECURITY_CODE
|
||||||
|
HRESULT CArchiveExtractCallback::SetSecurityInfo(UInt32 indexInArc, const FString &path) const
|
||||||
|
{
|
||||||
|
if (!_stdOutMode && _extractMode && _ntOptions.NtSecurity.Val && _arc->GetRawProps)
|
||||||
|
{
|
||||||
|
const void *data;
|
||||||
|
UInt32 dataSize;
|
||||||
|
UInt32 propType;
|
||||||
|
_arc->GetRawProps->GetRawProp(indexInArc, kpidNtSecure, &data, &dataSize, &propType);
|
||||||
|
if (dataSize != 0)
|
||||||
|
{
|
||||||
|
if (propType != NPropDataType::kRaw)
|
||||||
|
return E_FAIL;
|
||||||
|
if (CheckNtSecure((const Byte *)data, dataSize))
|
||||||
|
{
|
||||||
|
SECURITY_INFORMATION securInfo = DACL_SECURITY_INFORMATION | GROUP_SECURITY_INFORMATION | OWNER_SECURITY_INFORMATION;
|
||||||
|
if (_saclEnabled)
|
||||||
|
securInfo |= SACL_SECURITY_INFORMATION;
|
||||||
|
// if (!
|
||||||
|
::SetFileSecurityW(fs2us(path), securInfo, (PSECURITY_DESCRIPTOR)(void *)(const Byte *)(data));
|
||||||
|
{
|
||||||
|
// RINOK(SendMessageError_with_LastError("SetFileSecurity FAILS", path))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return S_OK;
|
||||||
|
}
|
||||||
|
#endif // Z7_USE_SECURITY_CODE
|
||||||
|
|
||||||
|
|
||||||
Z7_COM7F_IMF(CArchiveExtractCallback::SetOperationResult(Int32 opRes))
|
Z7_COM7F_IMF(CArchiveExtractCallback::SetOperationResult(Int32 opRes))
|
||||||
{
|
{
|
||||||
COM_TRY_BEGIN
|
COM_TRY_BEGIN
|
||||||
|
|
@ -2490,27 +2705,9 @@ Z7_COM7F_IMF(CArchiveExtractCallback::SetOperationResult(Int32 opRes))
|
||||||
|
|
||||||
RINOK(CloseReparseAndFile())
|
RINOK(CloseReparseAndFile())
|
||||||
|
|
||||||
#ifdef Z7_USE_SECURITY_CODE
|
#ifdef Z7_USE_SECURITY_CODE
|
||||||
if (!_stdOutMode && _extractMode && _ntOptions.NtSecurity.Val && _arc->GetRawProps)
|
RINOK(SetSecurityInfo(_index, _diskFilePath))
|
||||||
{
|
#endif
|
||||||
const void *data;
|
|
||||||
UInt32 dataSize;
|
|
||||||
UInt32 propType;
|
|
||||||
_arc->GetRawProps->GetRawProp(_index, kpidNtSecure, &data, &dataSize, &propType);
|
|
||||||
if (dataSize != 0)
|
|
||||||
{
|
|
||||||
if (propType != NPropDataType::kRaw)
|
|
||||||
return E_FAIL;
|
|
||||||
if (CheckNtSecure((const Byte *)data, dataSize))
|
|
||||||
{
|
|
||||||
SECURITY_INFORMATION securInfo = DACL_SECURITY_INFORMATION | GROUP_SECURITY_INFORMATION | OWNER_SECURITY_INFORMATION;
|
|
||||||
if (_saclEnabled)
|
|
||||||
securInfo |= SACL_SECURITY_INFORMATION;
|
|
||||||
::SetFileSecurityW(fs2us(_diskFilePath), securInfo, (PSECURITY_DESCRIPTOR)(void *)(const Byte *)(data));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#endif // Z7_USE_SECURITY_CODE
|
|
||||||
|
|
||||||
if (!_curSize_Defined)
|
if (!_curSize_Defined)
|
||||||
GetUnpackSize();
|
GetUnpackSize();
|
||||||
|
|
@ -2754,15 +2951,58 @@ void CDirPathSortPair::SetNumSlashes(const FChar *s)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
bool CDirPathTime::SetDirTime() const
|
bool CFiTimesCAM::SetDirTime_to_FS(CFSTR path) const
|
||||||
{
|
{
|
||||||
return NDir::SetDirTime(Path,
|
// it's same function for dir and for file
|
||||||
|
return NDir::SetDirTime(path,
|
||||||
CTime_Defined ? &CTime : NULL,
|
CTime_Defined ? &CTime : NULL,
|
||||||
ATime_Defined ? &ATime : NULL,
|
ATime_Defined ? &ATime : NULL,
|
||||||
MTime_Defined ? &MTime : NULL);
|
MTime_Defined ? &MTime : NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#ifdef SUPPORT_LINKS
|
||||||
|
|
||||||
|
bool CFiTimesCAM::SetLinkFileTime_to_FS(CFSTR path) const
|
||||||
|
{
|
||||||
|
// it's same function for dir and for file
|
||||||
|
return NDir::SetLinkFileTime(path,
|
||||||
|
CTime_Defined ? &CTime : NULL,
|
||||||
|
ATime_Defined ? &ATime : NULL,
|
||||||
|
MTime_Defined ? &MTime : NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
HRESULT CArchiveExtractCallback::SetPostLinks() const
|
||||||
|
{
|
||||||
|
FOR_VECTOR (i, _postLinks)
|
||||||
|
{
|
||||||
|
const CPostLink &link = _postLinks[i];
|
||||||
|
bool linkWasSet = false;
|
||||||
|
RINOK(SetLink2(*this, link, linkWasSet))
|
||||||
|
if (linkWasSet)
|
||||||
|
{
|
||||||
|
#ifdef _WIN32
|
||||||
|
// Linux now doesn't support permissions for symlinks
|
||||||
|
SetAttrib_Base(link.fullProcessedPath_from, link.item_FileInfo, *this);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
CFiTimesCAM pt;
|
||||||
|
GetFiTimesCAM(link.item_FileInfo, pt, *_arc);
|
||||||
|
if (pt.IsSomeTimeDefined())
|
||||||
|
pt.SetLinkFileTime_to_FS(link.fullProcessedPath_from);
|
||||||
|
|
||||||
|
#ifdef Z7_USE_SECURITY_CODE
|
||||||
|
// we set security information after timestamps setting
|
||||||
|
RINOK(SetSecurityInfo(link.Index_in_Arc, link.fullProcessedPath_from))
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return S_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
HRESULT CArchiveExtractCallback::SetDirsTimes()
|
HRESULT CArchiveExtractCallback::SetDirsTimes()
|
||||||
{
|
{
|
||||||
if (!_arc)
|
if (!_arc)
|
||||||
|
|
@ -2786,7 +3026,7 @@ HRESULT CArchiveExtractCallback::SetDirsTimes()
|
||||||
for (i = 0; i < pairs.Size(); i++)
|
for (i = 0; i < pairs.Size(); i++)
|
||||||
{
|
{
|
||||||
const CDirPathTime &dpt = _extractedFolders[pairs[i].Index];
|
const CDirPathTime &dpt = _extractedFolders[pairs[i].Index];
|
||||||
if (!dpt.SetDirTime())
|
if (!dpt.SetDirTime_to_FS_2())
|
||||||
{
|
{
|
||||||
// result = E_FAIL;
|
// result = E_FAIL;
|
||||||
// do we need error message here in Windows and in posix?
|
// do we need error message here in Windows and in posix?
|
||||||
|
|
@ -2818,10 +3058,20 @@ HRESULT CArchiveExtractCallback::SetDirsTimes()
|
||||||
|
|
||||||
HRESULT CArchiveExtractCallback::CloseArc()
|
HRESULT CArchiveExtractCallback::CloseArc()
|
||||||
{
|
{
|
||||||
|
// we call CloseReparseAndFile() here because we can have non-closed file in some cases?
|
||||||
HRESULT res = CloseReparseAndFile();
|
HRESULT res = CloseReparseAndFile();
|
||||||
const HRESULT res2 = SetDirsTimes();
|
#ifdef SUPPORT_LINKS
|
||||||
if (res == S_OK)
|
{
|
||||||
res = res2;
|
const HRESULT res2 = SetPostLinks();
|
||||||
|
if (res == S_OK)
|
||||||
|
res = res2;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
{
|
||||||
|
const HRESULT res2 = SetDirsTimes();
|
||||||
|
if (res == S_OK)
|
||||||
|
res = res2;
|
||||||
|
}
|
||||||
_arc = NULL;
|
_arc = NULL;
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -52,7 +52,6 @@ struct CExtractNtOptions
|
||||||
{
|
{
|
||||||
CBoolPair NtSecurity;
|
CBoolPair NtSecurity;
|
||||||
CBoolPair SymLinks;
|
CBoolPair SymLinks;
|
||||||
CBoolPair SymLinks_AllowDangerous;
|
|
||||||
CBoolPair HardLinks;
|
CBoolPair HardLinks;
|
||||||
CBoolPair AltStreams;
|
CBoolPair AltStreams;
|
||||||
bool ReplaceColonForAltStream;
|
bool ReplaceColonForAltStream;
|
||||||
|
|
@ -66,6 +65,8 @@ struct CExtractNtOptions
|
||||||
bool PreserveATime;
|
bool PreserveATime;
|
||||||
bool OpenShareForWrite;
|
bool OpenShareForWrite;
|
||||||
|
|
||||||
|
unsigned SymLinks_DangerousLevel;
|
||||||
|
|
||||||
UInt64 MemLimit;
|
UInt64 MemLimit;
|
||||||
|
|
||||||
CExtractNtOptions():
|
CExtractNtOptions():
|
||||||
|
|
@ -74,10 +75,10 @@ struct CExtractNtOptions
|
||||||
ExtractOwner(false),
|
ExtractOwner(false),
|
||||||
PreserveATime(false),
|
PreserveATime(false),
|
||||||
OpenShareForWrite(false),
|
OpenShareForWrite(false),
|
||||||
|
SymLinks_DangerousLevel(5),
|
||||||
MemLimit((UInt64)(Int64)-1)
|
MemLimit((UInt64)(Int64)-1)
|
||||||
{
|
{
|
||||||
SymLinks.Val = true;
|
SymLinks.Val = true;
|
||||||
SymLinks_AllowDangerous.Val = false;
|
|
||||||
HardLinks.Val = true;
|
HardLinks.Val = true;
|
||||||
AltStreams.Val = true;
|
AltStreams.Val = true;
|
||||||
|
|
||||||
|
|
@ -166,19 +167,22 @@ struct CFiTimesCAM
|
||||||
ATime_Defined |
|
ATime_Defined |
|
||||||
MTime_Defined;
|
MTime_Defined;
|
||||||
}
|
}
|
||||||
|
bool SetDirTime_to_FS(CFSTR path) const;
|
||||||
|
#ifdef SUPPORT_LINKS
|
||||||
|
bool SetLinkFileTime_to_FS(CFSTR path) const;
|
||||||
|
#endif
|
||||||
};
|
};
|
||||||
|
|
||||||
struct CDirPathTime: public CFiTimesCAM
|
struct CDirPathTime: public CFiTimesCAM
|
||||||
{
|
{
|
||||||
FString Path;
|
FString Path;
|
||||||
|
|
||||||
bool SetDirTime() const;
|
bool SetDirTime_to_FS_2() const { return SetDirTime_to_FS(Path); }
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
#ifdef SUPPORT_LINKS
|
#ifdef SUPPORT_LINKS
|
||||||
|
|
||||||
|
|
||||||
enum ELinkType
|
enum ELinkType
|
||||||
{
|
{
|
||||||
k_LinkType_HardLink,
|
k_LinkType_HardLink,
|
||||||
|
|
@ -227,6 +231,15 @@ private:
|
||||||
#endif // SUPPORT_LINKS
|
#endif // SUPPORT_LINKS
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
struct CProcessedFileInfo
|
||||||
|
{
|
||||||
|
CArcTime CTime;
|
||||||
|
CArcTime ATime;
|
||||||
|
CArcTime MTime;
|
||||||
|
UInt32 Attrib;
|
||||||
|
bool Attrib_Defined;
|
||||||
|
|
||||||
#ifndef _WIN32
|
#ifndef _WIN32
|
||||||
|
|
||||||
struct COwnerInfo
|
struct COwnerInfo
|
||||||
|
|
@ -243,8 +256,76 @@ struct COwnerInfo
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
COwnerInfo Owner;
|
||||||
|
COwnerInfo Group;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
void Clear()
|
||||||
|
{
|
||||||
|
#ifndef _WIN32
|
||||||
|
Attrib_Defined = false;
|
||||||
|
Owner.Clear();
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
bool IsReparse() const
|
||||||
|
{
|
||||||
|
return (Attrib_Defined && (Attrib & FILE_ATTRIBUTE_REPARSE_POINT) != 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool IsLinuxSymLink() const
|
||||||
|
{
|
||||||
|
return (Attrib_Defined && MY_LIN_S_ISLNK(Attrib >> 16));
|
||||||
|
}
|
||||||
|
|
||||||
|
void SetFromPosixAttrib(UInt32 a)
|
||||||
|
{
|
||||||
|
// here we set only part of combined attribute required by SetFileAttrib() call
|
||||||
|
#ifdef _WIN32
|
||||||
|
// Windows sets FILE_ATTRIBUTE_NORMAL, if we try to set 0 as attribute.
|
||||||
|
Attrib = MY_LIN_S_ISDIR(a) ?
|
||||||
|
FILE_ATTRIBUTE_DIRECTORY :
|
||||||
|
FILE_ATTRIBUTE_ARCHIVE;
|
||||||
|
if ((a & 0222) == 0) // (& S_IWUSR) in p7zip
|
||||||
|
Attrib |= FILE_ATTRIBUTE_READONLY;
|
||||||
|
// 22.00 : we need type bits for (MY_LIN_S_IFLNK) for IsLinuxSymLink()
|
||||||
|
a &= MY_LIN_S_IFMT;
|
||||||
|
if (a == MY_LIN_S_IFLNK)
|
||||||
|
Attrib |= (a << 16);
|
||||||
|
#else
|
||||||
|
Attrib = (a << 16) | FILE_ATTRIBUTE_UNIX_EXTENSION;
|
||||||
|
#endif
|
||||||
|
Attrib_Defined = true;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
#ifdef SUPPORT_LINKS
|
||||||
|
|
||||||
|
struct CPostLink
|
||||||
|
{
|
||||||
|
UInt32 Index_in_Arc;
|
||||||
|
bool item_IsDir; // _item.IsDir
|
||||||
|
UString item_Path; // _item.Path;
|
||||||
|
UStringVector item_PathParts; // _item.PathParts;
|
||||||
|
CProcessedFileInfo item_FileInfo; // _fi
|
||||||
|
FString fullProcessedPath_from; // full file path in FS
|
||||||
|
CLinkInfo LinkInfo;
|
||||||
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
struct CPostLinks
|
||||||
|
{
|
||||||
|
void Clear()
|
||||||
|
{
|
||||||
|
Links.Clear();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
*/
|
||||||
|
|
||||||
|
#endif // SUPPORT_LINKS
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
class CArchiveExtractCallback Z7_final:
|
class CArchiveExtractCallback Z7_final:
|
||||||
public IArchiveExtractCallback,
|
public IArchiveExtractCallback,
|
||||||
|
|
@ -292,8 +373,9 @@ public:
|
||||||
private:
|
private:
|
||||||
|
|
||||||
const CArc *_arc;
|
const CArc *_arc;
|
||||||
|
public:
|
||||||
CExtractNtOptions _ntOptions;
|
CExtractNtOptions _ntOptions;
|
||||||
|
private:
|
||||||
bool _encrypted;
|
bool _encrypted;
|
||||||
bool _isSplit;
|
bool _isSplit;
|
||||||
bool _curSize_Defined;
|
bool _curSize_Defined;
|
||||||
|
|
@ -325,7 +407,9 @@ private:
|
||||||
CMyComPtr<ICryptoGetTextPassword> _cryptoGetTextPassword;
|
CMyComPtr<ICryptoGetTextPassword> _cryptoGetTextPassword;
|
||||||
|
|
||||||
FString _dirPathPrefix;
|
FString _dirPathPrefix;
|
||||||
|
public:
|
||||||
FString _dirPathPrefix_Full;
|
FString _dirPathPrefix_Full;
|
||||||
|
private:
|
||||||
|
|
||||||
#ifndef Z7_SFX
|
#ifndef Z7_SFX
|
||||||
|
|
||||||
|
|
@ -337,49 +421,7 @@ private:
|
||||||
CReadArcItem _item;
|
CReadArcItem _item;
|
||||||
FString _diskFilePath;
|
FString _diskFilePath;
|
||||||
|
|
||||||
struct CProcessedFileInfo
|
CProcessedFileInfo _fi;
|
||||||
{
|
|
||||||
CArcTime CTime;
|
|
||||||
CArcTime ATime;
|
|
||||||
CArcTime MTime;
|
|
||||||
UInt32 Attrib;
|
|
||||||
bool Attrib_Defined;
|
|
||||||
|
|
||||||
#ifndef _WIN32
|
|
||||||
COwnerInfo Owner;
|
|
||||||
COwnerInfo Group;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
bool IsReparse() const
|
|
||||||
{
|
|
||||||
return (Attrib_Defined && (Attrib & FILE_ATTRIBUTE_REPARSE_POINT) != 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool IsLinuxSymLink() const
|
|
||||||
{
|
|
||||||
return (Attrib_Defined && MY_LIN_S_ISLNK(Attrib >> 16));
|
|
||||||
}
|
|
||||||
|
|
||||||
void SetFromPosixAttrib(UInt32 a)
|
|
||||||
{
|
|
||||||
// here we set only part of combined attribute required by SetFileAttrib() call
|
|
||||||
#ifdef _WIN32
|
|
||||||
// Windows sets FILE_ATTRIBUTE_NORMAL, if we try to set 0 as attribute.
|
|
||||||
Attrib = MY_LIN_S_ISDIR(a) ?
|
|
||||||
FILE_ATTRIBUTE_DIRECTORY :
|
|
||||||
FILE_ATTRIBUTE_ARCHIVE;
|
|
||||||
if ((a & 0222) == 0) // (& S_IWUSR) in p7zip
|
|
||||||
Attrib |= FILE_ATTRIBUTE_READONLY;
|
|
||||||
// 22.00 : we need type bits for (MY_LIN_S_IFLNK) for IsLinuxSymLink()
|
|
||||||
a &= MY_LIN_S_IFMT;
|
|
||||||
if (a == MY_LIN_S_IFLNK)
|
|
||||||
Attrib |= (a << 16);
|
|
||||||
#else
|
|
||||||
Attrib = (a << 16) | FILE_ATTRIBUTE_UNIX_EXTENSION;
|
|
||||||
#endif
|
|
||||||
Attrib_Defined = true;
|
|
||||||
}
|
|
||||||
} _fi;
|
|
||||||
|
|
||||||
UInt64 _position;
|
UInt64 _position;
|
||||||
UInt64 _curSize;
|
UInt64 _curSize;
|
||||||
|
|
@ -421,20 +463,21 @@ private:
|
||||||
// CObjectVector<NWindows::NFile::NDir::CDelayedSymLink> _delayedSymLinks;
|
// CObjectVector<NWindows::NFile::NDir::CDelayedSymLink> _delayedSymLinks;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
void CreateComplexDirectory(const UStringVector &dirPathParts, FString &fullPath);
|
void CreateComplexDirectory(
|
||||||
|
const UStringVector &dirPathParts, bool isFinal, FString &fullPath);
|
||||||
HRESULT GetTime(UInt32 index, PROPID propID, CArcTime &ft);
|
HRESULT GetTime(UInt32 index, PROPID propID, CArcTime &ft);
|
||||||
HRESULT GetUnpackSize();
|
HRESULT GetUnpackSize();
|
||||||
|
|
||||||
FString Hash_GetFullFilePath();
|
FString Hash_GetFullFilePath();
|
||||||
|
|
||||||
void SetAttrib();
|
void SetAttrib() const;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
HRESULT SendMessageError(const char *message, const FString &path);
|
HRESULT SendMessageError(const char *message, const FString &path) const;
|
||||||
HRESULT SendMessageError_with_Error(HRESULT errorCode, const char *message, const FString &path);
|
HRESULT SendMessageError_with_Error(HRESULT errorCode, const char *message, const FString &path) const;
|
||||||
HRESULT SendMessageError_with_LastError(const char *message, const FString &path);
|
HRESULT SendMessageError_with_LastError(const char *message, const FString &path) const;
|
||||||
HRESULT SendMessageError2(HRESULT errorCode, const char *message, const FString &path1, const FString &path2);
|
HRESULT SendMessageError2(HRESULT errorCode, const char *message, const FString &path1, const FString &path2) const;
|
||||||
HRESULT SendMessageError2_with_LastError(const char *message, const FString &path1, const FString &path2);
|
HRESULT SendMessageError2_with_LastError(const char *message, const FString &path1, const FString &path2) const;
|
||||||
|
|
||||||
#if defined(_WIN32) && !defined(UNDER_CE) && !defined(Z7_SFX)
|
#if defined(_WIN32) && !defined(UNDER_CE) && !defined(Z7_SFX)
|
||||||
NExtract::NZoneIdMode::EEnum ZoneMode;
|
NExtract::NZoneIdMode::EEnum ZoneMode;
|
||||||
|
|
@ -497,10 +540,11 @@ public:
|
||||||
UInt64 packSize);
|
UInt64 packSize);
|
||||||
|
|
||||||
|
|
||||||
#ifdef SUPPORT_LINKS
|
#ifdef SUPPORT_LINKS
|
||||||
|
|
||||||
private:
|
private:
|
||||||
CHardLinks _hardLinks;
|
CHardLinks _hardLinks;
|
||||||
|
CObjectVector<CPostLink> _postLinks;
|
||||||
CLinkInfo _link;
|
CLinkInfo _link;
|
||||||
// const void *NtReparse_Data;
|
// const void *NtReparse_Data;
|
||||||
// UInt32 NtReparse_Size;
|
// UInt32 NtReparse_Size;
|
||||||
|
|
@ -512,13 +556,16 @@ private:
|
||||||
const FString &fullProcessedPath_from,
|
const FString &fullProcessedPath_from,
|
||||||
const CLinkInfo &linkInfo,
|
const CLinkInfo &linkInfo,
|
||||||
bool &linkWasSet);
|
bool &linkWasSet);
|
||||||
|
HRESULT SetPostLinks() const;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
// call PrepareHardLinks() after Init()
|
HRESULT CreateHardLink2(const FString &newFilePath,
|
||||||
|
const FString &existFilePath, bool &link_was_Created) const;
|
||||||
|
HRESULT DeleteLinkFileAlways_or_RemoveEmptyDir(const FString &path, bool checkThatFileIsEmpty) const;
|
||||||
HRESULT PrepareHardLinks(const CRecordVector<UInt32> *realIndices); // NULL means all items
|
HRESULT PrepareHardLinks(const CRecordVector<UInt32> *realIndices); // NULL means all items
|
||||||
|
#endif
|
||||||
|
|
||||||
#endif
|
private:
|
||||||
|
|
||||||
|
|
||||||
#ifdef SUPPORT_ALT_STREAMS
|
#ifdef SUPPORT_ALT_STREAMS
|
||||||
CObjectVector<CIndexToPathPair> _renamedFiles;
|
CObjectVector<CIndexToPathPair> _renamedFiles;
|
||||||
|
|
@ -526,6 +573,7 @@ public:
|
||||||
|
|
||||||
// call it after Init()
|
// call it after Init()
|
||||||
|
|
||||||
|
public:
|
||||||
#ifndef Z7_SFX
|
#ifndef Z7_SFX
|
||||||
void SetBaseParentFolderIndex(UInt32 indexInArc)
|
void SetBaseParentFolderIndex(UInt32 indexInArc)
|
||||||
{
|
{
|
||||||
|
|
@ -547,7 +595,6 @@ private:
|
||||||
|
|
||||||
HRESULT Read_fi_Props();
|
HRESULT Read_fi_Props();
|
||||||
void CorrectPathParts();
|
void CorrectPathParts();
|
||||||
void GetFiTimesCAM(CFiTimesCAM &pt);
|
|
||||||
void CreateFolders();
|
void CreateFolders();
|
||||||
|
|
||||||
HRESULT CheckExistFile(FString &fullProcessedPath, bool &needExit);
|
HRESULT CheckExistFile(FString &fullProcessedPath, bool &needExit);
|
||||||
|
|
@ -556,8 +603,8 @@ private:
|
||||||
|
|
||||||
HRESULT CloseFile();
|
HRESULT CloseFile();
|
||||||
HRESULT CloseReparseAndFile();
|
HRESULT CloseReparseAndFile();
|
||||||
HRESULT CloseReparseAndFile2();
|
|
||||||
HRESULT SetDirsTimes();
|
HRESULT SetDirsTimes();
|
||||||
|
HRESULT SetSecurityInfo(UInt32 indexInArc, const FString &path) const;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -124,7 +124,7 @@ bool GetSystemDir(FString &path)
|
||||||
#endif // UNDER_CE
|
#endif // UNDER_CE
|
||||||
|
|
||||||
|
|
||||||
bool SetDirTime(CFSTR path, const CFiTime *cTime, const CFiTime *aTime, const CFiTime *mTime)
|
static bool SetFileTime_Base(CFSTR path, const CFiTime *cTime, const CFiTime *aTime, const CFiTime *mTime, DWORD dwFlagsAndAttributes)
|
||||||
{
|
{
|
||||||
#ifndef _UNICODE
|
#ifndef _UNICODE
|
||||||
if (!g_IsNT)
|
if (!g_IsNT)
|
||||||
|
|
@ -137,14 +137,14 @@ bool SetDirTime(CFSTR path, const CFiTime *cTime, const CFiTime *aTime, const CF
|
||||||
HANDLE hDir = INVALID_HANDLE_VALUE;
|
HANDLE hDir = INVALID_HANDLE_VALUE;
|
||||||
IF_USE_MAIN_PATH
|
IF_USE_MAIN_PATH
|
||||||
hDir = ::CreateFileW(fs2us(path), GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE,
|
hDir = ::CreateFileW(fs2us(path), GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE,
|
||||||
NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, NULL);
|
NULL, OPEN_EXISTING, dwFlagsAndAttributes, NULL);
|
||||||
#ifdef Z7_LONG_PATH
|
#ifdef Z7_LONG_PATH
|
||||||
if (hDir == INVALID_HANDLE_VALUE && USE_SUPER_PATH)
|
if (hDir == INVALID_HANDLE_VALUE && USE_SUPER_PATH)
|
||||||
{
|
{
|
||||||
UString superPath;
|
UString superPath;
|
||||||
if (GetSuperPath(path, superPath, USE_MAIN_PATH))
|
if (GetSuperPath(path, superPath, USE_MAIN_PATH))
|
||||||
hDir = ::CreateFileW(superPath, GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE,
|
hDir = ::CreateFileW(superPath, GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE,
|
||||||
NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, NULL);
|
NULL, OPEN_EXISTING, dwFlagsAndAttributes, NULL);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
@ -157,6 +157,15 @@ bool SetDirTime(CFSTR path, const CFiTime *cTime, const CFiTime *aTime, const CF
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool SetDirTime(CFSTR path, const CFiTime *cTime, const CFiTime *aTime, const CFiTime *mTime)
|
||||||
|
{
|
||||||
|
return SetFileTime_Base(path, cTime, aTime, mTime, FILE_FLAG_BACKUP_SEMANTICS);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool SetLinkFileTime(CFSTR path, const CFiTime *cTime, const CFiTime *aTime, const CFiTime *mTime)
|
||||||
|
{
|
||||||
|
return SetFileTime_Base(path, cTime, aTime, mTime, FILE_FLAG_BACKUP_SEMANTICS | FILE_FLAG_OPEN_REPARSE_POINT);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
bool SetFileAttrib(CFSTR path, DWORD attrib)
|
bool SetFileAttrib(CFSTR path, DWORD attrib)
|
||||||
|
|
@ -1173,17 +1182,15 @@ bool GetCurrentDir(FString &path)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
bool SetDirTime(CFSTR path, const CFiTime *cTime, const CFiTime *aTime, const CFiTime *mTime)
|
static bool SetFileTime_Base(CFSTR path, const CFiTime *cTime, const CFiTime *aTime, const CFiTime *mTime, const int flags)
|
||||||
{
|
{
|
||||||
// need testing
|
// need testing
|
||||||
/*
|
/*
|
||||||
struct utimbuf buf;
|
struct utimbuf buf;
|
||||||
struct stat st;
|
struct stat st;
|
||||||
UNUSED_VAR(cTime)
|
UNUSED_VAR(cTime)
|
||||||
|
|
||||||
printf("\nstat = %s\n", path);
|
printf("\nstat = %s\n", path);
|
||||||
int ret = stat(path, &st);
|
int ret = stat(path, &st);
|
||||||
|
|
||||||
if (ret == 0)
|
if (ret == 0)
|
||||||
{
|
{
|
||||||
buf.actime = st.st_atime;
|
buf.actime = st.st_atime;
|
||||||
|
|
@ -1195,47 +1202,42 @@ bool SetDirTime(CFSTR path, const CFiTime *cTime, const CFiTime *aTime, const CF
|
||||||
buf.actime = cur_time;
|
buf.actime = cur_time;
|
||||||
buf.modtime = cur_time;
|
buf.modtime = cur_time;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (aTime)
|
if (aTime)
|
||||||
{
|
{
|
||||||
UInt32 ut;
|
UInt32 ut;
|
||||||
if (NTime::FileTimeToUnixTime(*aTime, ut))
|
if (NTime::FileTimeToUnixTime(*aTime, ut))
|
||||||
buf.actime = ut;
|
buf.actime = ut;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (mTime)
|
if (mTime)
|
||||||
{
|
{
|
||||||
UInt32 ut;
|
UInt32 ut;
|
||||||
if (NTime::FileTimeToUnixTime(*mTime, ut))
|
if (NTime::FileTimeToUnixTime(*mTime, ut))
|
||||||
buf.modtime = ut;
|
buf.modtime = ut;
|
||||||
}
|
}
|
||||||
|
|
||||||
return utime(path, &buf) == 0;
|
return utime(path, &buf) == 0;
|
||||||
*/
|
*/
|
||||||
|
|
||||||
// if (!aTime && !mTime) return true;
|
// if (!aTime && !mTime) return true;
|
||||||
|
|
||||||
struct timespec times[2];
|
struct timespec times[2];
|
||||||
UNUSED_VAR(cTime)
|
UNUSED_VAR(cTime)
|
||||||
|
|
||||||
bool needChange;
|
bool needChange;
|
||||||
needChange = FiTime_To_timespec(aTime, times[0]);
|
needChange = FiTime_To_timespec(aTime, times[0]);
|
||||||
needChange |= FiTime_To_timespec(mTime, times[1]);
|
needChange |= FiTime_To_timespec(mTime, times[1]);
|
||||||
|
// if (mTime) { printf("\n time = %ld.%9ld\n", mTime->tv_sec, mTime->tv_nsec); }
|
||||||
/*
|
|
||||||
if (mTime)
|
|
||||||
{
|
|
||||||
printf("\n time = %ld.%9ld\n", mTime->tv_sec, mTime->tv_nsec);
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
|
|
||||||
if (!needChange)
|
if (!needChange)
|
||||||
return true;
|
return true;
|
||||||
const int flags = 0; // follow link
|
|
||||||
// = AT_SYMLINK_NOFOLLOW; // don't follow link
|
|
||||||
return utimensat(AT_FDCWD, path, times, flags) == 0;
|
return utimensat(AT_FDCWD, path, times, flags) == 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool SetDirTime(CFSTR path, const CFiTime *cTime, const CFiTime *aTime, const CFiTime *mTime)
|
||||||
|
{
|
||||||
|
return SetFileTime_Base(path, cTime, aTime, mTime, 0); // (flags = 0) means follow_link
|
||||||
|
}
|
||||||
|
|
||||||
|
bool SetLinkFileTime(CFSTR path, const CFiTime *cTime, const CFiTime *aTime, const CFiTime *mTime)
|
||||||
|
{
|
||||||
|
return SetFileTime_Base(path, cTime, aTime, mTime, AT_SYMLINK_NOFOLLOW);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
struct C_umask
|
struct C_umask
|
||||||
|
|
|
||||||
|
|
@ -18,9 +18,20 @@ bool GetSystemDir(FString &path);
|
||||||
WIN32 API : SetFileTime() doesn't allow to set zero timestamps in file
|
WIN32 API : SetFileTime() doesn't allow to set zero timestamps in file
|
||||||
but linux : allows unix time = 0 in filesystem
|
but linux : allows unix time = 0 in filesystem
|
||||||
*/
|
*/
|
||||||
|
/*
|
||||||
|
SetDirTime() can be used to set time for file or for dir.
|
||||||
|
If path is symbolic link, SetDirTime() will follow symbolic link,
|
||||||
|
and it will set timestamps of symbolic link's target file or dir.
|
||||||
|
*/
|
||||||
bool SetDirTime(CFSTR path, const CFiTime *cTime, const CFiTime *aTime, const CFiTime *mTime);
|
bool SetDirTime(CFSTR path, const CFiTime *cTime, const CFiTime *aTime, const CFiTime *mTime);
|
||||||
|
|
||||||
|
/*
|
||||||
|
SetLinkFileTime() doesn't follow symbolic link,
|
||||||
|
and it sets timestamps for symbolic link file itself.
|
||||||
|
If (path) is not symbolic link, it still can work (at least in some new OS versions).
|
||||||
|
*/
|
||||||
|
bool SetLinkFileTime(CFSTR path, const CFiTime *cTime, const CFiTime *aTime, const CFiTime *mTime);
|
||||||
|
|
||||||
|
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
<?xml version="1.0"?>
|
<?xml version="1.0"?>
|
||||||
|
|
||||||
<?define VerMajor = "25" ?>
|
<?define VerMajor = "25" ?>
|
||||||
<?define VerMinor = "00" ?>
|
<?define VerMinor = "01" ?>
|
||||||
<?define VerBuild = "00" ?>
|
<?define VerBuild = "00" ?>
|
||||||
<?define MmVer = "$(var.VerMajor).$(var.VerMinor)" ?>
|
<?define MmVer = "$(var.VerMajor).$(var.VerMinor)" ?>
|
||||||
<?define MmHex = "$(var.VerMajor)$(var.VerMinor)" ?>
|
<?define MmHex = "$(var.VerMajor)$(var.VerMinor)" ?>
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
7-Zip 25.00 Sources
|
7-Zip 25.01 Sources
|
||||||
-------------------
|
-------------------
|
||||||
|
|
||||||
7-Zip is a file archiver for Windows.
|
7-Zip is a file archiver for Windows.
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,14 @@
|
||||||
HISTORY of the 7-Zip source code
|
HISTORY of the 7-Zip source code
|
||||||
--------------------------------
|
--------------------------------
|
||||||
|
|
||||||
|
25.01 2025-08-03
|
||||||
|
-------------------------
|
||||||
|
- The code for handling symbolic links has been changed
|
||||||
|
to provide greater security when extracting files from archives.
|
||||||
|
Command line switch -snld20 can be used to bypass default security
|
||||||
|
checks when creating symbolic links.
|
||||||
|
|
||||||
|
|
||||||
25.00 2025-07-05
|
25.00 2025-07-05
|
||||||
-------------------------
|
-------------------------
|
||||||
- 7-Zip for Windows can now use more than 64 CPU threads for compression
|
- 7-Zip for Windows can now use more than 64 CPU threads for compression
|
||||||
|
|
@ -11,6 +19,8 @@ HISTORY of the 7-Zip source code
|
||||||
- deflate (zip/gz) compression speed was increased by 1-3%.
|
- deflate (zip/gz) compression speed was increased by 1-3%.
|
||||||
- improved support for zip, cpio and fat archives.
|
- improved support for zip, cpio and fat archives.
|
||||||
- fixed some bugs and vulnerabilities.
|
- fixed some bugs and vulnerabilities.
|
||||||
|
- the bug was fixed : CVE-2025-53816 : 7-Zip could work incorrectly for some incorrect RAR archives.
|
||||||
|
- the bug was fixed : CVE-2025-53817 : 7-Zip could crash for some incorrect COM (Compound File) archives.
|
||||||
|
|
||||||
|
|
||||||
24.09 2024-11-29
|
24.09 2024-11-29
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue