diff options
Diffstat (limited to 'CPP/7zip/UI/Common')
-rw-r--r-- | CPP/7zip/UI/Common/ArchiveCommandLine.cpp | 80 | ||||
-rw-r--r-- | CPP/7zip/UI/Common/ArchiveExtractCallback.cpp | 1260 | ||||
-rw-r--r-- | CPP/7zip/UI/Common/ArchiveExtractCallback.h | 328 | ||||
-rw-r--r-- | CPP/7zip/UI/Common/Bench.cpp | 135 | ||||
-rw-r--r-- | CPP/7zip/UI/Common/EnumDirItems.cpp | 59 | ||||
-rw-r--r-- | CPP/7zip/UI/Common/Extract.cpp | 2 | ||||
-rw-r--r-- | CPP/7zip/UI/Common/ExtractingFilePath.cpp | 2 | ||||
-rw-r--r-- | CPP/7zip/UI/Common/HashCalc.cpp | 325 | ||||
-rw-r--r-- | CPP/7zip/UI/Common/HashCalc.h | 21 | ||||
-rw-r--r-- | CPP/7zip/UI/Common/LoadCodecs.cpp | 6 | ||||
-rw-r--r-- | CPP/7zip/UI/Common/TempFiles.cpp | 3 | ||||
-rw-r--r-- | CPP/7zip/UI/Common/TempFiles.h | 3 | ||||
-rw-r--r-- | CPP/7zip/UI/Common/Update.cpp | 72 | ||||
-rw-r--r-- | CPP/7zip/UI/Common/Update.h | 7 | ||||
-rw-r--r-- | CPP/7zip/UI/Common/UpdateCallback.cpp | 110 | ||||
-rw-r--r-- | CPP/7zip/UI/Common/WorkDir.cpp | 16 | ||||
-rw-r--r-- | CPP/7zip/UI/Common/WorkDir.h | 8 | ||||
-rw-r--r-- | CPP/7zip/UI/Common/ZipRegistry.cpp | 37 |
18 files changed, 1617 insertions, 857 deletions
diff --git a/CPP/7zip/UI/Common/ArchiveCommandLine.cpp b/CPP/7zip/UI/Common/ArchiveCommandLine.cpp index 556b25a..7fe18fb 100644 --- a/CPP/7zip/UI/Common/ArchiveCommandLine.cpp +++ b/CPP/7zip/UI/Common/ArchiveCommandLine.cpp | |||
@@ -63,17 +63,46 @@ EXTERN_C_END | |||
63 | 63 | ||
64 | #else | 64 | #else |
65 | 65 | ||
66 | // #define MY_isatty_fileno(x) (isatty(fileno(x))) | 66 | static bool MY_IS_TERMINAL(FILE *x) |
67 | // #define MY_IS_TERMINAL(x) (MY_isatty_fileno(x) != 0); | ||
68 | static inline bool MY_IS_TERMINAL(FILE *x) | ||
69 | { | 67 | { |
70 | return ( | 68 | #ifdef _WIN32 |
71 | #if defined(_MSC_VER) && (_MSC_VER >= 1400) | 69 | /* |
72 | _isatty(_fileno(x)) | 70 | crt/stdio.h: |
73 | #else | 71 | typedef struct _iobuf FILE; |
74 | isatty(fileno(x)) | 72 | #define stdin (&_iob[0]) |
75 | #endif | 73 | #define stdout (&_iob[1]) |
76 | != 0); | 74 | #define stderr (&_iob[2]) |
75 | */ | ||
76 | // fprintf(stderr, "\nMY_IS_TERMINAL = %p", x); | ||
77 | const int fd = _fileno(x); | ||
78 | /* (fd) is 0, 1 or 2 in console program. | ||
79 | docs: If stdout or stderr is not associated with | ||
80 | an output stream (for example, in a Windows application | ||
81 | without a console window), the file descriptor returned is -2. | ||
82 | In previous versions, the file descriptor returned was -1. | ||
83 | */ | ||
84 | if (fd < 0) // is not associated with an output stream application (without a console window) | ||
85 | return false; | ||
86 | // fprintf(stderr, "\n\nstderr _fileno(%p) = %d", x, fd); | ||
87 | if (!_isatty(fd)) | ||
88 | return false; | ||
89 | // fprintf(stderr, "\nisatty_val = true"); | ||
90 | const HANDLE h = (HANDLE)_get_osfhandle(fd); | ||
91 | /* _get_osfhandle() returns intptr_t in new SDK, or long in MSVC6. | ||
92 | Also it can return (INVALID_HANDLE_VALUE). | ||
93 | docs: _get_osfhandle also returns the special value -2 when | ||
94 | the file descriptor is not associated with a stream | ||
95 | in old msvcrt.dll: it returns (-1) for incorrect value | ||
96 | */ | ||
97 | // fprintf(stderr, "\n_get_osfhandle() = %p", (void *)h); | ||
98 | if (h == NULL || h == INVALID_HANDLE_VALUE) | ||
99 | return false; | ||
100 | DWORD st; | ||
101 | // fprintf(stderr, "\nGetConsoleMode() = %u", (unsigned)GetConsoleMode(h, &st)); | ||
102 | return GetConsoleMode(h, &st) != 0; | ||
103 | #else | ||
104 | return isatty(fileno(x)) != 0; | ||
105 | #endif | ||
77 | } | 106 | } |
78 | 107 | ||
79 | #endif | 108 | #endif |
@@ -312,7 +341,7 @@ static const CSwitchForm kSwitchForms[] = | |||
312 | { "spf", SWFRM_STRING_SINGL(0) }, | 341 | { "spf", SWFRM_STRING_SINGL(0) }, |
313 | 342 | ||
314 | { "snh", SWFRM_MINUS }, | 343 | { "snh", SWFRM_MINUS }, |
315 | { "snld", SWFRM_MINUS }, | 344 | { "snld", SWFRM_STRING }, |
316 | { "snl", SWFRM_MINUS }, | 345 | { "snl", SWFRM_MINUS }, |
317 | { "sni", SWFRM_SIMPLE }, | 346 | { "sni", SWFRM_SIMPLE }, |
318 | 347 | ||
@@ -1088,7 +1117,7 @@ void CArcCmdLineParser::Parse1(const UStringVector &commandStrings, | |||
1088 | const UString &s = parser[NKey::kLargePages].PostStrings[0]; | 1117 | const UString &s = parser[NKey::kLargePages].PostStrings[0]; |
1089 | if (s.IsEmpty()) | 1118 | if (s.IsEmpty()) |
1090 | slp = 1; | 1119 | slp = 1; |
1091 | else if (s != L"-") | 1120 | else if (!s.IsEqualTo("-")) |
1092 | { | 1121 | { |
1093 | if (!StringToUInt32(s, slp)) | 1122 | if (!StringToUInt32(s, slp)) |
1094 | throw CArcCmdLineException("Unsupported switch postfix for -slp", s); | 1123 | throw CArcCmdLineException("Unsupported switch postfix for -slp", s); |
@@ -1338,7 +1367,7 @@ void CArcCmdLineParser::Parse2(CArcCmdLineOptions &options) | |||
1338 | const UString &s = parser[NKey::kFullPathMode].PostStrings[0]; | 1367 | const UString &s = parser[NKey::kFullPathMode].PostStrings[0]; |
1339 | if (!s.IsEmpty()) | 1368 | if (!s.IsEmpty()) |
1340 | { | 1369 | { |
1341 | if (s == L"2") | 1370 | if (s.IsEqualTo("2")) |
1342 | censorPathMode = NWildcard::k_FullPath; | 1371 | censorPathMode = NWildcard::k_FullPath; |
1343 | else | 1372 | else |
1344 | throw CArcCmdLineException("Unsupported -spf:", s); | 1373 | throw CArcCmdLineException("Unsupported -spf:", s); |
@@ -1400,6 +1429,7 @@ void CArcCmdLineParser::Parse2(CArcCmdLineOptions &options) | |||
1400 | const bool isExtractGroupCommand = options.Command.IsFromExtractGroup(); | 1429 | const bool isExtractGroupCommand = options.Command.IsFromExtractGroup(); |
1401 | const bool isExtractOrList = isExtractGroupCommand || options.Command.CommandType == NCommandType::kList; | 1430 | const bool isExtractOrList = isExtractGroupCommand || options.Command.CommandType == NCommandType::kList; |
1402 | const bool isRename = options.Command.CommandType == NCommandType::kRename; | 1431 | const bool isRename = options.Command.CommandType == NCommandType::kRename; |
1432 | options.UpdateOptions.RenameMode = isRename; | ||
1403 | 1433 | ||
1404 | if ((isExtractOrList || isRename) && options.StdInMode) | 1434 | if ((isExtractOrList || isRename) && options.StdInMode) |
1405 | thereIsArchiveName = false; | 1435 | thereIsArchiveName = false; |
@@ -1449,14 +1479,8 @@ void CArcCmdLineParser::Parse2(CArcCmdLineOptions &options) | |||
1449 | 1479 | ||
1450 | SetBoolPair(parser, NKey::kStoreOwnerId, options.StoreOwnerId); | 1480 | SetBoolPair(parser, NKey::kStoreOwnerId, options.StoreOwnerId); |
1451 | SetBoolPair(parser, NKey::kStoreOwnerName, options.StoreOwnerName); | 1481 | SetBoolPair(parser, NKey::kStoreOwnerName, options.StoreOwnerName); |
1452 | |||
1453 | CBoolPair symLinks_AllowDangerous; | ||
1454 | SetBoolPair(parser, NKey::kSymLinks_AllowDangerous, symLinks_AllowDangerous); | ||
1455 | |||
1456 | |||
1457 | /* | 1482 | /* |
1458 | bool supportSymLink = options.SymLinks.Val; | 1483 | bool supportSymLink = options.SymLinks.Val; |
1459 | |||
1460 | if (!options.SymLinks.Def) | 1484 | if (!options.SymLinks.Def) |
1461 | { | 1485 | { |
1462 | if (isExtractOrList) | 1486 | if (isExtractOrList) |
@@ -1464,7 +1488,6 @@ void CArcCmdLineParser::Parse2(CArcCmdLineOptions &options) | |||
1464 | else | 1488 | else |
1465 | supportSymLink = false; | 1489 | supportSymLink = false; |
1466 | } | 1490 | } |
1467 | |||
1468 | #ifdef ENV_HAVE_LSTAT | 1491 | #ifdef ENV_HAVE_LSTAT |
1469 | if (supportSymLink) | 1492 | if (supportSymLink) |
1470 | global_use_lstat = 1; | 1493 | global_use_lstat = 1; |
@@ -1473,7 +1496,6 @@ void CArcCmdLineParser::Parse2(CArcCmdLineOptions &options) | |||
1473 | #endif | 1496 | #endif |
1474 | */ | 1497 | */ |
1475 | 1498 | ||
1476 | |||
1477 | if (isExtractOrList) | 1499 | if (isExtractOrList) |
1478 | { | 1500 | { |
1479 | CExtractOptionsBase &eo = options.ExtractOptions; | 1501 | CExtractOptionsBase &eo = options.ExtractOptions; |
@@ -1497,7 +1519,15 @@ void CArcCmdLineParser::Parse2(CArcCmdLineOptions &options) | |||
1497 | if (!options.SymLinks.Def) | 1519 | if (!options.SymLinks.Def) |
1498 | nt.SymLinks.Val = true; | 1520 | nt.SymLinks.Val = true; |
1499 | 1521 | ||
1500 | nt.SymLinks_AllowDangerous = symLinks_AllowDangerous; | 1522 | if (parser[NKey::kSymLinks_AllowDangerous].ThereIs) |
1523 | { | ||
1524 | const UString &s = parser[NKey::kSymLinks_AllowDangerous].PostStrings[0]; | ||
1525 | UInt32 v = 9; // default value for "-snld" instead of default = 5 without "-snld". | ||
1526 | if (!s.IsEmpty()) | ||
1527 | if (!StringToUInt32(s, v)) | ||
1528 | throw CArcCmdLineException("Unsupported switch postfix -snld", s); | ||
1529 | nt.SymLinks_DangerousLevel = (unsigned)v; | ||
1530 | } | ||
1501 | 1531 | ||
1502 | nt.ReplaceColonForAltStream = parser[NKey::kReplaceColonForAltStream].ThereIs; | 1532 | nt.ReplaceColonForAltStream = parser[NKey::kReplaceColonForAltStream].ThereIs; |
1503 | nt.WriteToAltStreamIfColon = parser[NKey::kWriteToAltStreamIfColon].ThereIs; | 1533 | nt.WriteToAltStreamIfColon = parser[NKey::kWriteToAltStreamIfColon].ThereIs; |
@@ -1516,9 +1546,9 @@ void CArcCmdLineParser::Parse2(CArcCmdLineOptions &options) | |||
1516 | const UString &s = parser[NKey::kZoneFile].PostStrings[0]; | 1546 | const UString &s = parser[NKey::kZoneFile].PostStrings[0]; |
1517 | if (!s.IsEmpty()) | 1547 | if (!s.IsEmpty()) |
1518 | { | 1548 | { |
1519 | if (s == L"0") eo.ZoneMode = NExtract::NZoneIdMode::kNone; | 1549 | if (s.IsEqualTo("0")) eo.ZoneMode = NExtract::NZoneIdMode::kNone; |
1520 | else if (s == L"1") eo.ZoneMode = NExtract::NZoneIdMode::kAll; | 1550 | else if (s.IsEqualTo("1")) eo.ZoneMode = NExtract::NZoneIdMode::kAll; |
1521 | else if (s == L"2") eo.ZoneMode = NExtract::NZoneIdMode::kOffice; | 1551 | else if (s.IsEqualTo("2")) eo.ZoneMode = NExtract::NZoneIdMode::kOffice; |
1522 | else | 1552 | else |
1523 | throw CArcCmdLineException("Unsupported -snz:", s); | 1553 | throw CArcCmdLineException("Unsupported -snz:", s); |
1524 | } | 1554 | } |
diff --git a/CPP/7zip/UI/Common/ArchiveExtractCallback.cpp b/CPP/7zip/UI/Common/ArchiveExtractCallback.cpp index 2d32694..6631629 100644 --- a/CPP/7zip/UI/Common/ArchiveExtractCallback.cpp +++ b/CPP/7zip/UI/Common/ArchiveExtractCallback.cpp | |||
@@ -6,12 +6,10 @@ | |||
6 | #undef printf | 6 | #undef printf |
7 | 7 | ||
8 | // #include <stdio.h> | 8 | // #include <stdio.h> |
9 | // #include "../../../../C/CpuTicks.h" | ||
10 | 9 | ||
11 | #include "../../../../C/Alloc.h" | 10 | #include "../../../../C/Alloc.h" |
12 | #include "../../../../C/CpuArch.h" | 11 | #include "../../../../C/CpuArch.h" |
13 | 12 | ||
14 | |||
15 | #include "../../../Common/ComTry.h" | 13 | #include "../../../Common/ComTry.h" |
16 | #include "../../../Common/IntToString.h" | 14 | #include "../../../Common/IntToString.h" |
17 | #include "../../../Common/StringConvert.h" | 15 | #include "../../../Common/StringConvert.h" |
@@ -33,6 +31,8 @@ | |||
33 | #include "../../Common/FilePathAutoRename.h" | 31 | #include "../../Common/FilePathAutoRename.h" |
34 | #include "../../Common/StreamUtils.h" | 32 | #include "../../Common/StreamUtils.h" |
35 | 33 | ||
34 | #include "../../Archive/Common/ItemNameUtils.h" | ||
35 | |||
36 | #include "../Common/ExtractingFilePath.h" | 36 | #include "../Common/ExtractingFilePath.h" |
37 | #include "../Common/PropIDUtils.h" | 37 | #include "../Common/PropIDUtils.h" |
38 | 38 | ||
@@ -54,6 +54,23 @@ static const char * const kCantSetFileLen = "Cannot set length for output file"; | |||
54 | #ifdef SUPPORT_LINKS | 54 | #ifdef SUPPORT_LINKS |
55 | static const char * const kCantCreateHardLink = "Cannot create hard link"; | 55 | static const char * const kCantCreateHardLink = "Cannot create hard link"; |
56 | static const char * const kCantCreateSymLink = "Cannot create symbolic link"; | 56 | static const char * const kCantCreateSymLink = "Cannot create symbolic link"; |
57 | static const char * const k_HardLink_to_SymLink_Ignored = "Hard link to symbolic link was ignored"; | ||
58 | static const char * const k_CantDelete_File_for_SymLink = "Cannot delete file for symbolic link creation"; | ||
59 | static const char * const k_CantDelete_Dir_for_SymLink = "Cannot delete directory for symbolic link creation"; | ||
60 | #endif | ||
61 | |||
62 | static const unsigned k_LinkDataSize_LIMIT = 1 << 12; | ||
63 | |||
64 | #ifdef SUPPORT_LINKS | ||
65 | #if WCHAR_PATH_SEPARATOR != L'/' | ||
66 | // we convert linux slashes to windows slashes for further processing. | ||
67 | // also we convert linux backslashes to BackslashReplacement character. | ||
68 | #define REPLACE_SLASHES_from_Linux_to_Sys(s) \ | ||
69 | { NArchive::NItemName::ReplaceToWinSlashes(s, true); } // useBackslashReplacement | ||
70 | // { s.Replace(L'/', WCHAR_PATH_SEPARATOR); } | ||
71 | #else | ||
72 | #define REPLACE_SLASHES_from_Linux_to_Sys(s) | ||
73 | #endif | ||
57 | #endif | 74 | #endif |
58 | 75 | ||
59 | #ifndef Z7_SFX | 76 | #ifndef Z7_SFX |
@@ -140,21 +157,25 @@ static bool FindExt2(const char *p, const UString &name) | |||
140 | } | 157 | } |
141 | 158 | ||
142 | 159 | ||
143 | static const FChar * const k_ZoneId_StreamName = FTEXT(":Zone.Identifier"); | 160 | static const char * const k_ZoneId_StreamName_With_Colon_Prefix = ":Zone.Identifier"; |
144 | 161 | ||
145 | void ReadZoneFile_Of_BaseFile(CFSTR fileName2, CByteBuffer &buf) | 162 | bool Is_ZoneId_StreamName(const wchar_t *s) |
146 | { | 163 | { |
147 | FString fileName (fileName2); | 164 | return StringsAreEqualNoCase_Ascii(s, k_ZoneId_StreamName_With_Colon_Prefix + 1); |
148 | fileName += k_ZoneId_StreamName; | 165 | } |
149 | 166 | ||
167 | void ReadZoneFile_Of_BaseFile(CFSTR fileName, CByteBuffer &buf) | ||
168 | { | ||
150 | buf.Free(); | 169 | buf.Free(); |
170 | FString path (fileName); | ||
171 | path += k_ZoneId_StreamName_With_Colon_Prefix; | ||
151 | NIO::CInFile file; | 172 | NIO::CInFile file; |
152 | if (!file.Open(fileName)) | 173 | if (!file.Open(path)) |
153 | return; | 174 | return; |
154 | UInt64 fileSize; | 175 | UInt64 fileSize; |
155 | if (!file.GetLength(fileSize)) | 176 | if (!file.GetLength(fileSize)) |
156 | return; | 177 | return; |
157 | if (fileSize == 0 || fileSize >= ((UInt32)1 << 16)) | 178 | if (fileSize == 0 || fileSize >= (1u << 15)) |
158 | return; | 179 | return; |
159 | buf.Alloc((size_t)fileSize); | 180 | buf.Alloc((size_t)fileSize); |
160 | size_t processed; | 181 | size_t processed; |
@@ -166,7 +187,7 @@ void ReadZoneFile_Of_BaseFile(CFSTR fileName2, CByteBuffer &buf) | |||
166 | bool WriteZoneFile_To_BaseFile(CFSTR fileName, const CByteBuffer &buf) | 187 | bool WriteZoneFile_To_BaseFile(CFSTR fileName, const CByteBuffer &buf) |
167 | { | 188 | { |
168 | FString path (fileName); | 189 | FString path (fileName); |
169 | path += k_ZoneId_StreamName; | 190 | path += k_ZoneId_StreamName_With_Colon_Prefix; |
170 | NIO::COutFile file; | 191 | NIO::COutFile file; |
171 | if (!file.Create_ALWAYS(path)) | 192 | if (!file.Create_ALWAYS(path)) |
172 | return false; | 193 | return false; |
@@ -213,7 +234,7 @@ HRESULT CArchiveExtractCallback::PrepareHardLinks(const CRecordVector<UInt32> *r | |||
213 | if (!_arc->Ask_INode) | 234 | if (!_arc->Ask_INode) |
214 | return S_OK; | 235 | return S_OK; |
215 | 236 | ||
216 | IInArchive *archive = _arc->Archive; | 237 | IInArchive * const archive = _arc->Archive; |
217 | CRecordVector<CHardLinkNode> &hardIDs = _hardLinks.IDs; | 238 | CRecordVector<CHardLinkNode> &hardIDs = _hardLinks.IDs; |
218 | 239 | ||
219 | { | 240 | { |
@@ -275,16 +296,13 @@ HRESULT CArchiveExtractCallback::PrepareHardLinks(const CRecordVector<UInt32> *r | |||
275 | 296 | ||
276 | 297 | ||
277 | CArchiveExtractCallback::CArchiveExtractCallback(): | 298 | CArchiveExtractCallback::CArchiveExtractCallback(): |
278 | _arc(NULL), | 299 | // Write_CTime(true), |
279 | Write_CTime(true), | 300 | // Write_ATime(true), |
280 | Write_ATime(true), | 301 | // Write_MTime(true), |
281 | Write_MTime(true), | ||
282 | Is_elimPrefix_Mode(false), | 302 | Is_elimPrefix_Mode(false), |
303 | _arc(NULL), | ||
283 | _multiArchives(false) | 304 | _multiArchives(false) |
284 | { | 305 | { |
285 | LocalProgressSpec = new CLocalProgress(); | ||
286 | _localProgress = LocalProgressSpec; | ||
287 | |||
288 | #ifdef Z7_USE_SECURITY_CODE | 306 | #ifdef Z7_USE_SECURITY_CODE |
289 | _saclEnabled = InitLocalPrivileges(); | 307 | _saclEnabled = InitLocalPrivileges(); |
290 | #endif | 308 | #endif |
@@ -293,9 +311,9 @@ CArchiveExtractCallback::CArchiveExtractCallback(): | |||
293 | 311 | ||
294 | void CArchiveExtractCallback::InitBeforeNewArchive() | 312 | void CArchiveExtractCallback::InitBeforeNewArchive() |
295 | { | 313 | { |
296 | #if defined(_WIN32) && !defined(UNDER_CE) | 314 | #if defined(_WIN32) && !defined(UNDER_CE) && !defined(Z7_SFX) |
297 | ZoneBuf.Free(); | 315 | ZoneBuf.Free(); |
298 | #endif | 316 | #endif |
299 | } | 317 | } |
300 | 318 | ||
301 | void CArchiveExtractCallback::Init( | 319 | void CArchiveExtractCallback::Init( |
@@ -312,37 +330,31 @@ void CArchiveExtractCallback::Init( | |||
312 | _outFileStream.Release(); | 330 | _outFileStream.Release(); |
313 | _bufPtrSeqOutStream.Release(); | 331 | _bufPtrSeqOutStream.Release(); |
314 | 332 | ||
315 | #ifdef SUPPORT_LINKS | 333 | #ifdef SUPPORT_LINKS |
316 | _hardLinks.Clear(); | 334 | _hardLinks.Clear(); |
317 | #endif | 335 | _postLinks.Clear(); |
336 | #endif | ||
318 | 337 | ||
319 | #ifdef SUPPORT_ALT_STREAMS | 338 | #ifdef SUPPORT_ALT_STREAMS |
320 | _renamedFiles.Clear(); | 339 | _renamedFiles.Clear(); |
321 | #endif | 340 | #endif |
322 | 341 | ||
323 | _ntOptions = ntOptions; | 342 | _ntOptions = ntOptions; |
324 | _wildcardCensor = wildcardCensor; | 343 | _wildcardCensor = wildcardCensor; |
325 | |||
326 | _stdOutMode = stdOutMode; | 344 | _stdOutMode = stdOutMode; |
327 | _testMode = testMode; | 345 | _testMode = testMode; |
328 | |||
329 | // _progressTotal = 0; | ||
330 | // _progressTotal_Defined = false; | ||
331 | |||
332 | _packTotal = packSize; | 346 | _packTotal = packSize; |
333 | _progressTotal = packSize; | 347 | _progressTotal = packSize; |
334 | _progressTotal_Defined = true; | 348 | // _progressTotal = 0; |
335 | 349 | // _progressTotal_Defined = false; | |
350 | // _progressTotal_Defined = true; | ||
336 | _extractCallback2 = extractCallback2; | 351 | _extractCallback2 = extractCallback2; |
337 | |||
338 | /* | 352 | /* |
339 | _compressProgress.Release(); | 353 | _compressProgress.Release(); |
340 | _extractCallback2.QueryInterface(IID_ICompressProgressInfo, &_compressProgress); | 354 | _extractCallback2.QueryInterface(IID_ICompressProgressInfo, &_compressProgress); |
341 | |||
342 | _callbackMessage.Release(); | 355 | _callbackMessage.Release(); |
343 | _extractCallback2.QueryInterface(IID_IArchiveExtractCallbackMessage2, &_callbackMessage); | 356 | _extractCallback2.QueryInterface(IID_IArchiveExtractCallbackMessage2, &_callbackMessage); |
344 | */ | 357 | */ |
345 | |||
346 | _folderArchiveExtractCallback2.Release(); | 358 | _folderArchiveExtractCallback2.Release(); |
347 | _extractCallback2.QueryInterface(IID_IFolderArchiveExtractCallback2, &_folderArchiveExtractCallback2); | 359 | _extractCallback2.QueryInterface(IID_IFolderArchiveExtractCallback2, &_folderArchiveExtractCallback2); |
348 | 360 | ||
@@ -390,7 +402,7 @@ Z7_COM7F_IMF(CArchiveExtractCallback::SetTotal(UInt64 size)) | |||
390 | { | 402 | { |
391 | COM_TRY_BEGIN | 403 | COM_TRY_BEGIN |
392 | _progressTotal = size; | 404 | _progressTotal = size; |
393 | _progressTotal_Defined = true; | 405 | // _progressTotal_Defined = true; |
394 | if (!_multiArchives && _extractCallback2) | 406 | if (!_multiArchives && _extractCallback2) |
395 | return _extractCallback2->SetTotal(size); | 407 | return _extractCallback2->SetTotal(size); |
396 | return S_OK; | 408 | return S_OK; |
@@ -430,7 +442,7 @@ Z7_COM7F_IMF(CArchiveExtractCallback::SetCompleted(const UInt64 *completeValue)) | |||
430 | if (_multiArchives) | 442 | if (_multiArchives) |
431 | { | 443 | { |
432 | packCur = LocalProgressSpec->InSize; | 444 | packCur = LocalProgressSpec->InSize; |
433 | if (completeValue && _progressTotal_Defined) | 445 | if (completeValue /* && _progressTotal_Defined */) |
434 | packCur += MyMultDiv64(*completeValue, _progressTotal, _packTotal); | 446 | packCur += MyMultDiv64(*completeValue, _progressTotal, _packTotal); |
435 | completeValue = &packCur; | 447 | completeValue = &packCur; |
436 | } | 448 | } |
@@ -443,12 +455,13 @@ Z7_COM7F_IMF(CArchiveExtractCallback::SetCompleted(const UInt64 *completeValue)) | |||
443 | Z7_COM7F_IMF(CArchiveExtractCallback::SetRatioInfo(const UInt64 *inSize, const UInt64 *outSize)) | 455 | Z7_COM7F_IMF(CArchiveExtractCallback::SetRatioInfo(const UInt64 *inSize, const UInt64 *outSize)) |
444 | { | 456 | { |
445 | COM_TRY_BEGIN | 457 | COM_TRY_BEGIN |
446 | return _localProgress->SetRatioInfo(inSize, outSize); | 458 | return LocalProgressSpec.Interface()->SetRatioInfo(inSize, outSize); |
447 | COM_TRY_END | 459 | COM_TRY_END |
448 | } | 460 | } |
449 | 461 | ||
450 | 462 | ||
451 | void CArchiveExtractCallback::CreateComplexDirectory(const UStringVector &dirPathParts, FString &fullPath) | 463 | void CArchiveExtractCallback::CreateComplexDirectory( |
464 | const UStringVector &dirPathParts, bool isFinal, FString &fullPath) | ||
452 | { | 465 | { |
453 | // we use (_item.IsDir) in this function | 466 | // we use (_item.IsDir) in this function |
454 | 467 | ||
@@ -480,7 +493,7 @@ void CArchiveExtractCallback::CreateComplexDirectory(const UStringVector &dirPat | |||
480 | const UString &s = dirPathParts[i]; | 493 | const UString &s = dirPathParts[i]; |
481 | fullPath += us2fs(s); | 494 | fullPath += us2fs(s); |
482 | 495 | ||
483 | const bool isFinalDir = (i == dirPathParts.Size() - 1 && _item.IsDir); | 496 | const bool isFinalDir = (i == dirPathParts.Size() - 1 && isFinal && _item.IsDir); |
484 | 497 | ||
485 | if (fullPath.IsEmpty()) | 498 | if (fullPath.IsEmpty()) |
486 | { | 499 | { |
@@ -541,7 +554,7 @@ static void AddPathToMessage(UString &s, const FString &path) | |||
541 | s += fs2us(path); | 554 | s += fs2us(path); |
542 | } | 555 | } |
543 | 556 | ||
544 | HRESULT CArchiveExtractCallback::SendMessageError(const char *message, const FString &path) | 557 | HRESULT CArchiveExtractCallback::SendMessageError(const char *message, const FString &path) const |
545 | { | 558 | { |
546 | UString s (message); | 559 | UString s (message); |
547 | AddPathToMessage(s, path); | 560 | AddPathToMessage(s, path); |
@@ -549,7 +562,7 @@ HRESULT CArchiveExtractCallback::SendMessageError(const char *message, const FSt | |||
549 | } | 562 | } |
550 | 563 | ||
551 | 564 | ||
552 | HRESULT CArchiveExtractCallback::SendMessageError_with_Error(HRESULT errorCode, const char *message, const FString &path) | 565 | HRESULT CArchiveExtractCallback::SendMessageError_with_Error(HRESULT errorCode, const char *message, const FString &path) const |
553 | { | 566 | { |
554 | UString s (message); | 567 | UString s (message); |
555 | if (errorCode != S_OK) | 568 | if (errorCode != S_OK) |
@@ -561,13 +574,13 @@ HRESULT CArchiveExtractCallback::SendMessageError_with_Error(HRESULT errorCode, | |||
561 | return _extractCallback2->MessageError(s); | 574 | return _extractCallback2->MessageError(s); |
562 | } | 575 | } |
563 | 576 | ||
564 | HRESULT CArchiveExtractCallback::SendMessageError_with_LastError(const char *message, const FString &path) | 577 | HRESULT CArchiveExtractCallback::SendMessageError_with_LastError(const char *message, const FString &path) const |
565 | { | 578 | { |
566 | const HRESULT errorCode = GetLastError_noZero_HRESULT(); | 579 | const HRESULT errorCode = GetLastError_noZero_HRESULT(); |
567 | return SendMessageError_with_Error(errorCode, message, path); | 580 | return SendMessageError_with_Error(errorCode, message, path); |
568 | } | 581 | } |
569 | 582 | ||
570 | HRESULT CArchiveExtractCallback::SendMessageError2(HRESULT errorCode, const char *message, const FString &path1, const FString &path2) | 583 | HRESULT CArchiveExtractCallback::SendMessageError2(HRESULT errorCode, const char *message, const FString &path1, const FString &path2) const |
571 | { | 584 | { |
572 | UString s (message); | 585 | UString s (message); |
573 | if (errorCode != 0) | 586 | if (errorCode != 0) |
@@ -580,15 +593,32 @@ HRESULT CArchiveExtractCallback::SendMessageError2(HRESULT errorCode, const char | |||
580 | return _extractCallback2->MessageError(s); | 593 | return _extractCallback2->MessageError(s); |
581 | } | 594 | } |
582 | 595 | ||
596 | HRESULT CArchiveExtractCallback::SendMessageError2_with_LastError( | ||
597 | const char *message, const FString &path1, const FString &path2) const | ||
598 | { | ||
599 | const HRESULT errorCode = GetLastError_noZero_HRESULT(); | ||
600 | return SendMessageError2(errorCode, message, path1, path2); | ||
601 | } | ||
602 | |||
583 | #ifndef Z7_SFX | 603 | #ifndef Z7_SFX |
584 | 604 | ||
605 | Z7_CLASS_IMP_COM_1( | ||
606 | CGetProp | ||
607 | , IGetProp | ||
608 | ) | ||
609 | public: | ||
610 | UInt32 IndexInArc; | ||
611 | const CArc *Arc; | ||
612 | // UString BaseName; // relative path | ||
613 | }; | ||
614 | |||
585 | Z7_COM7F_IMF(CGetProp::GetProp(PROPID propID, PROPVARIANT *value)) | 615 | Z7_COM7F_IMF(CGetProp::GetProp(PROPID propID, PROPVARIANT *value)) |
586 | { | 616 | { |
587 | /* | 617 | /* |
588 | if (propID == kpidName) | 618 | if (propID == kpidBaseName) |
589 | { | 619 | { |
590 | COM_TRY_BEGIN | 620 | COM_TRY_BEGIN |
591 | NCOM::CPropVariant prop = Name; | 621 | NCOM::CPropVariant prop = BaseName; |
592 | prop.Detach(value); | 622 | prop.Detach(value); |
593 | return S_OK; | 623 | return S_OK; |
594 | COM_TRY_END | 624 | COM_TRY_END |
@@ -600,38 +630,25 @@ Z7_COM7F_IMF(CGetProp::GetProp(PROPID propID, PROPVARIANT *value)) | |||
600 | #endif // Z7_SFX | 630 | #endif // Z7_SFX |
601 | 631 | ||
602 | 632 | ||
603 | #ifdef SUPPORT_LINKS | ||
604 | |||
605 | static UString GetDirPrefixOf(const UString &src) | ||
606 | { | ||
607 | UString s (src); | ||
608 | if (!s.IsEmpty()) | ||
609 | { | ||
610 | if (IsPathSepar(s.Back())) | ||
611 | s.DeleteBack(); | ||
612 | int pos = s.ReverseFind_PathSepar(); | ||
613 | s.DeleteFrom((unsigned)(pos + 1)); | ||
614 | } | ||
615 | return s; | ||
616 | } | ||
617 | |||
618 | #endif // SUPPORT_LINKS | ||
619 | |||
620 | struct CLinkLevelsInfo | 633 | struct CLinkLevelsInfo |
621 | { | 634 | { |
622 | bool IsAbsolute; | 635 | bool IsAbsolute; |
636 | bool ParentDirDots_after_NonParent; | ||
623 | int LowLevel; | 637 | int LowLevel; |
624 | int FinalLevel; | 638 | int FinalLevel; |
625 | 639 | ||
626 | void Parse(const UString &path); | 640 | void Parse(const UString &path, bool isWSL); |
627 | }; | 641 | }; |
628 | 642 | ||
629 | void CLinkLevelsInfo::Parse(const UString &path) | 643 | void CLinkLevelsInfo::Parse(const UString &path, bool isWSL) |
630 | { | 644 | { |
631 | IsAbsolute = NName::IsAbsolutePath(path); | 645 | IsAbsolute = isWSL ? |
632 | 646 | IS_PATH_SEPAR(path[0]) : | |
647 | NName::IsAbsolutePath(path); | ||
633 | LowLevel = 0; | 648 | LowLevel = 0; |
634 | FinalLevel = 0; | 649 | FinalLevel = 0; |
650 | ParentDirDots_after_NonParent = false; | ||
651 | bool nonParentDir = false; | ||
635 | 652 | ||
636 | UStringVector parts; | 653 | UStringVector parts; |
637 | SplitPathToParts(path, parts); | 654 | SplitPathToParts(path, parts); |
@@ -646,32 +663,41 @@ void CLinkLevelsInfo::Parse(const UString &path) | |||
646 | IsAbsolute = true; | 663 | IsAbsolute = true; |
647 | continue; | 664 | continue; |
648 | } | 665 | } |
649 | if (s == L".") | 666 | if (s.IsEqualTo(".")) |
650 | continue; | 667 | continue; |
651 | if (s == L"..") | 668 | if (s.IsEqualTo("..")) |
652 | { | 669 | { |
670 | if (IsAbsolute || nonParentDir) | ||
671 | ParentDirDots_after_NonParent = true; | ||
653 | level--; | 672 | level--; |
654 | if (LowLevel > level) | 673 | if (LowLevel > level) |
655 | LowLevel = level; | 674 | LowLevel = level; |
656 | } | 675 | } |
657 | else | 676 | else |
677 | { | ||
678 | nonParentDir = true; | ||
658 | level++; | 679 | level++; |
680 | } | ||
659 | } | 681 | } |
660 | 682 | ||
661 | FinalLevel = level; | 683 | FinalLevel = level; |
662 | } | 684 | } |
663 | 685 | ||
664 | 686 | ||
665 | bool IsSafePath(const UString &path); | 687 | static bool IsSafePath(const UString &path, bool isWSL) |
666 | bool IsSafePath(const UString &path) | ||
667 | { | 688 | { |
668 | CLinkLevelsInfo levelsInfo; | 689 | CLinkLevelsInfo levelsInfo; |
669 | levelsInfo.Parse(path); | 690 | levelsInfo.Parse(path, isWSL); |
670 | return !levelsInfo.IsAbsolute | 691 | return !levelsInfo.IsAbsolute |
671 | && levelsInfo.LowLevel >= 0 | 692 | && levelsInfo.LowLevel >= 0 |
672 | && levelsInfo.FinalLevel > 0; | 693 | && levelsInfo.FinalLevel > 0; |
673 | } | 694 | } |
674 | 695 | ||
696 | bool IsSafePath(const UString &path); | ||
697 | bool IsSafePath(const UString &path) | ||
698 | { | ||
699 | return IsSafePath(path, false); // isWSL | ||
700 | } | ||
675 | 701 | ||
676 | bool CensorNode_CheckPath2(const NWildcard::CCensorNode &node, const CReadArcItem &item, bool &include); | 702 | bool CensorNode_CheckPath2(const NWildcard::CCensorNode &node, const CReadArcItem &item, bool &include); |
677 | bool CensorNode_CheckPath2(const NWildcard::CCensorNode &node, const CReadArcItem &item, bool &include) | 703 | bool CensorNode_CheckPath2(const NWildcard::CCensorNode &node, const CReadArcItem &item, bool &include) |
@@ -787,159 +813,113 @@ HRESULT CArchiveExtractCallback::MyCopyFile(ISequentialOutStream *outStream) | |||
787 | 813 | ||
788 | HRESULT CArchiveExtractCallback::ReadLink() | 814 | HRESULT CArchiveExtractCallback::ReadLink() |
789 | { | 815 | { |
790 | IInArchive *archive = _arc->Archive; | 816 | IInArchive * const archive = _arc->Archive; |
791 | const UInt32 index = _index; | 817 | const UInt32 index = _index; |
792 | _link.Clear(); | 818 | // _link.Clear(); // _link.Clear() was called already. |
793 | |||
794 | { | 819 | { |
795 | NCOM::CPropVariant prop; | 820 | NCOM::CPropVariant prop; |
796 | RINOK(archive->GetProperty(index, kpidHardLink, &prop)) | 821 | RINOK(archive->GetProperty(index, kpidHardLink, &prop)) |
797 | if (prop.vt == VT_BSTR) | 822 | if (prop.vt == VT_BSTR) |
798 | { | 823 | { |
799 | _link.isHardLink = true; | 824 | _link.LinkType = k_LinkType_HardLink; |
800 | // _link.isCopyLink = false; | ||
801 | _link.isRelative = false; // RAR5, TAR: hard links are from root folder of archive | 825 | _link.isRelative = false; // RAR5, TAR: hard links are from root folder of archive |
802 | _link.linkPath.SetFromBstr(prop.bstrVal); | 826 | _link.LinkPath.SetFromBstr(prop.bstrVal); |
827 | // 7-Zip 24-: tar handler returned original path (with linux slash in most case) | ||
828 | // 7-Zip 24-: rar5 handler returned path with system slash. | ||
829 | // 7-Zip 25+: tar/rar5 handlers return linux path in most cases. | ||
803 | } | 830 | } |
804 | else if (prop.vt != VT_EMPTY) | 831 | else if (prop.vt != VT_EMPTY) |
805 | return E_FAIL; | 832 | return E_FAIL; |
806 | } | 833 | } |
807 | |||
808 | /* | 834 | /* |
809 | { | 835 | { |
810 | NCOM::CPropVariant prop; | 836 | NCOM::CPropVariant prop; |
811 | RINOK(archive->GetProperty(index, kpidCopyLink, &prop)); | 837 | RINOK(archive->GetProperty(index, kpidCopyLink, &prop)); |
812 | if (prop.vt == VT_BSTR) | 838 | if (prop.vt == VT_BSTR) |
813 | { | 839 | { |
814 | _link.isHardLink = false; | 840 | _link.LinkType = k_LinkType_CopyLink; |
815 | _link.isCopyLink = true; | ||
816 | _link.isRelative = false; // RAR5: copy links are from root folder of archive | 841 | _link.isRelative = false; // RAR5: copy links are from root folder of archive |
817 | _link.linkPath.SetFromBstr(prop.bstrVal); | 842 | _link.LinkPath.SetFromBstr(prop.bstrVal); |
818 | } | 843 | } |
819 | else if (prop.vt != VT_EMPTY) | 844 | else if (prop.vt != VT_EMPTY) |
820 | return E_FAIL; | 845 | return E_FAIL; |
821 | } | 846 | } |
822 | */ | 847 | */ |
823 | |||
824 | { | 848 | { |
825 | NCOM::CPropVariant prop; | 849 | NCOM::CPropVariant prop; |
826 | RINOK(archive->GetProperty(index, kpidSymLink, &prop)) | 850 | RINOK(archive->GetProperty(index, kpidSymLink, &prop)) |
827 | if (prop.vt == VT_BSTR) | 851 | if (prop.vt == VT_BSTR) |
828 | { | 852 | { |
829 | _link.isHardLink = false; | 853 | _link.LinkType = k_LinkType_PureSymLink; |
830 | // _link.isCopyLink = false; | 854 | _link.isRelative = true; // RAR5, TAR: symbolic links are relative by default |
831 | _link.isRelative = true; // RAR5, TAR: symbolic links can be relative | 855 | _link.LinkPath.SetFromBstr(prop.bstrVal); |
832 | _link.linkPath.SetFromBstr(prop.bstrVal); | 856 | // 7-Zip 24-: (tar, cpio, xar, ext, iso) handlers returned returned original path (with linux slash in most case) |
857 | // 7-Zip 24-: rar5 handler returned path with system slash. | ||
858 | // 7-Zip 25+: all handlers return linux path in most cases. | ||
833 | } | 859 | } |
834 | else if (prop.vt != VT_EMPTY) | 860 | else if (prop.vt != VT_EMPTY) |
835 | return E_FAIL; | 861 | return E_FAIL; |
836 | } | 862 | } |
837 | 863 | ||
838 | NtReparse_Data = NULL; | 864 | // linux path separator in (_link.LinkPath) is expected for most cases, |
839 | NtReparse_Size = 0; | 865 | // if new handler code is used, and if data in archive is correct. |
840 | 866 | // NtReparse_Data = NULL; | |
841 | if (_link.linkPath.IsEmpty() && _arc->GetRawProps) | 867 | // NtReparse_Size = 0; |
868 | if (!_link.LinkPath.IsEmpty()) | ||
869 | { | ||
870 | REPLACE_SLASHES_from_Linux_to_Sys(_link.LinkPath) | ||
871 | } | ||
872 | else if (_arc->GetRawProps) | ||
842 | { | 873 | { |
843 | const void *data; | 874 | const void *data; |
844 | UInt32 dataSize; | 875 | UInt32 dataSize, propType; |
845 | UInt32 propType; | 876 | if (_arc->GetRawProps->GetRawProp(_index, kpidNtReparse, &data, &dataSize, &propType) == S_OK |
846 | 877 | // && dataSize == 1234567 // for debug: unpacking without reparse | |
847 | _arc->GetRawProps->GetRawProp(_index, kpidNtReparse, &data, &dataSize, &propType); | 878 | && dataSize) |
848 | |||
849 | // if (dataSize == 1234567) // for debug: unpacking without reparse | ||
850 | if (dataSize != 0) | ||
851 | { | 879 | { |
852 | if (propType != NPropDataType::kRaw) | 880 | if (propType != NPropDataType::kRaw) |
853 | return E_FAIL; | 881 | return E_FAIL; |
854 | |||
855 | // 21.06: we need kpidNtReparse in linux for wim archives created in Windows | 882 | // 21.06: we need kpidNtReparse in linux for wim archives created in Windows |
856 | // #ifdef _WIN32 | 883 | // NtReparse_Data = data; |
857 | 884 | // NtReparse_Size = dataSize; | |
858 | NtReparse_Data = data; | 885 | // we ignore error code here, if there is failure of parsing: |
859 | NtReparse_Size = dataSize; | 886 | _link.Parse_from_WindowsReparseData((const Byte *)data, dataSize); |
860 | |||
861 | CReparseAttr reparse; | ||
862 | bool isOkReparse = reparse.Parse((const Byte *)data, dataSize); | ||
863 | if (isOkReparse) | ||
864 | { | ||
865 | _link.isHardLink = false; | ||
866 | // _link.isCopyLink = false; | ||
867 | _link.linkPath = reparse.GetPath(); | ||
868 | _link.isJunction = reparse.IsMountPoint(); | ||
869 | |||
870 | if (reparse.IsSymLink_WSL()) | ||
871 | { | ||
872 | _link.isWSL = true; | ||
873 | _link.isRelative = reparse.IsRelative_WSL(); | ||
874 | } | ||
875 | else | ||
876 | _link.isRelative = reparse.IsRelative_Win(); | ||
877 | |||
878 | // const AString s = GetAnsiString(_link.linkPath); | ||
879 | // printf("\n_link.linkPath: %s\n", s.Ptr()); | ||
880 | |||
881 | #ifndef _WIN32 | ||
882 | _link.linkPath.Replace(L'\\', WCHAR_PATH_SEPARATOR); | ||
883 | #endif | ||
884 | } | ||
885 | // #endif | ||
886 | } | 887 | } |
887 | } | 888 | } |
888 | 889 | ||
889 | if (_link.linkPath.IsEmpty()) | 890 | if (_link.LinkPath.IsEmpty()) |
890 | return S_OK; | 891 | return S_OK; |
891 | 892 | // (_link.LinkPath) uses system path separator. | |
893 | // windows: (_link.LinkPath) doesn't contain linux separator (slash). | ||
892 | { | 894 | { |
893 | #ifdef _WIN32 | 895 | // _link.LinkPath = "\\??\\r:\\1\\2"; // for debug |
894 | _link.linkPath.Replace(L'/', WCHAR_PATH_SEPARATOR); | 896 | // rar5+ returns kpidSymLink absolute link path with "\??\" prefix. |
895 | #endif | 897 | // we normalize such prefix: |
896 | 898 | if (_link.LinkPath.IsPrefixedBy(STRING_PATH_SEPARATOR "??" STRING_PATH_SEPARATOR)) | |
897 | // rar5 uses "\??\" prefix for absolute links | ||
898 | if (_link.linkPath.IsPrefixedBy(WSTRING_PATH_SEPARATOR L"??" WSTRING_PATH_SEPARATOR)) | ||
899 | { | ||
900 | _link.isRelative = false; | ||
901 | _link.linkPath.DeleteFrontal(4); | ||
902 | } | ||
903 | |||
904 | for (;;) | ||
905 | // while (NName::IsAbsolutePath(linkPath)) | ||
906 | { | 899 | { |
907 | unsigned n = NName::GetRootPrefixSize(_link.linkPath); | ||
908 | if (n == 0) | ||
909 | break; | ||
910 | _link.isRelative = false; | 900 | _link.isRelative = false; |
911 | _link.linkPath.DeleteFrontal(n); | 901 | // we normalize prefix from "\??\" to "\\?\": |
912 | } | 902 | _link.LinkPath.ReplaceOneCharAtPos(1, WCHAR_PATH_SEPARATOR); |
913 | } | 903 | _link.isWindowsPath = true; |
914 | 904 | if (_link.LinkPath.IsPrefixedBy_Ascii_NoCase( | |
915 | if (_link.linkPath.IsEmpty()) | 905 | STRING_PATH_SEPARATOR |
916 | return S_OK; | 906 | STRING_PATH_SEPARATOR "?" |
917 | 907 | STRING_PATH_SEPARATOR "UNC" | |
918 | if (!_link.isRelative && _removePathParts.Size() != 0) | 908 | STRING_PATH_SEPARATOR)) |
919 | { | ||
920 | UStringVector pathParts; | ||
921 | SplitPathToParts(_link.linkPath, pathParts); | ||
922 | bool badPrefix = false; | ||
923 | FOR_VECTOR (i, _removePathParts) | ||
924 | { | ||
925 | if (CompareFileNames(_removePathParts[i], pathParts[i]) != 0) | ||
926 | { | 909 | { |
927 | badPrefix = true; | 910 | // we normalize prefix from "\\?\UNC\path" to "\\path": |
928 | break; | 911 | _link.LinkPath.DeleteFrontal(6); |
912 | _link.LinkPath.ReplaceOneCharAtPos(0, WCHAR_PATH_SEPARATOR); | ||
913 | } | ||
914 | else | ||
915 | { | ||
916 | const unsigned k_prefix_Size = 4; | ||
917 | if (NName::IsDrivePath(_link.LinkPath.Ptr(k_prefix_Size))) | ||
918 | _link.LinkPath.DeleteFrontal(k_prefix_Size); | ||
929 | } | 919 | } |
930 | } | 920 | } |
931 | if (!badPrefix) | ||
932 | pathParts.DeleteFrontal(_removePathParts.Size()); | ||
933 | _link.linkPath = MakePathFromParts(pathParts); | ||
934 | } | ||
935 | |||
936 | /* | ||
937 | if (!_link.linkPath.IsEmpty()) | ||
938 | { | ||
939 | printf("\n_link %s to -> %s\n", GetOemString(_item.Path).Ptr(), GetOemString(_link.linkPath).Ptr()); | ||
940 | } | 921 | } |
941 | */ | 922 | _link.Normalize_to_RelativeSafe(_removePathParts); |
942 | |||
943 | return S_OK; | 923 | return S_OK; |
944 | } | 924 | } |
945 | 925 | ||
@@ -949,7 +929,7 @@ HRESULT CArchiveExtractCallback::ReadLink() | |||
949 | #ifndef _WIN32 | 929 | #ifndef _WIN32 |
950 | 930 | ||
951 | static HRESULT GetOwner(IInArchive *archive, | 931 | static HRESULT GetOwner(IInArchive *archive, |
952 | UInt32 index, UInt32 pidName, UInt32 pidId, COwnerInfo &res) | 932 | UInt32 index, UInt32 pidName, UInt32 pidId, CProcessedFileInfo::COwnerInfo &res) |
953 | { | 933 | { |
954 | { | 934 | { |
955 | NWindows::NCOM::CPropVariant prop; | 935 | NWindows::NCOM::CPropVariant prop; |
@@ -957,7 +937,7 @@ static HRESULT GetOwner(IInArchive *archive, | |||
957 | if (prop.vt == VT_UI4) | 937 | if (prop.vt == VT_UI4) |
958 | { | 938 | { |
959 | res.Id_Defined = true; | 939 | res.Id_Defined = true; |
960 | res.Id = prop.ulVal; // for debug | 940 | res.Id = prop.ulVal; |
961 | // res.Id++; // for debug | 941 | // res.Id++; // for debug |
962 | // if (pidId == kpidGroupId) res.Id += 7; // for debug | 942 | // if (pidId == kpidGroupId) res.Id += 7; // for debug |
963 | // res.Id = 0; // for debug | 943 | // res.Id = 0; // for debug |
@@ -989,7 +969,7 @@ static HRESULT GetOwner(IInArchive *archive, | |||
989 | 969 | ||
990 | HRESULT CArchiveExtractCallback::Read_fi_Props() | 970 | HRESULT CArchiveExtractCallback::Read_fi_Props() |
991 | { | 971 | { |
992 | IInArchive *archive = _arc->Archive; | 972 | IInArchive * const archive = _arc->Archive; |
993 | const UInt32 index = _index; | 973 | const UInt32 index = _index; |
994 | 974 | ||
995 | _fi.Attrib_Defined = false; | 975 | _fi.Attrib_Defined = false; |
@@ -1081,35 +1061,35 @@ void CArchiveExtractCallback::CorrectPathParts() | |||
1081 | } | 1061 | } |
1082 | 1062 | ||
1083 | 1063 | ||
1084 | void CArchiveExtractCallback::GetFiTimesCAM(CFiTimesCAM &pt) | 1064 | static void GetFiTimesCAM(const CProcessedFileInfo &fi, CFiTimesCAM &pt, const CArc &arc) |
1085 | { | 1065 | { |
1086 | pt.CTime_Defined = false; | 1066 | pt.CTime_Defined = false; |
1087 | pt.ATime_Defined = false; | 1067 | pt.ATime_Defined = false; |
1088 | pt.MTime_Defined = false; | 1068 | pt.MTime_Defined = false; |
1089 | 1069 | ||
1090 | if (Write_MTime) | 1070 | // if (Write_MTime) |
1091 | { | 1071 | { |
1092 | if (_fi.MTime.Def) | 1072 | if (fi.MTime.Def) |
1093 | { | 1073 | { |
1094 | _fi.MTime.Write_To_FiTime(pt.MTime); | 1074 | fi.MTime.Write_To_FiTime(pt.MTime); |
1095 | pt.MTime_Defined = true; | 1075 | pt.MTime_Defined = true; |
1096 | } | 1076 | } |
1097 | else if (_arc->MTime.Def) | 1077 | else if (arc.MTime.Def) |
1098 | { | 1078 | { |
1099 | _arc->MTime.Write_To_FiTime(pt.MTime); | 1079 | arc.MTime.Write_To_FiTime(pt.MTime); |
1100 | pt.MTime_Defined = true; | 1080 | pt.MTime_Defined = true; |
1101 | } | 1081 | } |
1102 | } | 1082 | } |
1103 | 1083 | ||
1104 | if (Write_CTime && _fi.CTime.Def) | 1084 | if (/* Write_CTime && */ fi.CTime.Def) |
1105 | { | 1085 | { |
1106 | _fi.CTime.Write_To_FiTime(pt.CTime); | 1086 | fi.CTime.Write_To_FiTime(pt.CTime); |
1107 | pt.CTime_Defined = true; | 1087 | pt.CTime_Defined = true; |
1108 | } | 1088 | } |
1109 | 1089 | ||
1110 | if (Write_ATime && _fi.ATime.Def) | 1090 | if (/* Write_ATime && */ fi.ATime.Def) |
1111 | { | 1091 | { |
1112 | _fi.ATime.Write_To_FiTime(pt.ATime); | 1092 | fi.ATime.Write_To_FiTime(pt.ATime); |
1113 | pt.ATime_Defined = true; | 1093 | pt.ATime_Defined = true; |
1114 | } | 1094 | } |
1115 | } | 1095 | } |
@@ -1120,6 +1100,7 @@ void CArchiveExtractCallback::CreateFolders() | |||
1120 | // 21.04 : we don't change original (_item.PathParts) here | 1100 | // 21.04 : we don't change original (_item.PathParts) here |
1121 | UStringVector pathParts = _item.PathParts; | 1101 | UStringVector pathParts = _item.PathParts; |
1122 | 1102 | ||
1103 | bool isFinal = true; | ||
1123 | // bool is_DirOp = false; | 1104 | // bool is_DirOp = false; |
1124 | if (!pathParts.IsEmpty()) | 1105 | if (!pathParts.IsEmpty()) |
1125 | { | 1106 | { |
@@ -1129,12 +1110,15 @@ void CArchiveExtractCallback::CreateFolders() | |||
1129 | but if we create dir item here, it's not problem. */ | 1110 | but if we create dir item here, it's not problem. */ |
1130 | if (!_item.IsDir | 1111 | if (!_item.IsDir |
1131 | #ifdef SUPPORT_LINKS | 1112 | #ifdef SUPPORT_LINKS |
1132 | #ifndef WIN32 | 1113 | // #ifndef WIN32 |
1133 | || !_link.linkPath.IsEmpty() | 1114 | || !_link.LinkPath.IsEmpty() |
1134 | #endif | 1115 | // #endif |
1135 | #endif | 1116 | #endif |
1136 | ) | 1117 | ) |
1118 | { | ||
1137 | pathParts.DeleteBack(); | 1119 | pathParts.DeleteBack(); |
1120 | isFinal = false; // last path part was excluded | ||
1121 | } | ||
1138 | // else is_DirOp = true; | 1122 | // else is_DirOp = true; |
1139 | } | 1123 | } |
1140 | 1124 | ||
@@ -1158,7 +1142,7 @@ void CArchiveExtractCallback::CreateFolders() | |||
1158 | */ | 1142 | */ |
1159 | 1143 | ||
1160 | FString fullPathNew; | 1144 | FString fullPathNew; |
1161 | CreateComplexDirectory(pathParts, fullPathNew); | 1145 | CreateComplexDirectory(pathParts, isFinal, fullPathNew); |
1162 | 1146 | ||
1163 | /* | 1147 | /* |
1164 | if (is_DirOp) | 1148 | if (is_DirOp) |
@@ -1179,12 +1163,12 @@ void CArchiveExtractCallback::CreateFolders() | |||
1179 | return; | 1163 | return; |
1180 | 1164 | ||
1181 | CDirPathTime pt; | 1165 | CDirPathTime pt; |
1182 | GetFiTimesCAM(pt); | 1166 | GetFiTimesCAM(_fi, pt, *_arc); |
1183 | 1167 | ||
1184 | if (pt.IsSomeTimeDefined()) | 1168 | if (pt.IsSomeTimeDefined()) |
1185 | { | 1169 | { |
1186 | pt.Path = fullPathNew; | 1170 | pt.Path = fullPathNew; |
1187 | pt.SetDirTime(); | 1171 | pt.SetDirTime_to_FS_2(); |
1188 | _extractedFolders.Add(pt); | 1172 | _extractedFolders.Add(pt); |
1189 | } | 1173 | } |
1190 | } | 1174 | } |
@@ -1269,8 +1253,7 @@ HRESULT CArchiveExtractCallback::CheckExistFile(FString &fullProcessedPath, bool | |||
1269 | // MyMoveFile can rename folders. So it's OK to use it for folders too | 1253 | // MyMoveFile can rename folders. So it's OK to use it for folders too |
1270 | if (!MyMoveFile(fullProcessedPath, existPath)) | 1254 | if (!MyMoveFile(fullProcessedPath, existPath)) |
1271 | { | 1255 | { |
1272 | HRESULT errorCode = GetLastError_noZero_HRESULT(); | 1256 | RINOK(SendMessageError2_with_LastError(kCantRenameFile, existPath, fullProcessedPath)) |
1273 | RINOK(SendMessageError2(errorCode, kCantRenameFile, existPath, fullProcessedPath)) | ||
1274 | return E_FAIL; | 1257 | return E_FAIL; |
1275 | } | 1258 | } |
1276 | } | 1259 | } |
@@ -1302,7 +1285,7 @@ HRESULT CArchiveExtractCallback::CheckExistFile(FString &fullProcessedPath, bool | |||
1302 | { | 1285 | { |
1303 | #if defined(_WIN32) && !defined(UNDER_CE) | 1286 | #if defined(_WIN32) && !defined(UNDER_CE) |
1304 | // we need to clear READ-ONLY of parent before creating alt stream | 1287 | // we need to clear READ-ONLY of parent before creating alt stream |
1305 | int colonPos = NName::FindAltStreamColon(fullProcessedPath); | 1288 | const int colonPos = NName::FindAltStreamColon(fullProcessedPath); |
1306 | if (colonPos >= 0 && fullProcessedPath[(unsigned)colonPos + 1] != 0) | 1289 | if (colonPos >= 0 && fullProcessedPath[(unsigned)colonPos + 1] != 0) |
1307 | { | 1290 | { |
1308 | FString parentFsPath (fullProcessedPath); | 1291 | FString parentFsPath (fullProcessedPath); |
@@ -1311,7 +1294,11 @@ HRESULT CArchiveExtractCallback::CheckExistFile(FString &fullProcessedPath, bool | |||
1311 | if (parentFi.Find(parentFsPath)) | 1294 | if (parentFi.Find(parentFsPath)) |
1312 | { | 1295 | { |
1313 | if (parentFi.IsReadOnly()) | 1296 | if (parentFi.IsReadOnly()) |
1297 | { | ||
1298 | _altStream_NeedRestore_Attrib_for_parentFsPath = parentFsPath; | ||
1299 | _altStream_NeedRestore_AttribVal = parentFi.Attrib; | ||
1314 | SetFileAttrib(parentFsPath, parentFi.Attrib & ~(DWORD)FILE_ATTRIBUTE_READONLY); | 1300 | SetFileAttrib(parentFsPath, parentFi.Attrib & ~(DWORD)FILE_ATTRIBUTE_READONLY); |
1301 | } | ||
1315 | } | 1302 | } |
1316 | } | 1303 | } |
1317 | #endif // defined(_WIN32) && !defined(UNDER_CE) | 1304 | #endif // defined(_WIN32) && !defined(UNDER_CE) |
@@ -1323,9 +1310,11 @@ HRESULT CArchiveExtractCallback::CheckExistFile(FString &fullProcessedPath, bool | |||
1323 | 1310 | ||
1324 | 1311 | ||
1325 | 1312 | ||
1326 | 1313 | /* | |
1327 | 1314 | return: | |
1328 | 1315 | needExit = false: caller will use (outStreamLoc) and _hashStreamSpec | |
1316 | needExit = true : caller will not use (outStreamLoc) and _hashStreamSpec. | ||
1317 | */ | ||
1329 | HRESULT CArchiveExtractCallback::GetExtractStream(CMyComPtr<ISequentialOutStream> &outStreamLoc, bool &needExit) | 1318 | HRESULT CArchiveExtractCallback::GetExtractStream(CMyComPtr<ISequentialOutStream> &outStreamLoc, bool &needExit) |
1330 | { | 1319 | { |
1331 | needExit = true; | 1320 | needExit = true; |
@@ -1333,7 +1322,7 @@ HRESULT CArchiveExtractCallback::GetExtractStream(CMyComPtr<ISequentialOutStream | |||
1333 | RINOK(Read_fi_Props()) | 1322 | RINOK(Read_fi_Props()) |
1334 | 1323 | ||
1335 | #ifdef SUPPORT_LINKS | 1324 | #ifdef SUPPORT_LINKS |
1336 | IInArchive *archive = _arc->Archive; | 1325 | IInArchive * const archive = _arc->Archive; |
1337 | #endif | 1326 | #endif |
1338 | 1327 | ||
1339 | const UInt32 index = _index; | 1328 | const UInt32 index = _index; |
@@ -1379,7 +1368,7 @@ HRESULT CArchiveExtractCallback::GetExtractStream(CMyComPtr<ISequentialOutStream | |||
1379 | if (isAnti) | 1368 | if (isAnti) |
1380 | RemoveDir(_diskFilePath); | 1369 | RemoveDir(_diskFilePath); |
1381 | #ifdef SUPPORT_LINKS | 1370 | #ifdef SUPPORT_LINKS |
1382 | if (_link.linkPath.IsEmpty()) | 1371 | if (_link.LinkPath.IsEmpty()) |
1383 | #endif | 1372 | #endif |
1384 | { | 1373 | { |
1385 | if (!isAnti) | 1374 | if (!isAnti) |
@@ -1408,18 +1397,21 @@ HRESULT CArchiveExtractCallback::GetExtractStream(CMyComPtr<ISequentialOutStream | |||
1408 | 1397 | ||
1409 | #ifdef SUPPORT_LINKS | 1398 | #ifdef SUPPORT_LINKS |
1410 | 1399 | ||
1411 | if (!_link.linkPath.IsEmpty()) | 1400 | if (!_link.LinkPath.IsEmpty()) |
1412 | { | 1401 | { |
1413 | #ifndef UNDER_CE | 1402 | #ifndef UNDER_CE |
1414 | { | 1403 | { |
1415 | bool linkWasSet = false; | 1404 | bool linkWasSet = false; |
1416 | RINOK(SetFromLinkPath(fullProcessedPath, _link, linkWasSet)) | 1405 | RINOK(SetLink(fullProcessedPath, _link, linkWasSet)) |
1406 | /* | ||
1407 | // we don't set attributes for placeholder. | ||
1417 | if (linkWasSet) | 1408 | if (linkWasSet) |
1418 | { | 1409 | { |
1419 | _isSymLinkCreated = _link.IsSymLink(); | 1410 | _isSymLinkCreated = _link.Is_AnySymLink(); |
1420 | SetAttrib(); | 1411 | SetAttrib(); |
1421 | // printf("\nlinkWasSet %s\n", GetAnsiString(_diskFilePath)); | 1412 | // printf("\nlinkWasSet %s\n", GetAnsiString(_diskFilePath)); |
1422 | } | 1413 | } |
1414 | */ | ||
1423 | } | 1415 | } |
1424 | #endif // UNDER_CE | 1416 | #endif // UNDER_CE |
1425 | 1417 | ||
@@ -1445,16 +1437,17 @@ HRESULT CArchiveExtractCallback::GetExtractStream(CMyComPtr<ISequentialOutStream | |||
1445 | hl = fullProcessedPath; | 1437 | hl = fullProcessedPath; |
1446 | else | 1438 | else |
1447 | { | 1439 | { |
1448 | if (!MyCreateHardLink(fullProcessedPath, hl)) | 1440 | bool link_was_Created = false; |
1449 | { | 1441 | RINOK(CreateHardLink2(fullProcessedPath, hl, link_was_Created)) |
1450 | const HRESULT errorCode = GetLastError_noZero_HRESULT(); | 1442 | if (!link_was_Created) |
1451 | RINOK(SendMessageError2(errorCode, kCantCreateHardLink, fullProcessedPath, hl)) | ||
1452 | return S_OK; | 1443 | return S_OK; |
1453 | } | ||
1454 | |||
1455 | // printf("\nHard linkWasSet Archive_Get_HardLinkNode %s\n", GetAnsiString(_diskFilePath)); | 1444 | // printf("\nHard linkWasSet Archive_Get_HardLinkNode %s\n", GetAnsiString(_diskFilePath)); |
1456 | // _needSetAttrib = true; // do we need to set attribute ? | 1445 | // _needSetAttrib = true; // do we need to set attribute ? |
1457 | SetAttrib(); | 1446 | SetAttrib(); |
1447 | /* if we set (needExit = false) here, _hashStreamSpec will be used, | ||
1448 | and hash will be calulated for all hard links files (it's slower). | ||
1449 | But "Test" operation also calculates hashes. | ||
1450 | */ | ||
1458 | needExit = false; | 1451 | needExit = false; |
1459 | return S_OK; | 1452 | return S_OK; |
1460 | } | 1453 | } |
@@ -1483,7 +1476,7 @@ HRESULT CArchiveExtractCallback::GetExtractStream(CMyComPtr<ISequentialOutStream | |||
1483 | 1476 | ||
1484 | bool is_SymLink_in_Data = false; | 1477 | bool is_SymLink_in_Data = false; |
1485 | 1478 | ||
1486 | if (_curSize_Defined && _curSize > 0 && _curSize < (1 << 12)) | 1479 | if (_curSize_Defined && _curSize && _curSize < k_LinkDataSize_LIMIT) |
1487 | { | 1480 | { |
1488 | if (_fi.IsLinuxSymLink()) | 1481 | if (_fi.IsLinuxSymLink()) |
1489 | { | 1482 | { |
@@ -1505,7 +1498,7 @@ HRESULT CArchiveExtractCallback::GetExtractStream(CMyComPtr<ISequentialOutStream | |||
1505 | _bufPtrSeqOutStream_Spec->Init(_outMemBuf, _outMemBuf.Size()); | 1498 | _bufPtrSeqOutStream_Spec->Init(_outMemBuf, _outMemBuf.Size()); |
1506 | outStreamLoc = _bufPtrSeqOutStream; | 1499 | outStreamLoc = _bufPtrSeqOutStream; |
1507 | } | 1500 | } |
1508 | else // not reprase | 1501 | else // not reparse |
1509 | { | 1502 | { |
1510 | if (_ntOptions.PreAllocateOutFile && !_isSplit && _curSize_Defined && _curSize > (1 << 12)) | 1503 | if (_ntOptions.PreAllocateOutFile && !_isSplit && _curSize_Defined && _curSize > (1 << 12)) |
1511 | { | 1504 | { |
@@ -1560,7 +1553,7 @@ HRESULT CArchiveExtractCallback::GetExtractStream(CMyComPtr<ISequentialOutStream | |||
1560 | RINOK(outFileStream_Loc->Seek((Int64)_position, STREAM_SEEK_SET, NULL)) | 1553 | RINOK(outFileStream_Loc->Seek((Int64)_position, STREAM_SEEK_SET, NULL)) |
1561 | } | 1554 | } |
1562 | outStreamLoc = outFileStream_Loc; | 1555 | outStreamLoc = outFileStream_Loc; |
1563 | } // if not reprase | 1556 | } // if not reparse |
1564 | 1557 | ||
1565 | _outFileStream = outFileStream_Loc; | 1558 | _outFileStream = outFileStream_Loc; |
1566 | 1559 | ||
@@ -1607,37 +1600,36 @@ Z7_COM7F_IMF(CArchiveExtractCallback::GetStream(UInt32 index, ISequentialOutStre | |||
1607 | _bufPtrSeqOutStream.Release(); | 1600 | _bufPtrSeqOutStream.Release(); |
1608 | 1601 | ||
1609 | _encrypted = false; | 1602 | _encrypted = false; |
1610 | _position = 0; | ||
1611 | _isSplit = false; | 1603 | _isSplit = false; |
1612 | |||
1613 | _curSize = 0; | ||
1614 | _curSize_Defined = false; | 1604 | _curSize_Defined = false; |
1615 | _fileLength_WasSet = false; | 1605 | _fileLength_WasSet = false; |
1616 | _fileLength_that_WasSet = 0; | ||
1617 | _index = index; | ||
1618 | |||
1619 | _diskFilePath.Empty(); | ||
1620 | |||
1621 | _isRenamed = false; | 1606 | _isRenamed = false; |
1622 | |||
1623 | // _fi.Clear(); | 1607 | // _fi.Clear(); |
1624 | 1608 | _extractMode = false; | |
1625 | // _is_SymLink_in_Data = false; | ||
1626 | _is_SymLink_in_Data_Linux = false; | 1609 | _is_SymLink_in_Data_Linux = false; |
1627 | |||
1628 | _needSetAttrib = false; | 1610 | _needSetAttrib = false; |
1629 | _isSymLinkCreated = false; | 1611 | _isSymLinkCreated = false; |
1630 | _itemFailure = false; | 1612 | _itemFailure = false; |
1631 | |||
1632 | _some_pathParts_wereRemoved = false; | 1613 | _some_pathParts_wereRemoved = false; |
1633 | // _op_WasReported = false; | 1614 | // _op_WasReported = false; |
1634 | 1615 | ||
1616 | _position = 0; | ||
1617 | _curSize = 0; | ||
1618 | _fileLength_that_WasSet = 0; | ||
1619 | _index = index; | ||
1620 | |||
1621 | #if defined(_WIN32) && !defined(UNDER_CE) | ||
1622 | _altStream_NeedRestore_AttribVal = 0; | ||
1623 | _altStream_NeedRestore_Attrib_for_parentFsPath.Empty(); | ||
1624 | #endif | ||
1625 | |||
1626 | _diskFilePath.Empty(); | ||
1627 | |||
1635 | #ifdef SUPPORT_LINKS | 1628 | #ifdef SUPPORT_LINKS |
1636 | // _copyFile_Path.Empty(); | 1629 | // _copyFile_Path.Empty(); |
1637 | _link.Clear(); | 1630 | _link.Clear(); |
1638 | #endif | 1631 | #endif |
1639 | 1632 | ||
1640 | _extractMode = false; | ||
1641 | 1633 | ||
1642 | switch (askExtractMode) | 1634 | switch (askExtractMode) |
1643 | { | 1635 | { |
@@ -1653,7 +1645,7 @@ Z7_COM7F_IMF(CArchiveExtractCallback::GetStream(UInt32 index, ISequentialOutStre | |||
1653 | } | 1645 | } |
1654 | 1646 | ||
1655 | 1647 | ||
1656 | IInArchive *archive = _arc->Archive; | 1648 | IInArchive * const archive = _arc->Archive; |
1657 | 1649 | ||
1658 | RINOK(GetItem(index)) | 1650 | RINOK(GetItem(index)) |
1659 | 1651 | ||
@@ -1669,10 +1661,9 @@ Z7_COM7F_IMF(CArchiveExtractCallback::GetStream(UInt32 index, ISequentialOutStre | |||
1669 | } | 1661 | } |
1670 | } | 1662 | } |
1671 | 1663 | ||
1672 | #ifdef SUPPORT_LINKS | 1664 | #ifdef SUPPORT_LINKS |
1673 | RINOK(ReadLink()) | 1665 | RINOK(ReadLink()) |
1674 | #endif // SUPPORT_LINKS | 1666 | #endif |
1675 | |||
1676 | 1667 | ||
1677 | RINOK(Archive_GetItemBoolProp(archive, index, kpidEncrypted, _encrypted)) | 1668 | RINOK(Archive_GetItemBoolProp(archive, index, kpidEncrypted, _encrypted)) |
1678 | 1669 | ||
@@ -1692,6 +1683,19 @@ Z7_COM7F_IMF(CArchiveExtractCallback::GetStream(UInt32 index, ISequentialOutStre | |||
1692 | return S_OK; | 1683 | return S_OK; |
1693 | } | 1684 | } |
1694 | 1685 | ||
1686 | #if defined(_WIN32) && !defined(UNDER_CE) && !defined(Z7_SFX) | ||
1687 | if (askExtractMode == NArchive::NExtract::NAskMode::kExtract | ||
1688 | && !_testMode | ||
1689 | && _item.IsAltStream | ||
1690 | && ZoneBuf.Size() != 0 | ||
1691 | && Is_ZoneId_StreamName(_item.AltStreamName)) | ||
1692 | if (ZoneMode != NExtract::NZoneIdMode::kOffice | ||
1693 | || _item.PathParts.IsEmpty() | ||
1694 | || FindExt2(kOfficeExtensions, _item.PathParts.Back())) | ||
1695 | return S_OK; | ||
1696 | #endif | ||
1697 | |||
1698 | |||
1695 | #ifndef Z7_SFX | 1699 | #ifndef Z7_SFX |
1696 | if (_use_baseParentFolder_mode) | 1700 | if (_use_baseParentFolder_mode) |
1697 | { | 1701 | { |
@@ -1810,15 +1814,11 @@ Z7_COM7F_IMF(CArchiveExtractCallback::GetStream(UInt32 index, ISequentialOutStre | |||
1810 | 1814 | ||
1811 | if (ExtractToStreamCallback) | 1815 | if (ExtractToStreamCallback) |
1812 | { | 1816 | { |
1813 | if (!GetProp) | 1817 | CMyComPtr2_Create<IGetProp, CGetProp> GetProp; |
1814 | { | 1818 | GetProp->Arc = _arc; |
1815 | GetProp_Spec = new CGetProp; | 1819 | GetProp->IndexInArc = index; |
1816 | GetProp = GetProp_Spec; | ||
1817 | } | ||
1818 | GetProp_Spec->Arc = _arc; | ||
1819 | GetProp_Spec->IndexInArc = index; | ||
1820 | UString name (MakePathFromParts(pathParts)); | 1820 | UString name (MakePathFromParts(pathParts)); |
1821 | 1821 | // GetProp->BaseName = name; | |
1822 | #ifdef SUPPORT_ALT_STREAMS | 1822 | #ifdef SUPPORT_ALT_STREAMS |
1823 | if (_item.IsAltStream) | 1823 | if (_item.IsAltStream) |
1824 | { | 1824 | { |
@@ -1972,7 +1972,7 @@ HRESULT CArchiveExtractCallback::CloseFile() | |||
1972 | #endif | 1972 | #endif |
1973 | 1973 | ||
1974 | CFiTimesCAM t; | 1974 | CFiTimesCAM t; |
1975 | GetFiTimesCAM(t); | 1975 | GetFiTimesCAM(_fi, t, *_arc); |
1976 | 1976 | ||
1977 | // #ifdef _WIN32 | 1977 | // #ifdef _WIN32 |
1978 | if (t.IsSomeTimeDefined()) | 1978 | if (t.IsSomeTimeDefined()) |
@@ -1984,94 +1984,290 @@ HRESULT CArchiveExtractCallback::CloseFile() | |||
1984 | 1984 | ||
1985 | RINOK(_outFileStreamSpec->Close()) | 1985 | RINOK(_outFileStreamSpec->Close()) |
1986 | _outFileStream.Release(); | 1986 | _outFileStream.Release(); |
1987 | |||
1988 | #if defined(_WIN32) && !defined(UNDER_CE) | ||
1989 | if (!_altStream_NeedRestore_Attrib_for_parentFsPath.IsEmpty()) | ||
1990 | { | ||
1991 | SetFileAttrib(_altStream_NeedRestore_Attrib_for_parentFsPath, _altStream_NeedRestore_AttribVal); | ||
1992 | _altStream_NeedRestore_Attrib_for_parentFsPath.Empty(); | ||
1993 | } | ||
1994 | #endif | ||
1995 | |||
1987 | return hres; | 1996 | return hres; |
1988 | } | 1997 | } |
1989 | 1998 | ||
1990 | 1999 | ||
1991 | #ifdef SUPPORT_LINKS | 2000 | #ifdef SUPPORT_LINKS |
1992 | 2001 | ||
2002 | static bool CheckLinkPath_in_FS_for_pathParts(const FString &path, const UStringVector &v) | ||
2003 | { | ||
2004 | FString path2 = path; | ||
2005 | FOR_VECTOR (i, v) | ||
2006 | { | ||
2007 | // if (i == v.Size() - 1) path = path2; // we don't need last part in returned path | ||
2008 | path2 += us2fs(v[i]); | ||
2009 | NFind::CFileInfo fi; | ||
2010 | // printf("\nCheckLinkPath_in_FS_for_pathParts(): %s\n", GetOemString(path2).Ptr()); | ||
2011 | if (fi.Find(path2) && fi.IsOsSymLink()) | ||
2012 | return false; | ||
2013 | path2.Add_PathSepar(); | ||
2014 | } | ||
2015 | return true; | ||
2016 | } | ||
2017 | |||
2018 | /* | ||
2019 | link.isRelative / relative_item_PathPrefix | ||
2020 | false / empty | ||
2021 | true / item path without last part | ||
2022 | */ | ||
2023 | static bool CheckLinkPath_in_FS( | ||
2024 | const FString &pathPrefix_in_FS, | ||
2025 | const CPostLink &postLink, | ||
2026 | const UString &relative_item_PathPrefix) | ||
2027 | { | ||
2028 | const CLinkInfo &link = postLink.LinkInfo; | ||
2029 | if (postLink.item_PathParts.IsEmpty() || link.LinkPath.IsEmpty()) | ||
2030 | return false; | ||
2031 | FString path; | ||
2032 | { | ||
2033 | const UString &s = postLink.item_PathParts[0]; | ||
2034 | if (!s.IsEmpty() && !NName::IsAbsolutePath(s)) | ||
2035 | path = pathPrefix_in_FS; // item_PathParts is relative. So we use absolutre prefix | ||
2036 | } | ||
2037 | if (!CheckLinkPath_in_FS_for_pathParts(path, postLink.item_PathParts)) | ||
2038 | return false; | ||
2039 | path += us2fs(relative_item_PathPrefix); | ||
2040 | UStringVector v; | ||
2041 | SplitPathToParts(link.LinkPath, v); | ||
2042 | // we check target paths: | ||
2043 | return CheckLinkPath_in_FS_for_pathParts(path, v); | ||
2044 | } | ||
1993 | 2045 | ||
1994 | HRESULT CArchiveExtractCallback::SetFromLinkPath( | 2046 | static const unsigned k_DangLevel_MAX_for_Link_over_Link = 9; |
1995 | const FString &fullProcessedPath, | 2047 | |
1996 | const CLinkInfo &linkInfo, | 2048 | HRESULT CArchiveExtractCallback::CreateHardLink2( |
1997 | bool &linkWasSet) | 2049 | const FString &newFilePath, const FString &existFilePath, bool &link_was_Created) const |
2050 | { | ||
2051 | link_was_Created = false; | ||
2052 | if (_ntOptions.SymLinks_DangerousLevel <= k_DangLevel_MAX_for_Link_over_Link) | ||
2053 | { | ||
2054 | NFind::CFileInfo fi; | ||
2055 | if (fi.Find(existFilePath) && fi.IsOsSymLink()) | ||
2056 | return SendMessageError2(0, k_HardLink_to_SymLink_Ignored, newFilePath, existFilePath); | ||
2057 | } | ||
2058 | if (!MyCreateHardLink(newFilePath, existFilePath)) | ||
2059 | return SendMessageError2_with_LastError(kCantCreateHardLink, newFilePath, existFilePath); | ||
2060 | link_was_Created = true; | ||
2061 | return S_OK; | ||
2062 | } | ||
2063 | |||
2064 | |||
2065 | |||
2066 | HRESULT CArchiveExtractCallback::SetLink( | ||
2067 | const FString &fullProcessedPath_from, | ||
2068 | const CLinkInfo &link, | ||
2069 | bool &linkWasSet) // placeholder was created | ||
1998 | { | 2070 | { |
1999 | linkWasSet = false; | 2071 | linkWasSet = false; |
2000 | if (!_ntOptions.SymLinks.Val && !linkInfo.isHardLink) | 2072 | if (link.LinkPath.IsEmpty()) |
2073 | return S_OK; | ||
2074 | if (!_ntOptions.SymLinks.Val && link.Is_AnySymLink()) | ||
2001 | return S_OK; | 2075 | return S_OK; |
2076 | CPostLink postLink; | ||
2077 | postLink.Index_in_Arc = _index; | ||
2078 | postLink.item_IsDir = _item.IsDir; | ||
2079 | postLink.item_Path = _item.Path; | ||
2080 | postLink.item_PathParts = _item.PathParts; | ||
2081 | postLink.item_FileInfo = _fi; | ||
2082 | postLink.fullProcessedPath_from = fullProcessedPath_from; | ||
2083 | postLink.LinkInfo = link; | ||
2084 | _postLinks.Add(postLink); | ||
2085 | |||
2086 | // file doesn't exist in most cases. So we don't check for error. | ||
2087 | DeleteLinkFileAlways_or_RemoveEmptyDir(fullProcessedPath_from, false); // checkThatFileIsEmpty = false | ||
2002 | 2088 | ||
2003 | UString relatPath; | 2089 | NIO::COutFile outFile; |
2090 | if (!outFile.Create_NEW(fullProcessedPath_from)) | ||
2091 | return SendMessageError("Cannot create temporary link file", fullProcessedPath_from); | ||
2092 | #if 0 // 1 for debug | ||
2093 | // here we can write link path to temporary link file placeholder, | ||
2094 | // but empty placeholder is better, because we don't want to get any non-eampty data instead of link file. | ||
2095 | AString s; | ||
2096 | ConvertUnicodeToUTF8(link.LinkPath, s); | ||
2097 | outFile.WriteFull(s, s.Len()); | ||
2098 | #endif | ||
2099 | linkWasSet = true; | ||
2100 | return S_OK; | ||
2101 | } | ||
2004 | 2102 | ||
2005 | /* if (linkInfo.isRelative) | 2103 | |
2006 | linkInfo.linkPath is final link path that must be stored to file link field | 2104 | // if file/dir is symbolic link it will remove only link itself |
2007 | else | 2105 | HRESULT CArchiveExtractCallback::DeleteLinkFileAlways_or_RemoveEmptyDir( |
2008 | linkInfo.linkPath is path from root of archive. So we must add _dirPathPrefix_Full before linkPath. | 2106 | const FString &path, bool checkThatFileIsEmpty) const |
2009 | */ | 2107 | { |
2010 | 2108 | NFile::NFind::CFileInfo fi; | |
2011 | if (linkInfo.isRelative) | 2109 | if (fi.Find(path)) // followLink = false |
2012 | relatPath = GetDirPrefixOf(_item.Path); | ||
2013 | relatPath += linkInfo.linkPath; | ||
2014 | |||
2015 | if (!IsSafePath(relatPath)) | ||
2016 | { | 2110 | { |
2017 | return SendMessageError2( | 2111 | if (fi.IsDir()) |
2018 | 0, // errorCode | 2112 | { |
2019 | "Dangerous link path was ignored", | 2113 | if (RemoveDirAlways_if_Empty(path)) |
2020 | us2fs(_item.Path), | 2114 | return S_OK; |
2021 | us2fs(linkInfo.linkPath)); // us2fs(relatPath) | 2115 | } |
2116 | else | ||
2117 | { | ||
2118 | // link file placeholder must be empty | ||
2119 | if (checkThatFileIsEmpty && !fi.IsOsSymLink() && fi.Size != 0) | ||
2120 | return SendMessageError("Temporary link file is not empty", path); | ||
2121 | if (DeleteFileAlways(path)) | ||
2122 | return S_OK; | ||
2123 | } | ||
2124 | if (GetLastError() != ERROR_FILE_NOT_FOUND) | ||
2125 | return SendMessageError_with_LastError( | ||
2126 | fi.IsDir() ? | ||
2127 | k_CantDelete_Dir_for_SymLink: | ||
2128 | k_CantDelete_File_for_SymLink, | ||
2129 | path); | ||
2022 | } | 2130 | } |
2131 | return S_OK; | ||
2132 | } | ||
2133 | |||
2134 | |||
2135 | /* | ||
2136 | in: | ||
2137 | link.LinkPath : must be relative (non-absolute) path in any case !!! | ||
2138 | link.isRelative / target path that must stored as created link: | ||
2139 | == false / _dirPathPrefix_Full + link.LinkPath | ||
2140 | == true / link.LinkPath | ||
2141 | */ | ||
2142 | static HRESULT SetLink2(const CArchiveExtractCallback &callback, | ||
2143 | const CPostLink &postLink, bool &linkWasSet) | ||
2144 | { | ||
2145 | const CLinkInfo &link = postLink.LinkInfo; | ||
2146 | const FString &fullProcessedPath_from = postLink.fullProcessedPath_from; // full file path in FS (fullProcessedPath_from) | ||
2023 | 2147 | ||
2024 | FString existPath; | 2148 | const unsigned level = callback._ntOptions.SymLinks_DangerousLevel; |
2025 | if (linkInfo.isHardLink /* || linkInfo.IsCopyLink */ || !linkInfo.isRelative) | 2149 | if (level < 20) |
2026 | { | 2150 | { |
2027 | if (!NName::GetFullPath(_dirPathPrefix_Full, us2fs(relatPath), existPath)) | 2151 | /* |
2152 | We want to use additional check for links that can link to directory. | ||
2153 | - linux: all symbolic links are files. | ||
2154 | - windows: we can have file/directory symbolic link, | ||
2155 | but file symbolic link works like directory link in windows. | ||
2156 | So we use additional check for all relative links. | ||
2157 | |||
2158 | We don't allow decreasing of final level of link. | ||
2159 | So if some another extracted file will use this link, | ||
2160 | then number of real path parts (after link redirection) cannot be | ||
2161 | smaller than number of requested path parts from archive records. | ||
2162 | |||
2163 | here we check only (link.LinkPath) without (_item.PathParts). | ||
2164 | */ | ||
2165 | CLinkLevelsInfo li; | ||
2166 | li.Parse(link.LinkPath, link.Is_WSL()); | ||
2167 | bool isDang; | ||
2168 | UString relativePathPrefix; | ||
2169 | if (li.IsAbsolute // unexpected | ||
2170 | || li.ParentDirDots_after_NonParent | ||
2171 | || (level <= 5 && link.isRelative && li.FinalLevel < 1) // final level lower | ||
2172 | || (level <= 5 && link.isRelative && li.LowLevel < 0) // negative temporary levels | ||
2173 | ) | ||
2174 | isDang = true; | ||
2175 | else // if (!isDang) | ||
2028 | { | 2176 | { |
2029 | RINOK(SendMessageError("Incorrect path", us2fs(relatPath))) | 2177 | UString path; |
2030 | } | 2178 | if (link.isRelative) |
2179 | { | ||
2180 | // item_PathParts : parts that will be created in output folder. | ||
2181 | // we want to get directory prefix of link item. | ||
2182 | // so we remove file name (last non-empty part) from PathParts: | ||
2183 | UStringVector v = postLink.item_PathParts; | ||
2184 | while (!v.IsEmpty()) | ||
2185 | { | ||
2186 | const unsigned len = v.Back().Len(); | ||
2187 | v.DeleteBack(); | ||
2188 | if (len) | ||
2189 | break; | ||
2190 | } | ||
2191 | path = MakePathFromParts(v); | ||
2192 | NName::NormalizeDirPathPrefix(path); | ||
2193 | relativePathPrefix = path; | ||
2194 | } | ||
2195 | path += link.LinkPath; | ||
2196 | /* | ||
2197 | path is calculated virtual target path of link | ||
2198 | path is relative to root folder of extracted items | ||
2199 | if (!link.isRelative), then (path == link.LinkPath) | ||
2200 | */ | ||
2201 | isDang = false; | ||
2202 | if (!IsSafePath(path, link.Is_WSL())) | ||
2203 | isDang = true; | ||
2204 | } | ||
2205 | const char *message = NULL; | ||
2206 | if (isDang) | ||
2207 | message = "Dangerous link path was ignored"; | ||
2208 | else if (level <= k_DangLevel_MAX_for_Link_over_Link | ||
2209 | && !CheckLinkPath_in_FS(callback._dirPathPrefix_Full, | ||
2210 | postLink, relativePathPrefix)) | ||
2211 | message = "Dangerous link via another link was ignored"; | ||
2212 | if (message) | ||
2213 | return callback.SendMessageError2(0, // errorCode | ||
2214 | message, us2fs(postLink.item_Path), us2fs(link.LinkPath)); | ||
2215 | } | ||
2216 | |||
2217 | FString target; // target path that will be stored to link field | ||
2218 | if (link.Is_HardLink() /* || link.IsCopyLink */ || !link.isRelative) | ||
2219 | { | ||
2220 | // isRelative == false | ||
2221 | // all hard links and absolute symbolic links | ||
2222 | // relatPath == link.LinkPath | ||
2223 | // we get absolute link path for target: | ||
2224 | if (!NName::GetFullPath(callback._dirPathPrefix_Full, us2fs(link.LinkPath), target)) | ||
2225 | return callback.SendMessageError("Incorrect link path", us2fs(link.LinkPath)); | ||
2226 | // (target) is (_dirPathPrefix_Full + relatPath) | ||
2031 | } | 2227 | } |
2032 | else | 2228 | else |
2033 | { | 2229 | { |
2034 | existPath = us2fs(linkInfo.linkPath); | 2230 | // link.isRelative == true |
2035 | // printf("\nlinkPath = : %s\n", GetOemString(linkInfo.linkPath).Ptr()); | 2231 | // relative symbolic links only |
2232 | target = us2fs(link.LinkPath); | ||
2036 | } | 2233 | } |
2037 | 2234 | if (target.IsEmpty()) | |
2038 | if (existPath.IsEmpty()) | 2235 | return callback.SendMessageError("Empty link", fullProcessedPath_from); |
2039 | return SendMessageError("Empty link", fullProcessedPath); | ||
2040 | 2236 | ||
2041 | if (linkInfo.isHardLink /* || linkInfo.IsCopyLink */) | 2237 | if (link.Is_HardLink() /* || link.IsCopyLink */) |
2042 | { | 2238 | { |
2043 | // if (linkInfo.isHardLink) | 2239 | // if (link.isHardLink) |
2044 | { | 2240 | { |
2045 | if (!MyCreateHardLink(fullProcessedPath, existPath)) | 2241 | RINOK(callback.DeleteLinkFileAlways_or_RemoveEmptyDir(fullProcessedPath_from, true)) // checkThatFileIsEmpty |
2046 | { | 2242 | { |
2047 | const HRESULT errorCode = GetLastError_noZero_HRESULT(); | 2243 | // RINOK(SendMessageError_with_LastError(k_Cant_DeleteTempLinkFile, fullProcessedPath_from)) |
2048 | RINOK(SendMessageError2(errorCode, kCantCreateHardLink, fullProcessedPath, existPath)) | ||
2049 | } | 2244 | } |
2245 | return callback.CreateHardLink2(fullProcessedPath_from, target, linkWasSet); | ||
2050 | /* | 2246 | /* |
2051 | RINOK(PrepareOperation(NArchive::NExtract::NAskMode::kExtract)) | 2247 | RINOK(PrepareOperation(NArchive::NExtract::NAskMode::kExtract)) |
2052 | _op_WasReported = true; | 2248 | _op_WasReported = true; |
2053 | RINOK(SetOperationResult(NArchive::NExtract::NOperationResult::kOK)) | 2249 | RINOK(SetOperationResult(NArchive::NExtract::NOperationResult::kOK)) |
2054 | */ | ||
2055 | linkWasSet = true; | 2250 | linkWasSet = true; |
2056 | return S_OK; | 2251 | return S_OK; |
2252 | */ | ||
2057 | } | 2253 | } |
2058 | /* | 2254 | /* |
2059 | // IsCopyLink | 2255 | // IsCopyLink |
2060 | { | 2256 | { |
2061 | NFind::CFileInfo fi; | 2257 | NFind::CFileInfo fi; |
2062 | if (!fi.Find(existPath)) | 2258 | if (!fi.Find(target)) |
2063 | { | 2259 | { |
2064 | RINOK(SendMessageError2("Cannot find the file for copying", existPath, fullProcessedPath)); | 2260 | RINOK(SendMessageError2("Cannot find the file for copying", target, fullProcessedPath)); |
2065 | } | 2261 | } |
2066 | else | 2262 | else |
2067 | { | 2263 | { |
2068 | if (_curSize_Defined && _curSize == fi.Size) | 2264 | if (_curSize_Defined && _curSize == fi.Size) |
2069 | _copyFile_Path = existPath; | 2265 | _copyFile_Path = target; |
2070 | else | 2266 | else |
2071 | { | 2267 | { |
2072 | RINOK(SendMessageError2("File size collision for file copying", existPath, fullProcessedPath)); | 2268 | RINOK(SendMessageError2("File size collision for file copying", target, fullProcessedPath)); |
2073 | } | 2269 | } |
2074 | // RINOK(MyCopyFile(existPath, fullProcessedPath)); | 2270 | // RINOK(MyCopyFile(target, fullProcessedPath)); |
2075 | } | 2271 | } |
2076 | } | 2272 | } |
2077 | */ | 2273 | */ |
@@ -2085,127 +2281,227 @@ HRESULT CArchiveExtractCallback::SetFromLinkPath( | |||
2085 | // Windows before Vista doesn't support symbolic links. | 2281 | // Windows before Vista doesn't support symbolic links. |
2086 | // we could convert such symbolic links to Junction Points | 2282 | // we could convert such symbolic links to Junction Points |
2087 | // isJunction = true; | 2283 | // isJunction = true; |
2088 | // convertToAbs = true; | ||
2089 | } | 2284 | } |
2090 | */ | 2285 | */ |
2091 | 2286 | ||
2092 | if (!_ntOptions.SymLinks_AllowDangerous.Val) | 2287 | #ifdef _WIN32 |
2093 | { | 2288 | const bool isDir = (postLink.item_IsDir || link.LinkType == k_LinkType_Junction); |
2094 | #ifdef _WIN32 | 2289 | #endif |
2095 | if (_item.IsDir) | ||
2096 | #endif | ||
2097 | if (linkInfo.isRelative) | ||
2098 | { | ||
2099 | CLinkLevelsInfo levelsInfo; | ||
2100 | levelsInfo.Parse(linkInfo.linkPath); | ||
2101 | if (levelsInfo.FinalLevel < 1 || levelsInfo.IsAbsolute) | ||
2102 | { | ||
2103 | return SendMessageError2( | ||
2104 | 0, // errorCode | ||
2105 | "Dangerous symbolic link path was ignored", | ||
2106 | us2fs(_item.Path), | ||
2107 | us2fs(linkInfo.linkPath)); | ||
2108 | } | ||
2109 | } | ||
2110 | } | ||
2111 | 2290 | ||
2112 | 2291 | ||
2113 | #ifdef _WIN32 | 2292 | #ifdef _WIN32 |
2114 | |||
2115 | CByteBuffer data; | 2293 | CByteBuffer data; |
2116 | // printf("\nFillLinkData(): %s\n", GetOemString(existPath).Ptr()); | 2294 | // printf("\nFillLinkData(): %s\n", GetOemString(target).Ptr()); |
2117 | if (!FillLinkData(data, fs2us(existPath), !linkInfo.isJunction, linkInfo.isWSL)) | 2295 | if (link.Is_WSL()) |
2118 | return SendMessageError("Cannot fill link data", us2fs(_item.Path)); | ||
2119 | |||
2120 | /* | ||
2121 | if (NtReparse_Size != data.Size() || memcmp(NtReparse_Data, data, data.Size()) != 0) | ||
2122 | { | 2296 | { |
2123 | SendMessageError("reconstructed Reparse is different", fs2us(existPath)); | 2297 | Convert_WinPath_to_WslLinuxPath(target, !link.isRelative); |
2298 | FillLinkData_WslLink(data, fs2us(target)); | ||
2124 | } | 2299 | } |
2300 | else | ||
2301 | FillLinkData_WinLink(data, fs2us(target), link.LinkType != k_LinkType_Junction); | ||
2302 | if (data.Size() == 0) | ||
2303 | return callback.SendMessageError("Cannot fill link data", us2fs(postLink.item_Path)); | ||
2304 | /* | ||
2305 | if (NtReparse_Size != data.Size() || memcmp(NtReparse_Data, data, data.Size()) != 0) | ||
2306 | SendMessageError("reconstructed Reparse is different", fs2us(target)); | ||
2125 | */ | 2307 | */ |
2126 | |||
2127 | CReparseAttr attr; | ||
2128 | if (!attr.Parse(data, data.Size())) | ||
2129 | { | 2308 | { |
2130 | RINOK(SendMessageError("Internal error for symbolic link file", us2fs(_item.Path))) | 2309 | // we check that reparse data is correct, but we ignore attr.MinorError. |
2131 | return S_OK; | 2310 | CReparseAttr attr; |
2132 | } | 2311 | if (!attr.Parse(data, data.Size())) |
2133 | if (!NFile::NIO::SetReparseData(fullProcessedPath, _item.IsDir, data, (DWORD)data.Size())) | 2312 | return callback.SendMessageError("Internal error for symbolic link file", us2fs(postLink.item_Path)); |
2134 | { | ||
2135 | RINOK(SendMessageError_with_LastError(kCantCreateSymLink, fullProcessedPath)) | ||
2136 | return S_OK; | ||
2137 | } | 2313 | } |
2138 | linkWasSet = true; | 2314 | #endif |
2139 | |||
2140 | return S_OK; | ||
2141 | |||
2142 | |||
2143 | #else // ! _WIN32 | ||
2144 | 2315 | ||
2145 | if (!NFile::NIO::SetSymLink(fullProcessedPath, existPath)) | 2316 | RINOK(callback.DeleteLinkFileAlways_or_RemoveEmptyDir(fullProcessedPath_from, true)) // checkThatFileIsEmpty |
2317 | #ifdef _WIN32 | ||
2318 | if (!NFile::NIO::SetReparseData(fullProcessedPath_from, isDir, data, (DWORD)data.Size())) | ||
2319 | #else // ! _WIN32 | ||
2320 | if (!NFile::NIO::SetSymLink(fullProcessedPath_from, target)) | ||
2321 | #endif // ! _WIN32 | ||
2146 | { | 2322 | { |
2147 | RINOK(SendMessageError_with_LastError(kCantCreateSymLink, fullProcessedPath)) | 2323 | return callback.SendMessageError_with_LastError(kCantCreateSymLink, fullProcessedPath_from); |
2148 | return S_OK; | ||
2149 | } | 2324 | } |
2150 | linkWasSet = true; | 2325 | linkWasSet = true; |
2151 | |||
2152 | return S_OK; | 2326 | return S_OK; |
2153 | |||
2154 | #endif // ! _WIN32 | ||
2155 | } | 2327 | } |
2156 | 2328 | ||
2157 | 2329 | ||
2158 | bool CLinkInfo::Parse(const Byte *data, size_t dataSize, bool isLinuxData) | ||
2159 | { | ||
2160 | Clear(); | ||
2161 | // this->isLinux = isLinuxData; | ||
2162 | |||
2163 | if (isLinuxData) | ||
2164 | { | ||
2165 | isJunction = false; | ||
2166 | isHardLink = false; | ||
2167 | AString utf; | ||
2168 | if (dataSize >= (1 << 12)) | ||
2169 | return false; | ||
2170 | utf.SetFrom_CalcLen((const char *)data, (unsigned)dataSize); | ||
2171 | UString u; | ||
2172 | if (!ConvertUTF8ToUnicode(utf, u)) | ||
2173 | return false; | ||
2174 | linkPath = u; | ||
2175 | |||
2176 | // in linux symbolic data: we expect that linux separator '/' is used | ||
2177 | // if windows link was created, then we also must use linux separator | ||
2178 | if (u.IsEmpty()) | ||
2179 | return false; | ||
2180 | const wchar_t c = u[0]; | ||
2181 | isRelative = !IS_PATH_SEPAR(c); | ||
2182 | return true; | ||
2183 | } | ||
2184 | 2330 | ||
2331 | bool CLinkInfo::Parse_from_WindowsReparseData(const Byte *data, size_t dataSize) | ||
2332 | { | ||
2185 | CReparseAttr reparse; | 2333 | CReparseAttr reparse; |
2186 | if (!reparse.Parse(data, dataSize)) | 2334 | if (!reparse.Parse(data, dataSize)) |
2187 | return false; | 2335 | return false; |
2188 | isHardLink = false; | 2336 | // const AString s = GetAnsiString(LinkPath); |
2189 | // isCopyLink = false; | 2337 | // printf("\nlinkPath: %s\n", s.Ptr()); |
2190 | linkPath = reparse.GetPath(); | 2338 | LinkPath = reparse.GetPath(); |
2191 | isJunction = reparse.IsMountPoint(); | ||
2192 | |||
2193 | if (reparse.IsSymLink_WSL()) | 2339 | if (reparse.IsSymLink_WSL()) |
2194 | { | 2340 | { |
2195 | isWSL = true; | 2341 | LinkType = k_LinkType_WSL; |
2196 | isRelative = reparse.IsRelative_WSL(); | 2342 | isRelative = reparse.IsRelative_WSL(); // detected from LinkPath[0] |
2343 | // LinkPath is original raw name converted to UString from AString | ||
2344 | // Linux separator '/' is expected here. | ||
2345 | REPLACE_SLASHES_from_Linux_to_Sys(LinkPath) | ||
2197 | } | 2346 | } |
2198 | else | 2347 | else |
2199 | isRelative = reparse.IsRelative_Win(); | 2348 | { |
2200 | 2349 | LinkType = reparse.IsMountPoint() ? k_LinkType_Junction : k_LinkType_PureSymLink; | |
2201 | // FIXME !!! | 2350 | isRelative = reparse.IsRelative_Win(); // detected by (Flags == Z7_WIN_SYMLINK_FLAG_RELATIVE) |
2202 | #ifndef _WIN32 | 2351 | isWindowsPath = true; |
2203 | linkPath.Replace(L'\\', WCHAR_PATH_SEPARATOR); | 2352 | // LinkPath is original windows link path from raparse data with \??\ prefix removed. |
2204 | #endif | 2353 | // windows '\\' separator is expected here. |
2205 | 2354 | // linux '/' separator is not expected here. | |
2355 | // we translate both types of separators to system separator. | ||
2356 | LinkPath.Replace( | ||
2357 | #if WCHAR_PATH_SEPARATOR == L'\\' | ||
2358 | L'/' | ||
2359 | #else | ||
2360 | L'\\' | ||
2361 | #endif | ||
2362 | , WCHAR_PATH_SEPARATOR); | ||
2363 | } | ||
2364 | // (LinkPath) uses system path separator. | ||
2365 | // windows: (LinkPath) doesn't contain linux separator (slash). | ||
2366 | return true; | ||
2367 | } | ||
2368 | |||
2369 | |||
2370 | bool CLinkInfo::Parse_from_LinuxData(const Byte *data, size_t dataSize) | ||
2371 | { | ||
2372 | // Clear(); // *this object was cleared by constructor already. | ||
2373 | LinkType = k_LinkType_PureSymLink; | ||
2374 | AString utf; | ||
2375 | if (dataSize >= k_LinkDataSize_LIMIT) | ||
2376 | return false; | ||
2377 | utf.SetFrom_CalcLen((const char *)data, (unsigned)dataSize); | ||
2378 | UString u; | ||
2379 | if (!ConvertUTF8ToUnicode(utf, u)) | ||
2380 | return false; | ||
2381 | if (u.IsEmpty()) | ||
2382 | return false; | ||
2383 | const wchar_t c = u[0]; | ||
2384 | isRelative = (c != L'/'); | ||
2385 | // linux path separator is expected | ||
2386 | REPLACE_SLASHES_from_Linux_to_Sys(u) | ||
2387 | LinkPath = u; | ||
2388 | // (LinkPath) uses system path separator. | ||
2389 | // windows: (LinkPath) doesn't contain linux separator (slash). | ||
2206 | return true; | 2390 | return true; |
2207 | } | 2391 | } |
2208 | 2392 | ||
2393 | |||
2394 | // in/out: (LinkPath) uses system path separator | ||
2395 | // in/out: windows: (LinkPath) doesn't contain linux separator (slash). | ||
2396 | // out: (LinkPath) is relative path, and LinkPath[0] is not path separator | ||
2397 | // out: isRelative changed to false, if any prefix was removed. | ||
2398 | // note: absolute windows links "c:\" to root will be reduced to empty string: | ||
2399 | void CLinkInfo::Remove_AbsPathPrefixes() | ||
2400 | { | ||
2401 | while (!LinkPath.IsEmpty()) | ||
2402 | { | ||
2403 | unsigned n = 0; | ||
2404 | if (!Is_WSL()) | ||
2405 | { | ||
2406 | n = | ||
2407 | #ifndef _WIN32 | ||
2408 | isWindowsPath ? | ||
2409 | NName::GetRootPrefixSize_WINDOWS(LinkPath) : | ||
2410 | #endif | ||
2411 | NName::GetRootPrefixSize(LinkPath); | ||
2412 | /* | ||
2413 | // "c:path" will be ignored later as "Dangerous absolute path" | ||
2414 | // so check is not required | ||
2415 | if (n == 0 | ||
2416 | #ifndef _WIN32 | ||
2417 | && isWindowsPath | ||
2418 | #endif | ||
2419 | && NName::IsDrivePath2(LinkPath)) | ||
2420 | n = 2; | ||
2421 | */ | ||
2422 | } | ||
2423 | if (n == 0) | ||
2424 | { | ||
2425 | if (!IS_PATH_SEPAR(LinkPath[0])) | ||
2426 | break; | ||
2427 | n = 1; | ||
2428 | } | ||
2429 | isRelative = false; // (LinkPath) will be treated as relative to root folder of archive | ||
2430 | LinkPath.DeleteFrontal(n); | ||
2431 | } | ||
2432 | } | ||
2433 | |||
2434 | |||
2435 | /* | ||
2436 | it removes redundant separators, if there are double separators, | ||
2437 | but it keeps double separators at start of string //name/. | ||
2438 | in/out: system path separator is used | ||
2439 | windows: slash character (linux separator) is not treated as separator | ||
2440 | windows: (path) doesn't contain linux separator (slash). | ||
2441 | */ | ||
2442 | static void RemoveRedundantPathSeparators(UString &path) | ||
2443 | { | ||
2444 | wchar_t *dest = path.GetBuf(); | ||
2445 | const wchar_t * const start = dest; | ||
2446 | const wchar_t *src = dest; | ||
2447 | for (;;) | ||
2448 | { | ||
2449 | wchar_t c = *src++; | ||
2450 | if (c == 0) | ||
2451 | break; | ||
2452 | // if (IS_PATH_SEPAR(c)) // for Windows: we can change (/) to (\). | ||
2453 | if (c == WCHAR_PATH_SEPARATOR) | ||
2454 | { | ||
2455 | if (dest - start >= 2 && dest[-1] == WCHAR_PATH_SEPARATOR) | ||
2456 | continue; | ||
2457 | // c = WCHAR_PATH_SEPARATOR; // for Windows: we can change (/) to (\). | ||
2458 | } | ||
2459 | *dest++ = c; | ||
2460 | } | ||
2461 | *dest = 0; | ||
2462 | path.ReleaseBuf_SetLen((unsigned)(dest - path.Ptr())); | ||
2463 | } | ||
2464 | |||
2465 | |||
2466 | // in/out: (LinkPath) uses system path separator | ||
2467 | // in/out: windows: (LinkPath) doesn't contain linux separator (slash). | ||
2468 | // out: (LinkPath) is relative path, and LinkPath[0] is not path separator | ||
2469 | void CLinkInfo::Normalize_to_RelativeSafe(UStringVector &removePathParts) | ||
2470 | { | ||
2471 | // We WILL NOT WRITE original absolute link path from archive to filesystem. | ||
2472 | // So here we remove all root prefixes from (LinkPath). | ||
2473 | // If we see any absolute root prefix, then we suppose that this prefix is virtual prefix | ||
2474 | // that shows that link is relative to root folder of archive | ||
2475 | RemoveRedundantPathSeparators(LinkPath); | ||
2476 | // LinkPath = "\\\\?\\r:test\\test2"; // for debug | ||
2477 | Remove_AbsPathPrefixes(); | ||
2478 | // (LinkPath) now is relative: | ||
2479 | // if (isRelative == false), then (LinkPath) is relative to root folder of archive | ||
2480 | // if (isRelative == true ), then (LinkPath) is relative to current item | ||
2481 | if (LinkPath.IsEmpty() || isRelative || removePathParts.Size() == 0) | ||
2482 | return; | ||
2483 | |||
2484 | // if LinkPath is prefixed by _removePathParts, we remove these paths | ||
2485 | UStringVector pathParts; | ||
2486 | SplitPathToParts(LinkPath, pathParts); | ||
2487 | bool badPrefix = false; | ||
2488 | { | ||
2489 | FOR_VECTOR (i, removePathParts) | ||
2490 | { | ||
2491 | if (i >= pathParts.Size() | ||
2492 | || CompareFileNames(removePathParts[i], pathParts[i]) != 0) | ||
2493 | { | ||
2494 | badPrefix = true; | ||
2495 | break; | ||
2496 | } | ||
2497 | } | ||
2498 | } | ||
2499 | if (!badPrefix) | ||
2500 | pathParts.DeleteFrontal(removePathParts.Size()); | ||
2501 | LinkPath = MakePathFromParts(pathParts); | ||
2502 | Remove_AbsPathPrefixes(); | ||
2503 | } | ||
2504 | |||
2209 | #endif // SUPPORT_LINKS | 2505 | #endif // SUPPORT_LINKS |
2210 | 2506 | ||
2211 | 2507 | ||
@@ -2213,12 +2509,12 @@ HRESULT CArchiveExtractCallback::CloseReparseAndFile() | |||
2213 | { | 2509 | { |
2214 | HRESULT res = S_OK; | 2510 | HRESULT res = S_OK; |
2215 | 2511 | ||
2216 | #ifdef SUPPORT_LINKS | 2512 | #ifdef SUPPORT_LINKS |
2217 | 2513 | ||
2218 | size_t reparseSize = 0; | 2514 | size_t reparseSize = 0; |
2219 | bool repraseMode = false; | 2515 | bool repraseMode = false; |
2220 | bool needSetReparse = false; | 2516 | bool needSetReparse = false; |
2221 | CLinkInfo linkInfo; | 2517 | CLinkInfo link; |
2222 | 2518 | ||
2223 | if (_bufPtrSeqOutStream) | 2519 | if (_bufPtrSeqOutStream) |
2224 | { | 2520 | { |
@@ -2232,15 +2528,19 @@ HRESULT CArchiveExtractCallback::CloseReparseAndFile() | |||
2232 | needSetReparse = reparse.Parse(_outMemBuf, reparseSize, errorCode); | 2528 | needSetReparse = reparse.Parse(_outMemBuf, reparseSize, errorCode); |
2233 | if (needSetReparse) | 2529 | if (needSetReparse) |
2234 | { | 2530 | { |
2235 | UString linkPath = reparse.GetPath(); | 2531 | UString LinkPath = reparse.GetPath(); |
2236 | #ifndef _WIN32 | 2532 | #ifndef _WIN32 |
2237 | linkPath.Replace(L'\\', WCHAR_PATH_SEPARATOR); | 2533 | LinkPath.Replace(L'\\', WCHAR_PATH_SEPARATOR); |
2238 | #endif | 2534 | #endif |
2239 | } | 2535 | } |
2240 | */ | 2536 | */ |
2241 | needSetReparse = linkInfo.Parse(_outMemBuf, reparseSize, _is_SymLink_in_Data_Linux); | 2537 | needSetReparse = _is_SymLink_in_Data_Linux ? |
2538 | link.Parse_from_LinuxData(_outMemBuf, reparseSize) : | ||
2539 | link.Parse_from_WindowsReparseData(_outMemBuf, reparseSize); | ||
2242 | if (!needSetReparse) | 2540 | if (!needSetReparse) |
2243 | res = SendMessageError_with_LastError("Incorrect reparse stream", us2fs(_item.Path)); | 2541 | res = SendMessageError_with_LastError("Incorrect reparse stream", us2fs(_item.Path)); |
2542 | // (link.LinkPath) uses system path separator. | ||
2543 | // windows: (link.LinkPath) doesn't contain linux separator (slash). | ||
2244 | } | 2544 | } |
2245 | else | 2545 | else |
2246 | { | 2546 | { |
@@ -2255,25 +2555,21 @@ HRESULT CArchiveExtractCallback::CloseReparseAndFile() | |||
2255 | _bufPtrSeqOutStream.Release(); | 2555 | _bufPtrSeqOutStream.Release(); |
2256 | } | 2556 | } |
2257 | 2557 | ||
2258 | #endif // SUPPORT_LINKS | 2558 | #endif // SUPPORT_LINKS |
2259 | |||
2260 | 2559 | ||
2261 | const HRESULT res2 = CloseFile(); | 2560 | const HRESULT res2 = CloseFile(); |
2262 | |||
2263 | if (res == S_OK) | 2561 | if (res == S_OK) |
2264 | res = res2; | 2562 | res = res2; |
2265 | |||
2266 | RINOK(res) | 2563 | RINOK(res) |
2267 | 2564 | ||
2268 | #ifdef SUPPORT_LINKS | 2565 | #ifdef SUPPORT_LINKS |
2269 | if (repraseMode) | 2566 | if (repraseMode) |
2270 | { | 2567 | { |
2271 | _curSize = reparseSize; | 2568 | _curSize = reparseSize; |
2272 | _curSize_Defined = true; | 2569 | _curSize_Defined = true; |
2273 | |||
2274 | #ifdef SUPPORT_LINKS | ||
2275 | if (needSetReparse) | 2570 | if (needSetReparse) |
2276 | { | 2571 | { |
2572 | // empty file was created so we must delete it. | ||
2277 | // in Linux : we must delete empty file before symbolic link creation | 2573 | // in Linux : we must delete empty file before symbolic link creation |
2278 | // in Windows : we can create symbolic link even without file deleting | 2574 | // in Windows : we can create symbolic link even without file deleting |
2279 | if (!DeleteFileAlways(_diskFilePath)) | 2575 | if (!DeleteFileAlways(_diskFilePath)) |
@@ -2281,42 +2577,57 @@ HRESULT CArchiveExtractCallback::CloseReparseAndFile() | |||
2281 | RINOK(SendMessageError_with_LastError("can't delete file", _diskFilePath)) | 2577 | RINOK(SendMessageError_with_LastError("can't delete file", _diskFilePath)) |
2282 | } | 2578 | } |
2283 | { | 2579 | { |
2284 | /* | ||
2285 | // for DEBUG ONLY: we can extract sym links as WSL links | ||
2286 | // to eliminate (non-admin) errors for sym links. | ||
2287 | #ifdef _WIN32 | ||
2288 | if (!linkInfo.isHardLink && !linkInfo.isJunction) | ||
2289 | linkInfo.isWSL = true; | ||
2290 | #endif | ||
2291 | */ | ||
2292 | bool linkWasSet = false; | 2580 | bool linkWasSet = false; |
2293 | RINOK(SetFromLinkPath(_diskFilePath, linkInfo, linkWasSet)) | 2581 | // link.LinkPath = "r:\\1\\2"; // for debug |
2582 | // link.isJunction = true; // for debug | ||
2583 | link.Normalize_to_RelativeSafe(_removePathParts); | ||
2584 | RINOK(SetLink(_diskFilePath, link, linkWasSet)) | ||
2585 | /* | ||
2586 | // we don't set attributes for placeholder. | ||
2294 | if (linkWasSet) | 2587 | if (linkWasSet) |
2295 | _isSymLinkCreated = linkInfo.IsSymLink(); | 2588 | _isSymLinkCreated = true; // link.IsSymLink(); |
2296 | else | 2589 | else |
2590 | */ | ||
2297 | _needSetAttrib = false; | 2591 | _needSetAttrib = false; |
2298 | } | 2592 | } |
2299 | /* | ||
2300 | if (!NFile::NIO::SetReparseData(_diskFilePath, _item.IsDir, )) | ||
2301 | { | ||
2302 | res = SendMessageError_with_LastError(kCantCreateSymLink, _diskFilePath); | ||
2303 | } | ||
2304 | */ | ||
2305 | } | 2593 | } |
2306 | #endif | ||
2307 | } | 2594 | } |
2308 | #endif | 2595 | #endif // SUPPORT_LINKS |
2309 | return res; | 2596 | return res; |
2310 | } | 2597 | } |
2311 | 2598 | ||
2312 | 2599 | ||
2313 | void CArchiveExtractCallback::SetAttrib() | 2600 | static void SetAttrib_Base(const FString &path, const CProcessedFileInfo &fi, |
2601 | const CArchiveExtractCallback &callback) | ||
2314 | { | 2602 | { |
2315 | #ifndef _WIN32 | 2603 | #ifndef _WIN32 |
2604 | if (fi.Owner.Id_Defined && | ||
2605 | fi.Group.Id_Defined) | ||
2606 | { | ||
2607 | if (my_chown(path, fi.Owner.Id, fi.Group.Id) != 0) | ||
2608 | callback.SendMessageError_with_LastError("Cannot set owner", path); | ||
2609 | } | ||
2610 | #endif | ||
2611 | |||
2612 | if (fi.Attrib_Defined) | ||
2613 | { | ||
2614 | // const AString s = GetAnsiString(_diskFilePath); | ||
2615 | // printf("\nSetFileAttrib_PosixHighDetect: %s: hex:%x\n", s.Ptr(), _fi.Attrib); | ||
2616 | if (!SetFileAttrib_PosixHighDetect(path, fi.Attrib)) | ||
2617 | { | ||
2618 | // do we need error message here in Windows and in posix? | ||
2619 | callback.SendMessageError_with_LastError("Cannot set file attribute", path); | ||
2620 | } | ||
2621 | } | ||
2622 | } | ||
2623 | |||
2624 | void CArchiveExtractCallback::SetAttrib() const | ||
2625 | { | ||
2626 | #ifndef _WIN32 | ||
2316 | // Linux now doesn't support permissions for symlinks | 2627 | // Linux now doesn't support permissions for symlinks |
2317 | if (_isSymLinkCreated) | 2628 | if (_isSymLinkCreated) |
2318 | return; | 2629 | return; |
2319 | #endif | 2630 | #endif |
2320 | 2631 | ||
2321 | if (_itemFailure | 2632 | if (_itemFailure |
2322 | || _diskFilePath.IsEmpty() | 2633 | || _diskFilePath.IsEmpty() |
@@ -2324,29 +2635,39 @@ void CArchiveExtractCallback::SetAttrib() | |||
2324 | || !_extractMode) | 2635 | || !_extractMode) |
2325 | return; | 2636 | return; |
2326 | 2637 | ||
2327 | #ifndef _WIN32 | 2638 | SetAttrib_Base(_diskFilePath, _fi, *this); |
2328 | if (_fi.Owner.Id_Defined && | 2639 | } |
2329 | _fi.Group.Id_Defined) | ||
2330 | { | ||
2331 | if (my_chown(_diskFilePath, _fi.Owner.Id, _fi.Group.Id) != 0) | ||
2332 | { | ||
2333 | SendMessageError_with_LastError("Cannot set owner", _diskFilePath); | ||
2334 | } | ||
2335 | } | ||
2336 | #endif | ||
2337 | 2640 | ||
2338 | if (_fi.Attrib_Defined) | 2641 | |
2642 | #ifdef Z7_USE_SECURITY_CODE | ||
2643 | HRESULT CArchiveExtractCallback::SetSecurityInfo(UInt32 indexInArc, const FString &path) const | ||
2644 | { | ||
2645 | if (!_stdOutMode && _extractMode && _ntOptions.NtSecurity.Val && _arc->GetRawProps) | ||
2339 | { | 2646 | { |
2340 | // const AString s = GetAnsiString(_diskFilePath); | 2647 | const void *data; |
2341 | // printf("\nSetFileAttrib_PosixHighDetect: %s: hex:%x\n", s.Ptr(), _fi.Attrib); | 2648 | UInt32 dataSize; |
2342 | bool res = SetFileAttrib_PosixHighDetect(_diskFilePath, _fi.Attrib); | 2649 | UInt32 propType; |
2343 | if (!res) | 2650 | _arc->GetRawProps->GetRawProp(indexInArc, kpidNtSecure, &data, &dataSize, &propType); |
2651 | if (dataSize != 0) | ||
2344 | { | 2652 | { |
2345 | // do we need error message here in Windows and in posix? | 2653 | if (propType != NPropDataType::kRaw) |
2346 | SendMessageError_with_LastError("Cannot set file attribute", _diskFilePath); | 2654 | return E_FAIL; |
2655 | if (CheckNtSecure((const Byte *)data, dataSize)) | ||
2656 | { | ||
2657 | SECURITY_INFORMATION securInfo = DACL_SECURITY_INFORMATION | GROUP_SECURITY_INFORMATION | OWNER_SECURITY_INFORMATION; | ||
2658 | if (_saclEnabled) | ||
2659 | securInfo |= SACL_SECURITY_INFORMATION; | ||
2660 | // if (! | ||
2661 | ::SetFileSecurityW(fs2us(path), securInfo, (PSECURITY_DESCRIPTOR)(void *)(const Byte *)(data)); | ||
2662 | { | ||
2663 | // RINOK(SendMessageError_with_LastError("SetFileSecurity FAILS", path)) | ||
2664 | } | ||
2665 | } | ||
2347 | } | 2666 | } |
2348 | } | 2667 | } |
2668 | return S_OK; | ||
2349 | } | 2669 | } |
2670 | #endif // Z7_USE_SECURITY_CODE | ||
2350 | 2671 | ||
2351 | 2672 | ||
2352 | Z7_COM7F_IMF(CArchiveExtractCallback::SetOperationResult(Int32 opRes)) | 2673 | Z7_COM7F_IMF(CArchiveExtractCallback::SetOperationResult(Int32 opRes)) |
@@ -2384,27 +2705,9 @@ Z7_COM7F_IMF(CArchiveExtractCallback::SetOperationResult(Int32 opRes)) | |||
2384 | 2705 | ||
2385 | RINOK(CloseReparseAndFile()) | 2706 | RINOK(CloseReparseAndFile()) |
2386 | 2707 | ||
2387 | #ifdef Z7_USE_SECURITY_CODE | 2708 | #ifdef Z7_USE_SECURITY_CODE |
2388 | if (!_stdOutMode && _extractMode && _ntOptions.NtSecurity.Val && _arc->GetRawProps) | 2709 | RINOK(SetSecurityInfo(_index, _diskFilePath)) |
2389 | { | 2710 | #endif |
2390 | const void *data; | ||
2391 | UInt32 dataSize; | ||
2392 | UInt32 propType; | ||
2393 | _arc->GetRawProps->GetRawProp(_index, kpidNtSecure, &data, &dataSize, &propType); | ||
2394 | if (dataSize != 0) | ||
2395 | { | ||
2396 | if (propType != NPropDataType::kRaw) | ||
2397 | return E_FAIL; | ||
2398 | if (CheckNtSecure((const Byte *)data, dataSize)) | ||
2399 | { | ||
2400 | SECURITY_INFORMATION securInfo = DACL_SECURITY_INFORMATION | GROUP_SECURITY_INFORMATION | OWNER_SECURITY_INFORMATION; | ||
2401 | if (_saclEnabled) | ||
2402 | securInfo |= SACL_SECURITY_INFORMATION; | ||
2403 | ::SetFileSecurityW(fs2us(_diskFilePath), securInfo, (PSECURITY_DESCRIPTOR)(void *)(const Byte *)(data)); | ||
2404 | } | ||
2405 | } | ||
2406 | } | ||
2407 | #endif // Z7_USE_SECURITY_CODE | ||
2408 | 2711 | ||
2409 | if (!_curSize_Defined) | 2712 | if (!_curSize_Defined) |
2410 | GetUnpackSize(); | 2713 | GetUnpackSize(); |
@@ -2648,15 +2951,58 @@ void CDirPathSortPair::SetNumSlashes(const FChar *s) | |||
2648 | } | 2951 | } |
2649 | 2952 | ||
2650 | 2953 | ||
2651 | bool CDirPathTime::SetDirTime() const | 2954 | bool CFiTimesCAM::SetDirTime_to_FS(CFSTR path) const |
2652 | { | 2955 | { |
2653 | return NDir::SetDirTime(Path, | 2956 | // it's same function for dir and for file |
2957 | return NDir::SetDirTime(path, | ||
2654 | CTime_Defined ? &CTime : NULL, | 2958 | CTime_Defined ? &CTime : NULL, |
2655 | ATime_Defined ? &ATime : NULL, | 2959 | ATime_Defined ? &ATime : NULL, |
2656 | MTime_Defined ? &MTime : NULL); | 2960 | MTime_Defined ? &MTime : NULL); |
2657 | } | 2961 | } |
2658 | 2962 | ||
2659 | 2963 | ||
2964 | #ifdef SUPPORT_LINKS | ||
2965 | |||
2966 | bool CFiTimesCAM::SetLinkFileTime_to_FS(CFSTR path) const | ||
2967 | { | ||
2968 | // it's same function for dir and for file | ||
2969 | return NDir::SetLinkFileTime(path, | ||
2970 | CTime_Defined ? &CTime : NULL, | ||
2971 | ATime_Defined ? &ATime : NULL, | ||
2972 | MTime_Defined ? &MTime : NULL); | ||
2973 | } | ||
2974 | |||
2975 | HRESULT CArchiveExtractCallback::SetPostLinks() const | ||
2976 | { | ||
2977 | FOR_VECTOR (i, _postLinks) | ||
2978 | { | ||
2979 | const CPostLink &link = _postLinks[i]; | ||
2980 | bool linkWasSet = false; | ||
2981 | RINOK(SetLink2(*this, link, linkWasSet)) | ||
2982 | if (linkWasSet) | ||
2983 | { | ||
2984 | #ifdef _WIN32 | ||
2985 | // Linux now doesn't support permissions for symlinks | ||
2986 | SetAttrib_Base(link.fullProcessedPath_from, link.item_FileInfo, *this); | ||
2987 | #endif | ||
2988 | |||
2989 | CFiTimesCAM pt; | ||
2990 | GetFiTimesCAM(link.item_FileInfo, pt, *_arc); | ||
2991 | if (pt.IsSomeTimeDefined()) | ||
2992 | pt.SetLinkFileTime_to_FS(link.fullProcessedPath_from); | ||
2993 | |||
2994 | #ifdef Z7_USE_SECURITY_CODE | ||
2995 | // we set security information after timestamps setting | ||
2996 | RINOK(SetSecurityInfo(link.Index_in_Arc, link.fullProcessedPath_from)) | ||
2997 | #endif | ||
2998 | } | ||
2999 | } | ||
3000 | return S_OK; | ||
3001 | } | ||
3002 | |||
3003 | #endif | ||
3004 | |||
3005 | |||
2660 | HRESULT CArchiveExtractCallback::SetDirsTimes() | 3006 | HRESULT CArchiveExtractCallback::SetDirsTimes() |
2661 | { | 3007 | { |
2662 | if (!_arc) | 3008 | if (!_arc) |
@@ -2680,7 +3026,7 @@ HRESULT CArchiveExtractCallback::SetDirsTimes() | |||
2680 | for (i = 0; i < pairs.Size(); i++) | 3026 | for (i = 0; i < pairs.Size(); i++) |
2681 | { | 3027 | { |
2682 | const CDirPathTime &dpt = _extractedFolders[pairs[i].Index]; | 3028 | const CDirPathTime &dpt = _extractedFolders[pairs[i].Index]; |
2683 | if (!dpt.SetDirTime()) | 3029 | if (!dpt.SetDirTime_to_FS_2()) |
2684 | { | 3030 | { |
2685 | // result = E_FAIL; | 3031 | // result = E_FAIL; |
2686 | // do we need error message here in Windows and in posix? | 3032 | // do we need error message here in Windows and in posix? |
@@ -2712,10 +3058,20 @@ HRESULT CArchiveExtractCallback::SetDirsTimes() | |||
2712 | 3058 | ||
2713 | HRESULT CArchiveExtractCallback::CloseArc() | 3059 | HRESULT CArchiveExtractCallback::CloseArc() |
2714 | { | 3060 | { |
3061 | // we call CloseReparseAndFile() here because we can have non-closed file in some cases? | ||
2715 | HRESULT res = CloseReparseAndFile(); | 3062 | HRESULT res = CloseReparseAndFile(); |
2716 | const HRESULT res2 = SetDirsTimes(); | 3063 | #ifdef SUPPORT_LINKS |
2717 | if (res == S_OK) | 3064 | { |
2718 | res = res2; | 3065 | const HRESULT res2 = SetPostLinks(); |
3066 | if (res == S_OK) | ||
3067 | res = res2; | ||
3068 | } | ||
3069 | #endif | ||
3070 | { | ||
3071 | const HRESULT res2 = SetDirsTimes(); | ||
3072 | if (res == S_OK) | ||
3073 | res = res2; | ||
3074 | } | ||
2719 | _arc = NULL; | 3075 | _arc = NULL; |
2720 | return res; | 3076 | return res; |
2721 | } | 3077 | } |
diff --git a/CPP/7zip/UI/Common/ArchiveExtractCallback.h b/CPP/7zip/UI/Common/ArchiveExtractCallback.h index 7eb2f67..3c62763 100644 --- a/CPP/7zip/UI/Common/ArchiveExtractCallback.h +++ b/CPP/7zip/UI/Common/ArchiveExtractCallback.h | |||
@@ -52,7 +52,6 @@ struct CExtractNtOptions | |||
52 | { | 52 | { |
53 | CBoolPair NtSecurity; | 53 | CBoolPair NtSecurity; |
54 | CBoolPair SymLinks; | 54 | CBoolPair SymLinks; |
55 | CBoolPair SymLinks_AllowDangerous; | ||
56 | CBoolPair HardLinks; | 55 | CBoolPair HardLinks; |
57 | CBoolPair AltStreams; | 56 | CBoolPair AltStreams; |
58 | bool ReplaceColonForAltStream; | 57 | bool ReplaceColonForAltStream; |
@@ -66,6 +65,8 @@ struct CExtractNtOptions | |||
66 | bool PreserveATime; | 65 | bool PreserveATime; |
67 | bool OpenShareForWrite; | 66 | bool OpenShareForWrite; |
68 | 67 | ||
68 | unsigned SymLinks_DangerousLevel; | ||
69 | |||
69 | UInt64 MemLimit; | 70 | UInt64 MemLimit; |
70 | 71 | ||
71 | CExtractNtOptions(): | 72 | CExtractNtOptions(): |
@@ -74,10 +75,10 @@ struct CExtractNtOptions | |||
74 | ExtractOwner(false), | 75 | ExtractOwner(false), |
75 | PreserveATime(false), | 76 | PreserveATime(false), |
76 | OpenShareForWrite(false), | 77 | OpenShareForWrite(false), |
78 | SymLinks_DangerousLevel(5), | ||
77 | MemLimit((UInt64)(Int64)-1) | 79 | MemLimit((UInt64)(Int64)-1) |
78 | { | 80 | { |
79 | SymLinks.Val = true; | 81 | SymLinks.Val = true; |
80 | SymLinks_AllowDangerous.Val = false; | ||
81 | HardLinks.Val = true; | 82 | HardLinks.Val = true; |
82 | AltStreams.Val = true; | 83 | AltStreams.Val = true; |
83 | 84 | ||
@@ -90,25 +91,10 @@ struct CExtractNtOptions | |||
90 | } | 91 | } |
91 | }; | 92 | }; |
92 | 93 | ||
93 | #ifndef Z7_SFX | ||
94 | |||
95 | Z7_CLASS_IMP_COM_1( | ||
96 | CGetProp | ||
97 | , IGetProp | ||
98 | ) | ||
99 | public: | ||
100 | UInt32 IndexInArc; | ||
101 | const CArc *Arc; | ||
102 | // UString Name; // relative path | ||
103 | }; | ||
104 | |||
105 | #endif | ||
106 | 94 | ||
107 | #ifndef Z7_SFX | 95 | #ifndef Z7_SFX |
108 | #ifndef UNDER_CE | 96 | #ifndef UNDER_CE |
109 | |||
110 | #define SUPPORT_LINKS | 97 | #define SUPPORT_LINKS |
111 | |||
112 | #endif | 98 | #endif |
113 | #endif | 99 | #endif |
114 | 100 | ||
@@ -181,53 +167,79 @@ struct CFiTimesCAM | |||
181 | ATime_Defined | | 167 | ATime_Defined | |
182 | MTime_Defined; | 168 | MTime_Defined; |
183 | } | 169 | } |
170 | bool SetDirTime_to_FS(CFSTR path) const; | ||
171 | #ifdef SUPPORT_LINKS | ||
172 | bool SetLinkFileTime_to_FS(CFSTR path) const; | ||
173 | #endif | ||
184 | }; | 174 | }; |
185 | 175 | ||
186 | struct CDirPathTime: public CFiTimesCAM | 176 | struct CDirPathTime: public CFiTimesCAM |
187 | { | 177 | { |
188 | FString Path; | 178 | FString Path; |
189 | 179 | ||
190 | bool SetDirTime() const; | 180 | bool SetDirTime_to_FS_2() const { return SetDirTime_to_FS(Path); } |
191 | }; | 181 | }; |
192 | 182 | ||
193 | 183 | ||
194 | #ifdef SUPPORT_LINKS | 184 | #ifdef SUPPORT_LINKS |
195 | 185 | ||
186 | enum ELinkType | ||
187 | { | ||
188 | k_LinkType_HardLink, | ||
189 | k_LinkType_PureSymLink, | ||
190 | k_LinkType_Junction, | ||
191 | k_LinkType_WSL | ||
192 | // , k_LinkType_CopyLink; | ||
193 | }; | ||
194 | |||
195 | |||
196 | struct CLinkInfo | 196 | struct CLinkInfo |
197 | { | 197 | { |
198 | // bool isCopyLink; | 198 | ELinkType LinkType; |
199 | bool isHardLink; | ||
200 | bool isJunction; | ||
201 | bool isRelative; | 199 | bool isRelative; |
202 | bool isWSL; | 200 | // if (isRelative == false), then (LinkPath) is relative to root folder of archive |
203 | UString linkPath; | 201 | // if (isRelative == true ), then (LinkPath) is relative to current item |
202 | bool isWindowsPath; | ||
203 | UString LinkPath; | ||
204 | |||
205 | bool Is_HardLink() const { return LinkType == k_LinkType_HardLink; } | ||
206 | bool Is_AnySymLink() const { return LinkType != k_LinkType_HardLink; } | ||
204 | 207 | ||
205 | bool IsSymLink() const { return !isHardLink; } | 208 | bool Is_WSL() const { return LinkType == k_LinkType_WSL; } |
206 | 209 | ||
207 | CLinkInfo(): | 210 | CLinkInfo(): |
208 | // IsCopyLink(false), | 211 | LinkType(k_LinkType_PureSymLink), |
209 | isHardLink(false), | ||
210 | isJunction(false), | ||
211 | isRelative(false), | 212 | isRelative(false), |
212 | isWSL(false) | 213 | isWindowsPath(false) |
213 | {} | 214 | {} |
214 | 215 | ||
215 | void Clear() | 216 | void Clear() |
216 | { | 217 | { |
217 | // IsCopyLink = false; | 218 | LinkType = k_LinkType_PureSymLink; |
218 | isHardLink = false; | ||
219 | isJunction = false; | ||
220 | isRelative = false; | 219 | isRelative = false; |
221 | isWSL = false; | 220 | isWindowsPath = false; |
222 | linkPath.Empty(); | 221 | LinkPath.Empty(); |
223 | } | 222 | } |
224 | 223 | ||
225 | bool Parse(const Byte *data, size_t dataSize, bool isLinuxData); | 224 | bool Parse_from_WindowsReparseData(const Byte *data, size_t dataSize); |
225 | bool Parse_from_LinuxData(const Byte *data, size_t dataSize); | ||
226 | void Normalize_to_RelativeSafe(UStringVector &removePathParts); | ||
227 | private: | ||
228 | void Remove_AbsPathPrefixes(); | ||
226 | }; | 229 | }; |
227 | 230 | ||
228 | #endif // SUPPORT_LINKS | 231 | #endif // SUPPORT_LINKS |
229 | 232 | ||
230 | 233 | ||
234 | |||
235 | struct CProcessedFileInfo | ||
236 | { | ||
237 | CArcTime CTime; | ||
238 | CArcTime ATime; | ||
239 | CArcTime MTime; | ||
240 | UInt32 Attrib; | ||
241 | bool Attrib_Defined; | ||
242 | |||
231 | #ifndef _WIN32 | 243 | #ifndef _WIN32 |
232 | 244 | ||
233 | struct COwnerInfo | 245 | struct COwnerInfo |
@@ -244,7 +256,75 @@ struct COwnerInfo | |||
244 | } | 256 | } |
245 | }; | 257 | }; |
246 | 258 | ||
259 | COwnerInfo Owner; | ||
260 | COwnerInfo Group; | ||
261 | #endif | ||
262 | |||
263 | void Clear() | ||
264 | { | ||
265 | #ifndef _WIN32 | ||
266 | Attrib_Defined = false; | ||
267 | Owner.Clear(); | ||
247 | #endif | 268 | #endif |
269 | } | ||
270 | |||
271 | bool IsReparse() const | ||
272 | { | ||
273 | return (Attrib_Defined && (Attrib & FILE_ATTRIBUTE_REPARSE_POINT) != 0); | ||
274 | } | ||
275 | |||
276 | bool IsLinuxSymLink() const | ||
277 | { | ||
278 | return (Attrib_Defined && MY_LIN_S_ISLNK(Attrib >> 16)); | ||
279 | } | ||
280 | |||
281 | void SetFromPosixAttrib(UInt32 a) | ||
282 | { | ||
283 | // here we set only part of combined attribute required by SetFileAttrib() call | ||
284 | #ifdef _WIN32 | ||
285 | // Windows sets FILE_ATTRIBUTE_NORMAL, if we try to set 0 as attribute. | ||
286 | Attrib = MY_LIN_S_ISDIR(a) ? | ||
287 | FILE_ATTRIBUTE_DIRECTORY : | ||
288 | FILE_ATTRIBUTE_ARCHIVE; | ||
289 | if ((a & 0222) == 0) // (& S_IWUSR) in p7zip | ||
290 | Attrib |= FILE_ATTRIBUTE_READONLY; | ||
291 | // 22.00 : we need type bits for (MY_LIN_S_IFLNK) for IsLinuxSymLink() | ||
292 | a &= MY_LIN_S_IFMT; | ||
293 | if (a == MY_LIN_S_IFLNK) | ||
294 | Attrib |= (a << 16); | ||
295 | #else | ||
296 | Attrib = (a << 16) | FILE_ATTRIBUTE_UNIX_EXTENSION; | ||
297 | #endif | ||
298 | Attrib_Defined = true; | ||
299 | } | ||
300 | }; | ||
301 | |||
302 | |||
303 | #ifdef SUPPORT_LINKS | ||
304 | |||
305 | struct CPostLink | ||
306 | { | ||
307 | UInt32 Index_in_Arc; | ||
308 | bool item_IsDir; // _item.IsDir | ||
309 | UString item_Path; // _item.Path; | ||
310 | UStringVector item_PathParts; // _item.PathParts; | ||
311 | CProcessedFileInfo item_FileInfo; // _fi | ||
312 | FString fullProcessedPath_from; // full file path in FS | ||
313 | CLinkInfo LinkInfo; | ||
314 | }; | ||
315 | |||
316 | /* | ||
317 | struct CPostLinks | ||
318 | { | ||
319 | void Clear() | ||
320 | { | ||
321 | Links.Clear(); | ||
322 | } | ||
323 | }; | ||
324 | */ | ||
325 | |||
326 | #endif // SUPPORT_LINKS | ||
327 | |||
248 | 328 | ||
249 | 329 | ||
250 | class CArchiveExtractCallback Z7_final: | 330 | class CArchiveExtractCallback Z7_final: |
@@ -282,114 +362,78 @@ class CArchiveExtractCallback Z7_final: | |||
282 | Z7_IFACE_COM7_IMP(IArchiveRequestMemoryUseCallback) | 362 | Z7_IFACE_COM7_IMP(IArchiveRequestMemoryUseCallback) |
283 | #endif | 363 | #endif |
284 | 364 | ||
365 | // bool Write_CTime; | ||
366 | // bool Write_ATime; | ||
367 | // bool Write_MTime; | ||
368 | bool _stdOutMode; | ||
369 | bool _testMode; | ||
370 | bool _removePartsForAltStreams; | ||
371 | public: | ||
372 | bool Is_elimPrefix_Mode; | ||
373 | private: | ||
374 | |||
285 | const CArc *_arc; | 375 | const CArc *_arc; |
376 | public: | ||
286 | CExtractNtOptions _ntOptions; | 377 | CExtractNtOptions _ntOptions; |
287 | 378 | private: | |
379 | bool _encrypted; | ||
288 | bool _isSplit; | 380 | bool _isSplit; |
381 | bool _curSize_Defined; | ||
382 | bool _fileLength_WasSet; | ||
289 | 383 | ||
384 | bool _isRenamed; | ||
290 | bool _extractMode; | 385 | bool _extractMode; |
291 | 386 | bool _is_SymLink_in_Data_Linux; // false = WIN32, true = LINUX. | |
292 | bool Write_CTime; | 387 | // _is_SymLink_in_Data_Linux is detected from Windows/Linux part of attributes of file. |
293 | bool Write_ATime; | ||
294 | bool Write_MTime; | ||
295 | bool _keepAndReplaceEmptyDirPrefixes; // replace them to "_"; | ||
296 | |||
297 | bool _encrypted; | ||
298 | |||
299 | // bool _is_SymLink_in_Data; | ||
300 | bool _is_SymLink_in_Data_Linux; // false = WIN32, true = LINUX | ||
301 | |||
302 | bool _needSetAttrib; | 388 | bool _needSetAttrib; |
303 | bool _isSymLinkCreated; | 389 | bool _isSymLinkCreated; |
304 | bool _itemFailure; | 390 | bool _itemFailure; |
305 | |||
306 | bool _some_pathParts_wereRemoved; | 391 | bool _some_pathParts_wereRemoved; |
307 | public: | ||
308 | bool Is_elimPrefix_Mode; | ||
309 | |||
310 | private: | ||
311 | bool _curSize_Defined; | ||
312 | bool _fileLength_WasSet; | ||
313 | 392 | ||
314 | bool _removePartsForAltStreams; | ||
315 | |||
316 | bool _stdOutMode; | ||
317 | bool _testMode; | ||
318 | bool _multiArchives; | 393 | bool _multiArchives; |
394 | bool _keepAndReplaceEmptyDirPrefixes; // replace them to "_"; | ||
395 | #if defined(_WIN32) && !defined(UNDER_CE) && !defined(Z7_SFX) | ||
396 | bool _saclEnabled; | ||
397 | #endif | ||
319 | 398 | ||
320 | NExtract::NPathMode::EEnum _pathMode; | 399 | NExtract::NPathMode::EEnum _pathMode; |
321 | NExtract::NOverwriteMode::EEnum _overwriteMode; | 400 | NExtract::NOverwriteMode::EEnum _overwriteMode; |
322 | 401 | ||
323 | const NWildcard::CCensorNode *_wildcardCensor; // we need wildcard for single pass mode (stdin) | ||
324 | CMyComPtr<IFolderArchiveExtractCallback> _extractCallback2; | 402 | CMyComPtr<IFolderArchiveExtractCallback> _extractCallback2; |
403 | const NWildcard::CCensorNode *_wildcardCensor; // we need wildcard for single pass mode (stdin) | ||
325 | // CMyComPtr<ICompressProgressInfo> _compressProgress; | 404 | // CMyComPtr<ICompressProgressInfo> _compressProgress; |
326 | // CMyComPtr<IArchiveExtractCallbackMessage2> _callbackMessage; | 405 | // CMyComPtr<IArchiveExtractCallbackMessage2> _callbackMessage; |
327 | CMyComPtr<IFolderArchiveExtractCallback2> _folderArchiveExtractCallback2; | 406 | CMyComPtr<IFolderArchiveExtractCallback2> _folderArchiveExtractCallback2; |
328 | CMyComPtr<ICryptoGetTextPassword> _cryptoGetTextPassword; | 407 | CMyComPtr<ICryptoGetTextPassword> _cryptoGetTextPassword; |
329 | 408 | ||
330 | FString _dirPathPrefix; | 409 | FString _dirPathPrefix; |
410 | public: | ||
331 | FString _dirPathPrefix_Full; | 411 | FString _dirPathPrefix_Full; |
412 | private: | ||
332 | 413 | ||
333 | #ifndef Z7_SFX | 414 | #ifndef Z7_SFX |
334 | 415 | ||
335 | CMyComPtr<IFolderExtractToStreamCallback> ExtractToStreamCallback; | 416 | CMyComPtr<IFolderExtractToStreamCallback> ExtractToStreamCallback; |
336 | CGetProp *GetProp_Spec; | ||
337 | CMyComPtr<IGetProp> GetProp; | ||
338 | CMyComPtr<IArchiveRequestMemoryUseCallback> _requestMemoryUseCallback; | 417 | CMyComPtr<IArchiveRequestMemoryUseCallback> _requestMemoryUseCallback; |
339 | 418 | ||
340 | #endif | 419 | #endif |
341 | 420 | ||
342 | CReadArcItem _item; | 421 | CReadArcItem _item; |
343 | FString _diskFilePath; | 422 | FString _diskFilePath; |
344 | UInt64 _position; | ||
345 | |||
346 | struct CProcessedFileInfo | ||
347 | { | ||
348 | CArcTime CTime; | ||
349 | CArcTime ATime; | ||
350 | CArcTime MTime; | ||
351 | UInt32 Attrib; | ||
352 | bool Attrib_Defined; | ||
353 | 423 | ||
354 | #ifndef _WIN32 | 424 | CProcessedFileInfo _fi; |
355 | COwnerInfo Owner; | ||
356 | COwnerInfo Group; | ||
357 | #endif | ||
358 | |||
359 | bool IsReparse() const | ||
360 | { | ||
361 | return (Attrib_Defined && (Attrib & FILE_ATTRIBUTE_REPARSE_POINT) != 0); | ||
362 | } | ||
363 | |||
364 | bool IsLinuxSymLink() const | ||
365 | { | ||
366 | return (Attrib_Defined && MY_LIN_S_ISLNK(Attrib >> 16)); | ||
367 | } | ||
368 | 425 | ||
369 | void SetFromPosixAttrib(UInt32 a) | 426 | UInt64 _position; |
370 | { | ||
371 | // here we set only part of combined attribute required by SetFileAttrib() call | ||
372 | #ifdef _WIN32 | ||
373 | // Windows sets FILE_ATTRIBUTE_NORMAL, if we try to set 0 as attribute. | ||
374 | Attrib = MY_LIN_S_ISDIR(a) ? | ||
375 | FILE_ATTRIBUTE_DIRECTORY : | ||
376 | FILE_ATTRIBUTE_ARCHIVE; | ||
377 | if ((a & 0222) == 0) // (& S_IWUSR) in p7zip | ||
378 | Attrib |= FILE_ATTRIBUTE_READONLY; | ||
379 | // 22.00 : we need type bits for (MY_LIN_S_IFLNK) for IsLinuxSymLink() | ||
380 | a &= MY_LIN_S_IFMT; | ||
381 | if (a == MY_LIN_S_IFLNK) | ||
382 | Attrib |= (a << 16); | ||
383 | #else | ||
384 | Attrib = (a << 16) | FILE_ATTRIBUTE_UNIX_EXTENSION; | ||
385 | #endif | ||
386 | Attrib_Defined = true; | ||
387 | } | ||
388 | } _fi; | ||
389 | |||
390 | UInt32 _index; | ||
391 | UInt64 _curSize; | 427 | UInt64 _curSize; |
392 | UInt64 _fileLength_that_WasSet; | 428 | UInt64 _fileLength_that_WasSet; |
429 | UInt32 _index; | ||
430 | |||
431 | // #ifdef SUPPORT_ALT_STREAMS | ||
432 | #if defined(_WIN32) && !defined(UNDER_CE) | ||
433 | DWORD _altStream_NeedRestore_AttribVal; | ||
434 | FString _altStream_NeedRestore_Attrib_for_parentFsPath; | ||
435 | #endif | ||
436 | // #endif | ||
393 | 437 | ||
394 | COutFileStream *_outFileStreamSpec; | 438 | COutFileStream *_outFileStreamSpec; |
395 | CMyComPtr<ISequentialOutStream> _outFileStream; | 439 | CMyComPtr<ISequentialOutStream> _outFileStream; |
@@ -398,9 +442,7 @@ private: | |||
398 | CBufPtrSeqOutStream *_bufPtrSeqOutStream_Spec; | 442 | CBufPtrSeqOutStream *_bufPtrSeqOutStream_Spec; |
399 | CMyComPtr<ISequentialOutStream> _bufPtrSeqOutStream; | 443 | CMyComPtr<ISequentialOutStream> _bufPtrSeqOutStream; |
400 | 444 | ||
401 | |||
402 | #ifndef Z7_SFX | 445 | #ifndef Z7_SFX |
403 | |||
404 | COutStreamWithHash *_hashStreamSpec; | 446 | COutStreamWithHash *_hashStreamSpec; |
405 | CMyComPtr<ISequentialOutStream> _hashStream; | 447 | CMyComPtr<ISequentialOutStream> _hashStream; |
406 | bool _hashStreamWasUsed; | 448 | bool _hashStreamWasUsed; |
@@ -411,11 +453,9 @@ private: | |||
411 | 453 | ||
412 | UStringVector _removePathParts; | 454 | UStringVector _removePathParts; |
413 | 455 | ||
414 | CMyComPtr<ICompressProgressInfo> _localProgress; | ||
415 | UInt64 _packTotal; | 456 | UInt64 _packTotal; |
416 | |||
417 | UInt64 _progressTotal; | 457 | UInt64 _progressTotal; |
418 | bool _progressTotal_Defined; | 458 | // bool _progressTotal_Defined; |
419 | 459 | ||
420 | CObjectVector<CDirPathTime> _extractedFolders; | 460 | CObjectVector<CDirPathTime> _extractedFolders; |
421 | 461 | ||
@@ -423,31 +463,28 @@ private: | |||
423 | // CObjectVector<NWindows::NFile::NDir::CDelayedSymLink> _delayedSymLinks; | 463 | // CObjectVector<NWindows::NFile::NDir::CDelayedSymLink> _delayedSymLinks; |
424 | #endif | 464 | #endif |
425 | 465 | ||
426 | #if defined(_WIN32) && !defined(UNDER_CE) && !defined(Z7_SFX) | 466 | void CreateComplexDirectory( |
427 | bool _saclEnabled; | 467 | const UStringVector &dirPathParts, bool isFinal, FString &fullPath); |
428 | #endif | ||
429 | |||
430 | void CreateComplexDirectory(const UStringVector &dirPathParts, FString &fullPath); | ||
431 | HRESULT GetTime(UInt32 index, PROPID propID, CArcTime &ft); | 468 | HRESULT GetTime(UInt32 index, PROPID propID, CArcTime &ft); |
432 | HRESULT GetUnpackSize(); | 469 | HRESULT GetUnpackSize(); |
433 | 470 | ||
434 | FString Hash_GetFullFilePath(); | 471 | FString Hash_GetFullFilePath(); |
435 | 472 | ||
436 | void SetAttrib(); | 473 | void SetAttrib() const; |
437 | 474 | ||
438 | public: | 475 | public: |
439 | HRESULT SendMessageError(const char *message, const FString &path); | 476 | HRESULT SendMessageError(const char *message, const FString &path) const; |
440 | HRESULT SendMessageError_with_Error(HRESULT errorCode, const char *message, const FString &path); | 477 | HRESULT SendMessageError_with_Error(HRESULT errorCode, const char *message, const FString &path) const; |
441 | HRESULT SendMessageError_with_LastError(const char *message, const FString &path); | 478 | HRESULT SendMessageError_with_LastError(const char *message, const FString &path) const; |
442 | HRESULT SendMessageError2(HRESULT errorCode, const char *message, const FString &path1, const FString &path2); | 479 | HRESULT SendMessageError2(HRESULT errorCode, const char *message, const FString &path1, const FString &path2) const; |
480 | HRESULT SendMessageError2_with_LastError(const char *message, const FString &path1, const FString &path2) const; | ||
443 | 481 | ||
444 | public: | 482 | #if defined(_WIN32) && !defined(UNDER_CE) && !defined(Z7_SFX) |
445 | #if defined(_WIN32) && !defined(UNDER_CE) | ||
446 | NExtract::NZoneIdMode::EEnum ZoneMode; | 483 | NExtract::NZoneIdMode::EEnum ZoneMode; |
447 | CByteBuffer ZoneBuf; | 484 | CByteBuffer ZoneBuf; |
448 | #endif | 485 | #endif |
449 | 486 | ||
450 | CLocalProgress *LocalProgressSpec; | 487 | CMyComPtr2_Create<ICompressProgressInfo, CLocalProgress> LocalProgressSpec; |
451 | 488 | ||
452 | UInt64 NumFolders; | 489 | UInt64 NumFolders; |
453 | UInt64 NumFiles; | 490 | UInt64 NumFiles; |
@@ -468,11 +505,11 @@ public: | |||
468 | _multiArchives = multiArchives; | 505 | _multiArchives = multiArchives; |
469 | _pathMode = pathMode; | 506 | _pathMode = pathMode; |
470 | _overwriteMode = overwriteMode; | 507 | _overwriteMode = overwriteMode; |
471 | #if defined(_WIN32) && !defined(UNDER_CE) | 508 | #if defined(_WIN32) && !defined(UNDER_CE) && !defined(Z7_SFX) |
472 | ZoneMode = zoneMode; | 509 | ZoneMode = zoneMode; |
473 | #else | 510 | #else |
474 | UNUSED_VAR(zoneMode) | 511 | UNUSED_VAR(zoneMode) |
475 | #endif | 512 | #endif |
476 | _keepAndReplaceEmptyDirPrefixes = keepAndReplaceEmptyDirPrefixes; | 513 | _keepAndReplaceEmptyDirPrefixes = keepAndReplaceEmptyDirPrefixes; |
477 | NumFolders = NumFiles = NumAltStreams = UnpackSize = AltStreams_UnpackSize = 0; | 514 | NumFolders = NumFiles = NumAltStreams = UnpackSize = AltStreams_UnpackSize = 0; |
478 | } | 515 | } |
@@ -503,23 +540,32 @@ public: | |||
503 | UInt64 packSize); | 540 | UInt64 packSize); |
504 | 541 | ||
505 | 542 | ||
506 | #ifdef SUPPORT_LINKS | 543 | #ifdef SUPPORT_LINKS |
507 | 544 | ||
508 | private: | 545 | private: |
509 | CHardLinks _hardLinks; | 546 | CHardLinks _hardLinks; |
547 | CObjectVector<CPostLink> _postLinks; | ||
510 | CLinkInfo _link; | 548 | CLinkInfo _link; |
549 | // const void *NtReparse_Data; | ||
550 | // UInt32 NtReparse_Size; | ||
511 | 551 | ||
512 | // FString _copyFile_Path; | 552 | // FString _copyFile_Path; |
513 | // HRESULT MyCopyFile(ISequentialOutStream *outStream); | 553 | // HRESULT MyCopyFile(ISequentialOutStream *outStream); |
514 | HRESULT Link(const FString &fullProcessedPath); | ||
515 | HRESULT ReadLink(); | 554 | HRESULT ReadLink(); |
555 | HRESULT SetLink( | ||
556 | const FString &fullProcessedPath_from, | ||
557 | const CLinkInfo &linkInfo, | ||
558 | bool &linkWasSet); | ||
559 | HRESULT SetPostLinks() const; | ||
516 | 560 | ||
517 | public: | 561 | public: |
518 | // call PrepareHardLinks() after Init() | 562 | HRESULT CreateHardLink2(const FString &newFilePath, |
563 | const FString &existFilePath, bool &link_was_Created) const; | ||
564 | HRESULT DeleteLinkFileAlways_or_RemoveEmptyDir(const FString &path, bool checkThatFileIsEmpty) const; | ||
519 | HRESULT PrepareHardLinks(const CRecordVector<UInt32> *realIndices); // NULL means all items | 565 | HRESULT PrepareHardLinks(const CRecordVector<UInt32> *realIndices); // NULL means all items |
566 | #endif | ||
520 | 567 | ||
521 | #endif | 568 | private: |
522 | |||
523 | 569 | ||
524 | #ifdef SUPPORT_ALT_STREAMS | 570 | #ifdef SUPPORT_ALT_STREAMS |
525 | CObjectVector<CIndexToPathPair> _renamedFiles; | 571 | CObjectVector<CIndexToPathPair> _renamedFiles; |
@@ -527,6 +573,7 @@ public: | |||
527 | 573 | ||
528 | // call it after Init() | 574 | // call it after Init() |
529 | 575 | ||
576 | public: | ||
530 | #ifndef Z7_SFX | 577 | #ifndef Z7_SFX |
531 | void SetBaseParentFolderIndex(UInt32 indexInArc) | 578 | void SetBaseParentFolderIndex(UInt32 indexInArc) |
532 | { | 579 | { |
@@ -548,28 +595,16 @@ private: | |||
548 | 595 | ||
549 | HRESULT Read_fi_Props(); | 596 | HRESULT Read_fi_Props(); |
550 | void CorrectPathParts(); | 597 | void CorrectPathParts(); |
551 | void GetFiTimesCAM(CFiTimesCAM &pt); | ||
552 | void CreateFolders(); | 598 | void CreateFolders(); |
553 | 599 | ||
554 | bool _isRenamed; | ||
555 | HRESULT CheckExistFile(FString &fullProcessedPath, bool &needExit); | 600 | HRESULT CheckExistFile(FString &fullProcessedPath, bool &needExit); |
556 | HRESULT GetExtractStream(CMyComPtr<ISequentialOutStream> &outStreamLoc, bool &needExit); | 601 | HRESULT GetExtractStream(CMyComPtr<ISequentialOutStream> &outStreamLoc, bool &needExit); |
557 | HRESULT GetItem(UInt32 index); | 602 | HRESULT GetItem(UInt32 index); |
558 | 603 | ||
559 | HRESULT CloseFile(); | 604 | HRESULT CloseFile(); |
560 | HRESULT CloseReparseAndFile(); | 605 | HRESULT CloseReparseAndFile(); |
561 | HRESULT CloseReparseAndFile2(); | ||
562 | HRESULT SetDirsTimes(); | 606 | HRESULT SetDirsTimes(); |
563 | 607 | HRESULT SetSecurityInfo(UInt32 indexInArc, const FString &path) const; | |
564 | const void *NtReparse_Data; | ||
565 | UInt32 NtReparse_Size; | ||
566 | |||
567 | #ifdef SUPPORT_LINKS | ||
568 | HRESULT SetFromLinkPath( | ||
569 | const FString &fullProcessedPath, | ||
570 | const CLinkInfo &linkInfo, | ||
571 | bool &linkWasSet); | ||
572 | #endif | ||
573 | }; | 608 | }; |
574 | 609 | ||
575 | 610 | ||
@@ -599,7 +634,8 @@ struct CArchiveExtractCallback_Closer | |||
599 | 634 | ||
600 | bool CensorNode_CheckPath(const NWildcard::CCensorNode &node, const CReadArcItem &item); | 635 | bool CensorNode_CheckPath(const NWildcard::CCensorNode &node, const CReadArcItem &item); |
601 | 636 | ||
602 | void ReadZoneFile_Of_BaseFile(CFSTR fileName2, CByteBuffer &buf); | 637 | bool Is_ZoneId_StreamName(const wchar_t *s); |
638 | void ReadZoneFile_Of_BaseFile(CFSTR fileName, CByteBuffer &buf); | ||
603 | bool WriteZoneFile_To_BaseFile(CFSTR fileName, const CByteBuffer &buf); | 639 | bool WriteZoneFile_To_BaseFile(CFSTR fileName, const CByteBuffer &buf); |
604 | 640 | ||
605 | #endif | 641 | #endif |
diff --git a/CPP/7zip/UI/Common/Bench.cpp b/CPP/7zip/UI/Common/Bench.cpp index e1ca846..eb24e7f 100644 --- a/CPP/7zip/UI/Common/Bench.cpp +++ b/CPP/7zip/UI/Common/Bench.cpp | |||
@@ -871,14 +871,27 @@ struct CAffinityMode | |||
871 | unsigned NumCoreThreads; | 871 | unsigned NumCoreThreads; |
872 | unsigned NumCores; | 872 | unsigned NumCores; |
873 | // unsigned DivideNum; | 873 | // unsigned DivideNum; |
874 | |||
875 | #ifdef _WIN32 | ||
876 | unsigned NumGroups; | ||
877 | #endif | ||
878 | |||
874 | UInt32 Sizes[NUM_CPU_LEVELS_MAX]; | 879 | UInt32 Sizes[NUM_CPU_LEVELS_MAX]; |
875 | 880 | ||
876 | void SetLevels(unsigned numCores, unsigned numCoreThreads); | 881 | void SetLevels(unsigned numCores, unsigned numCoreThreads); |
877 | DWORD_PTR GetAffinityMask(UInt32 bundleIndex, CCpuSet *cpuSet) const; | 882 | DWORD_PTR GetAffinityMask(UInt32 bundleIndex, CCpuSet *cpuSet) const; |
878 | bool NeedAffinity() const { return NumBundleThreads != 0; } | 883 | bool NeedAffinity() const { return NumBundleThreads != 0; } |
879 | 884 | ||
885 | #ifdef _WIN32 | ||
886 | bool NeedGroupsMode() const { return NumGroups > 1; } | ||
887 | #endif | ||
888 | |||
880 | WRes CreateThread_WithAffinity(NWindows::CThread &thread, THREAD_FUNC_TYPE startAddress, LPVOID parameter, UInt32 bundleIndex) const | 889 | WRes CreateThread_WithAffinity(NWindows::CThread &thread, THREAD_FUNC_TYPE startAddress, LPVOID parameter, UInt32 bundleIndex) const |
881 | { | 890 | { |
891 | #ifdef _WIN32 | ||
892 | if (NeedGroupsMode()) // we need fix for bundleIndex usage | ||
893 | return thread.Create_With_Group(startAddress, parameter, bundleIndex % NumGroups); | ||
894 | #endif | ||
882 | if (NeedAffinity()) | 895 | if (NeedAffinity()) |
883 | { | 896 | { |
884 | CCpuSet cpuSet; | 897 | CCpuSet cpuSet; |
@@ -892,6 +905,9 @@ struct CAffinityMode | |||
892 | NumBundleThreads(0), | 905 | NumBundleThreads(0), |
893 | NumLevels(0), | 906 | NumLevels(0), |
894 | NumCoreThreads(1) | 907 | NumCoreThreads(1) |
908 | #ifdef _WIN32 | ||
909 | , NumGroups(0) | ||
910 | #endif | ||
895 | // DivideNum(1) | 911 | // DivideNum(1) |
896 | {} | 912 | {} |
897 | }; | 913 | }; |
@@ -1288,22 +1304,28 @@ HRESULT CEncoderInfo::Generate() | |||
1288 | if (scp) | 1304 | if (scp) |
1289 | { | 1305 | { |
1290 | const UInt64 reduceSize = kBufferSize; | 1306 | const UInt64 reduceSize = kBufferSize; |
1291 | 1307 | /* in posix : new thread uses same affinity as parent thread, | |
1292 | /* in posix new thread uses same affinity as parent thread, | ||
1293 | so we don't need to send affinity to coder in posix */ | 1308 | so we don't need to send affinity to coder in posix */ |
1294 | UInt64 affMask; | 1309 | UInt64 affMask = 0; |
1295 | #if !defined(Z7_ST) && defined(_WIN32) | 1310 | UInt32 affinityGroup = (UInt32)(Int32)-1; |
1311 | // UInt64 affinityInGroup = 0; | ||
1312 | #if !defined(Z7_ST) && defined(_WIN32) | ||
1296 | { | 1313 | { |
1297 | CCpuSet cpuSet; | 1314 | CCpuSet cpuSet; |
1298 | affMask = AffinityMode.GetAffinityMask(EncoderIndex, &cpuSet); | 1315 | if (AffinityMode.NeedGroupsMode()) // we need fix for affinityInGroup also |
1316 | affinityGroup = EncoderIndex % AffinityMode.NumGroups; | ||
1317 | else | ||
1318 | affMask = AffinityMode.GetAffinityMask(EncoderIndex, &cpuSet); | ||
1299 | } | 1319 | } |
1300 | #else | 1320 | #endif |
1301 | affMask = 0; | 1321 | // affMask <<= 3; // debug line: to test no affinity in coder |
1302 | #endif | 1322 | // affMask = 0; // for debug |
1303 | // affMask <<= 3; // debug line: to test no affinity in coder; | 1323 | // affinityGroup = 0; // for debug |
1304 | // affMask = 0; | 1324 | // affinityInGroup = 1; // for debug |
1305 | 1325 | RINOK(method.SetCoderProps_DSReduce_Aff(scp, &reduceSize, | |
1306 | RINOK(method.SetCoderProps_DSReduce_Aff(scp, &reduceSize, (affMask != 0 ? &affMask : NULL))) | 1326 | affMask != 0 ? &affMask : NULL, |
1327 | affinityGroup != (UInt32)(Int32)-1 ? &affinityGroup : NULL, | ||
1328 | /* affinityInGroup != 0 ? &affinityInGroup : */ NULL)) | ||
1307 | } | 1329 | } |
1308 | else | 1330 | else |
1309 | { | 1331 | { |
@@ -2298,6 +2320,28 @@ HRESULT CCrcInfo_Base::Generate(const Byte *data, size_t size) | |||
2298 | } | 2320 | } |
2299 | 2321 | ||
2300 | 2322 | ||
2323 | #if 1 | ||
2324 | #define HashUpdate(hf, data, size) hf->Update(data, size) | ||
2325 | #else | ||
2326 | // for debug: | ||
2327 | static void HashUpdate(IHasher *hf, const void *data, UInt32 size) | ||
2328 | { | ||
2329 | for (;;) | ||
2330 | { | ||
2331 | if (size == 0) | ||
2332 | return; | ||
2333 | UInt32 size2 = (size * 0x85EBCA87) % size / 8; | ||
2334 | // UInt32 size2 = size / 2; | ||
2335 | if (size2 == 0) | ||
2336 | size2 = 1; | ||
2337 | hf->Update(data, size2); | ||
2338 | data = (const void *)((const Byte *)data + size2); | ||
2339 | size -= size2; | ||
2340 | } | ||
2341 | } | ||
2342 | #endif | ||
2343 | |||
2344 | |||
2301 | HRESULT CCrcInfo_Base::CrcProcess(UInt64 numIterations, | 2345 | HRESULT CCrcInfo_Base::CrcProcess(UInt64 numIterations, |
2302 | const UInt32 *checkSum, IHasher *hf, | 2346 | const UInt32 *checkSum, IHasher *hf, |
2303 | IBenchPrintCallback *callback) | 2347 | IBenchPrintCallback *callback) |
@@ -2328,7 +2372,7 @@ HRESULT CCrcInfo_Base::CrcProcess(UInt64 numIterations, | |||
2328 | const size_t rem = size - pos; | 2372 | const size_t rem = size - pos; |
2329 | const UInt32 kStep = ((UInt32)1 << 31); | 2373 | const UInt32 kStep = ((UInt32)1 << 31); |
2330 | const UInt32 curSize = (rem < kStep) ? (UInt32)rem : kStep; | 2374 | const UInt32 curSize = (rem < kStep) ? (UInt32)rem : kStep; |
2331 | hf->Update(buf + pos, curSize); | 2375 | HashUpdate(hf, buf + pos, curSize); |
2332 | pos += curSize; | 2376 | pos += curSize; |
2333 | } | 2377 | } |
2334 | while (pos != size); | 2378 | while (pos != size); |
@@ -2742,14 +2786,20 @@ static const CBenchHash g_Hash[] = | |||
2742 | { 2, 128 *ARM_CRC_MUL, 0x21e207bb, "CRC32:32" }, | 2786 | { 2, 128 *ARM_CRC_MUL, 0x21e207bb, "CRC32:32" }, |
2743 | { 2, 64 *ARM_CRC_MUL, 0x21e207bb, "CRC32:64" }, | 2787 | { 2, 64 *ARM_CRC_MUL, 0x21e207bb, "CRC32:64" }, |
2744 | { 10, 256, 0x41b901d1, "CRC64" }, | 2788 | { 10, 256, 0x41b901d1, "CRC64" }, |
2745 | { 10, 64, 0x43eac94f, "XXH64" }, | 2789 | { 5, 64, 0x43eac94f, "XXH64" }, |
2746 | 2790 | { 2, 2340, 0x3398a904, "MD5" }, | |
2747 | { 10, 5100, 0x7913ba03, "SHA256:1" }, | 2791 | { 10, 2340, 0xff769021, "SHA1:1" }, |
2748 | { 2, CMPLX((32 * 4 + 1) * 4 + 4), 0x7913ba03, "SHA256:2" }, | ||
2749 | |||
2750 | { 10, 2340, 0xff769021, "SHA1:1" }, | ||
2751 | { 2, CMPLX((20 * 6 + 1) * 4 + 4), 0xff769021, "SHA1:2" }, | 2792 | { 2, CMPLX((20 * 6 + 1) * 4 + 4), 0xff769021, "SHA1:2" }, |
2752 | 2793 | { 10, 5100, 0x7913ba03, "SHA256:1" }, | |
2794 | { 2, CMPLX((32 * 4 + 1) * 4 + 4), 0x7913ba03, "SHA256:2" }, | ||
2795 | { 5, 3200, 0xe7aeb394, "SHA512:1" }, | ||
2796 | { 2, CMPLX((40 * 4 + 1) * 4 + 4), 0xe7aeb394, "SHA512:2" }, | ||
2797 | // { 10, 3428, 0x1cc99b18, "SHAKE128" }, | ||
2798 | // { 10, 4235, 0x74eaddc3, "SHAKE256" }, | ||
2799 | // { 10, 4000, 0xdf3e6863, "SHA3-224" }, | ||
2800 | { 5, 4200, 0xcecac10d, "SHA3-256" }, | ||
2801 | // { 10, 5538, 0x4e5d9163, "SHA3-384" }, | ||
2802 | // { 10, 8000, 0x96a58289, "SHA3-512" }, | ||
2753 | { 2, 4096, 0x85189d02, "BLAKE2sp:1" }, | 2803 | { 2, 4096, 0x85189d02, "BLAKE2sp:1" }, |
2754 | { 2, 1024, 0x85189d02, "BLAKE2sp:2" }, // sse2-way4-fast | 2804 | { 2, 1024, 0x85189d02, "BLAKE2sp:2" }, // sse2-way4-fast |
2755 | { 2, 512, 0x85189d02, "BLAKE2sp:3" } // avx2-way8-fast | 2805 | { 2, 512, 0x85189d02, "BLAKE2sp:3" } // avx2-way8-fast |
@@ -2934,7 +2984,7 @@ AString GetProcessThreadsInfo(const NSystem::CProcessAffinity &ti) | |||
2934 | { | 2984 | { |
2935 | AString s; | 2985 | AString s; |
2936 | // s.Add_UInt32(ti.numProcessThreads); | 2986 | // s.Add_UInt32(ti.numProcessThreads); |
2937 | unsigned numSysThreads = ti.GetNumSystemThreads(); | 2987 | const unsigned numSysThreads = ti.GetNumSystemThreads(); |
2938 | if (ti.GetNumProcessThreads() != numSysThreads) | 2988 | if (ti.GetNumProcessThreads() != numSysThreads) |
2939 | { | 2989 | { |
2940 | // if (ti.numProcessThreads != ti.numSysThreads) | 2990 | // if (ti.numProcessThreads != ti.numSysThreads) |
@@ -2964,6 +3014,35 @@ AString GetProcessThreadsInfo(const NSystem::CProcessAffinity &ti) | |||
2964 | } | 3014 | } |
2965 | #endif | 3015 | #endif |
2966 | } | 3016 | } |
3017 | #ifdef _WIN32 | ||
3018 | if (ti.Groups.GroupSizes.Size() > 1 || | ||
3019 | (ti.Groups.GroupSizes.Size() == 1 | ||
3020 | && ti.Groups.NumThreadsTotal != numSysThreads)) | ||
3021 | { | ||
3022 | s += " : "; | ||
3023 | s.Add_UInt32(ti.Groups.GroupSizes.Size()); | ||
3024 | s += " groups : "; | ||
3025 | if (ti.Groups.NumThreadsTotal == numSysThreads) | ||
3026 | { | ||
3027 | s.Add_UInt32(ti.Groups.NumThreadsTotal); | ||
3028 | s += " c : "; | ||
3029 | } | ||
3030 | UInt32 minSize, maxSize; | ||
3031 | ti.Groups.Get_GroupSize_Min_Max(minSize, maxSize); | ||
3032 | if (minSize == maxSize) | ||
3033 | { | ||
3034 | s.Add_UInt32(ti.Groups.GroupSizes[0]); | ||
3035 | s += " c/g"; | ||
3036 | } | ||
3037 | else | ||
3038 | FOR_VECTOR (i, ti.Groups.GroupSizes) | ||
3039 | { | ||
3040 | if (i != 0) | ||
3041 | s.Add_Char(' '); | ||
3042 | s.Add_UInt32(ti.Groups.GroupSizes[i]); | ||
3043 | } | ||
3044 | } | ||
3045 | #endif | ||
2967 | return s; | 3046 | return s; |
2968 | } | 3047 | } |
2969 | 3048 | ||
@@ -3687,7 +3766,7 @@ HRESULT Bench( | |||
3687 | return E_FAIL; | 3766 | return E_FAIL; |
3688 | 3767 | ||
3689 | UInt32 numCPUs = 1; | 3768 | UInt32 numCPUs = 1; |
3690 | UInt64 ramSize = (UInt64)(sizeof(size_t)) << 29; | 3769 | size_t ramSize = (size_t)sizeof(size_t) << 29; |
3691 | 3770 | ||
3692 | NSystem::CProcessAffinity threadsInfo; | 3771 | NSystem::CProcessAffinity threadsInfo; |
3693 | threadsInfo.InitST(); | 3772 | threadsInfo.InitST(); |
@@ -3725,9 +3804,13 @@ HRESULT Bench( | |||
3725 | UInt64 complexInCommands = kComplexInCommands; | 3804 | UInt64 complexInCommands = kComplexInCommands; |
3726 | UInt32 numThreads_Start = 1; | 3805 | UInt32 numThreads_Start = 1; |
3727 | 3806 | ||
3728 | #ifndef Z7_ST | 3807 | #ifndef Z7_ST |
3729 | CAffinityMode affinityMode; | 3808 | CAffinityMode affinityMode; |
3730 | #endif | 3809 | #ifdef _WIN32 |
3810 | if (threadsInfo.IsGroupMode && threadsInfo.Groups.GroupSizes.Size() > 1) | ||
3811 | affinityMode.NumGroups = threadsInfo.Groups.GroupSizes.Size(); | ||
3812 | #endif | ||
3813 | #endif | ||
3731 | 3814 | ||
3732 | 3815 | ||
3733 | COneMethodInfo method; | 3816 | COneMethodInfo method; |
@@ -4580,6 +4663,8 @@ HRESULT Bench( | |||
4580 | 4663 | ||
4581 | if (!dictIsDefined && !onlyHashBench) | 4664 | if (!dictIsDefined && !onlyHashBench) |
4582 | { | 4665 | { |
4666 | // we use dicSizeLog and dicSizeLog_Main for data size. | ||
4667 | // also we use it to reduce dictionary size of LZMA encoder via NCoderPropID::kReduceSize. | ||
4583 | const unsigned dicSizeLog_Main = (totalBenchMode ? 24 : 25); | 4668 | const unsigned dicSizeLog_Main = (totalBenchMode ? 24 : 25); |
4584 | unsigned dicSizeLog = dicSizeLog_Main; | 4669 | unsigned dicSizeLog = dicSizeLog_Main; |
4585 | 4670 | ||
@@ -4831,7 +4916,7 @@ HRESULT Bench( | |||
4831 | if (AreSameMethodNames(benchMethod, methodName)) | 4916 | if (AreSameMethodNames(benchMethod, methodName)) |
4832 | { | 4917 | { |
4833 | if (benchProps.IsEmpty() | 4918 | if (benchProps.IsEmpty() |
4834 | || (benchProps == "x5" && method.PropsString.IsEmpty()) | 4919 | || (benchProps.IsEqualTo("x5") && method.PropsString.IsEmpty()) |
4835 | || method.PropsString.IsPrefixedBy_Ascii_NoCase(benchProps)) | 4920 | || method.PropsString.IsPrefixedBy_Ascii_NoCase(benchProps)) |
4836 | { | 4921 | { |
4837 | callback.BenchProps.EncComplex = h.EncComplex; | 4922 | callback.BenchProps.EncComplex = h.EncComplex; |
diff --git a/CPP/7zip/UI/Common/EnumDirItems.cpp b/CPP/7zip/UI/Common/EnumDirItems.cpp index 0758547..cada2e6 100644 --- a/CPP/7zip/UI/Common/EnumDirItems.cpp +++ b/CPP/7zip/UI/Common/EnumDirItems.cpp | |||
@@ -671,7 +671,7 @@ static HRESULT EnumerateForItem( | |||
671 | } | 671 | } |
672 | 672 | ||
673 | #if defined(_WIN32) | 673 | #if defined(_WIN32) |
674 | if (needAltStreams && dirItems.ScanAltStreams) | 674 | if (needAltStreams && dirItems.ScanAltStreams && !fi.IsAltStream) |
675 | { | 675 | { |
676 | RINOK(EnumerateAltStreams(fi, curNode, phyParent, logParent, | 676 | RINOK(EnumerateAltStreams(fi, curNode, phyParent, logParent, |
677 | phyPrefix + fi.Name, // with (fi.Name) | 677 | phyPrefix + fi.Name, // with (fi.Name) |
@@ -929,7 +929,7 @@ static HRESULT EnumerateDirItems( | |||
929 | } | 929 | } |
930 | 930 | ||
931 | #if defined(_WIN32) | 931 | #if defined(_WIN32) |
932 | if (needAltStreams && dirItems.ScanAltStreams) | 932 | if (needAltStreams && dirItems.ScanAltStreams && !fi.IsAltStream) |
933 | { | 933 | { |
934 | UStringVector pathParts; | 934 | UStringVector pathParts; |
935 | pathParts.Add(fs2us(fi.Name)); | 935 | pathParts.Add(fs2us(fi.Name)); |
@@ -1213,11 +1213,13 @@ HRESULT CDirItems::FillFixedReparse() | |||
1213 | // continue; // for debug | 1213 | // continue; // for debug |
1214 | if (!item.Has_Attrib_ReparsePoint()) | 1214 | if (!item.Has_Attrib_ReparsePoint()) |
1215 | continue; | 1215 | continue; |
1216 | 1216 | /* | |
1217 | We want to get properties of target file instead of properies of symbolic link. | ||
1218 | Probably this code is unused, because | ||
1219 | CFileInfo::Find(with followLink = true) called Fill_From_ByHandleFileInfo() already. | ||
1220 | */ | ||
1217 | // if (item.IsDir()) continue; | 1221 | // if (item.IsDir()) continue; |
1218 | |||
1219 | const FString phyPath = GetPhyPath(i); | 1222 | const FString phyPath = GetPhyPath(i); |
1220 | |||
1221 | NFind::CFileInfo fi; | 1223 | NFind::CFileInfo fi; |
1222 | if (fi.Fill_From_ByHandleFileInfo(phyPath)) // item.IsDir() | 1224 | if (fi.Fill_From_ByHandleFileInfo(phyPath)) // item.IsDir() |
1223 | { | 1225 | { |
@@ -1228,38 +1230,13 @@ HRESULT CDirItems::FillFixedReparse() | |||
1228 | item.Attrib = fi.Attrib; | 1230 | item.Attrib = fi.Attrib; |
1229 | continue; | 1231 | continue; |
1230 | } | 1232 | } |
1231 | |||
1232 | /* | ||
1233 | // we request properties of target file instead of properies of symbolic link | ||
1234 | // here we also can manually parse unsupported links (like WSL links) | ||
1235 | NIO::CInFile inFile; | ||
1236 | if (inFile.Open(phyPath)) | ||
1237 | { | ||
1238 | BY_HANDLE_FILE_INFORMATION info; | ||
1239 | if (inFile.GetFileInformation(&info)) | ||
1240 | { | ||
1241 | // Stat.FilesSize doesn't contain item.Size already | ||
1242 | // Stat.FilesSize -= item.Size; | ||
1243 | item.Size = (((UInt64)info.nFileSizeHigh) << 32) + info.nFileSizeLow; | ||
1244 | Stat.FilesSize += item.Size; | ||
1245 | item.CTime = info.ftCreationTime; | ||
1246 | item.ATime = info.ftLastAccessTime; | ||
1247 | item.MTime = info.ftLastWriteTime; | ||
1248 | item.Attrib = info.dwFileAttributes; | ||
1249 | continue; | ||
1250 | } | ||
1251 | } | ||
1252 | */ | ||
1253 | |||
1254 | RINOK(AddError(phyPath)) | 1233 | RINOK(AddError(phyPath)) |
1255 | continue; | 1234 | continue; |
1256 | } | 1235 | } |
1257 | 1236 | ||
1258 | // (SymLinks == true) here | 1237 | // (SymLinks == true) |
1259 | |||
1260 | if (item.ReparseData.Size() == 0) | 1238 | if (item.ReparseData.Size() == 0) |
1261 | continue; | 1239 | continue; |
1262 | |||
1263 | // if (item.Size == 0) | 1240 | // if (item.Size == 0) |
1264 | { | 1241 | { |
1265 | // 20.03: we use Reparse Data instead of real data | 1242 | // 20.03: we use Reparse Data instead of real data |
@@ -1277,7 +1254,7 @@ HRESULT CDirItems::FillFixedReparse() | |||
1277 | /* imagex/WIM reduces absolute paths in links (raparse data), | 1254 | /* imagex/WIM reduces absolute paths in links (raparse data), |
1278 | if we archive non root folder. We do same thing here */ | 1255 | if we archive non root folder. We do same thing here */ |
1279 | 1256 | ||
1280 | bool isWSL = false; | 1257 | // bool isWSL = false; |
1281 | if (attr.IsSymLink_WSL()) | 1258 | if (attr.IsSymLink_WSL()) |
1282 | { | 1259 | { |
1283 | // isWSL = true; | 1260 | // isWSL = true; |
@@ -1314,21 +1291,27 @@ HRESULT CDirItems::FillFixedReparse() | |||
1314 | continue; | 1291 | continue; |
1315 | if (rootPrefixSize == prefix.Len()) | 1292 | if (rootPrefixSize == prefix.Len()) |
1316 | continue; // simple case: paths are from root | 1293 | continue; // simple case: paths are from root |
1317 | |||
1318 | if (link.Len() <= prefix.Len()) | 1294 | if (link.Len() <= prefix.Len()) |
1319 | continue; | 1295 | continue; |
1320 | |||
1321 | if (CompareFileNames(link.Left(prefix.Len()), prefix) != 0) | 1296 | if (CompareFileNames(link.Left(prefix.Len()), prefix) != 0) |
1322 | continue; | 1297 | continue; |
1323 | 1298 | ||
1324 | UString newLink = prefix.Left(rootPrefixSize); | 1299 | UString newLink = prefix.Left(rootPrefixSize); |
1325 | newLink += link.Ptr(prefix.Len()); | 1300 | newLink += link.Ptr(prefix.Len()); |
1326 | 1301 | ||
1327 | CByteBuffer data; | 1302 | CByteBuffer &data = item.ReparseData2; |
1328 | bool isSymLink = !attr.IsMountPoint(); | 1303 | /* |
1329 | if (!FillLinkData(data, newLink, isSymLink, isWSL)) | 1304 | if (isWSL) |
1305 | { | ||
1306 | Convert_WinPath_to_WslLinuxPath(newLink, true); // is absolute : change it | ||
1307 | FillLinkData_WslLink(data, newLink); | ||
1308 | } | ||
1309 | else | ||
1310 | */ | ||
1311 | FillLinkData_WinLink(data, newLink, !attr.IsMountPoint()); | ||
1312 | if (data.Size() == 0) | ||
1330 | continue; | 1313 | continue; |
1331 | item.ReparseData2 = data; | 1314 | // item.ReparseData2 = data; |
1332 | } | 1315 | } |
1333 | return S_OK; | 1316 | return S_OK; |
1334 | } | 1317 | } |
diff --git a/CPP/7zip/UI/Common/Extract.cpp b/CPP/7zip/UI/Common/Extract.cpp index 010b01c..0301976 100644 --- a/CPP/7zip/UI/Common/Extract.cpp +++ b/CPP/7zip/UI/Common/Extract.cpp | |||
@@ -389,7 +389,7 @@ HRESULT Extract( | |||
389 | { | 389 | { |
390 | UString s = arcPath.Ptr(pos + 1); | 390 | UString s = arcPath.Ptr(pos + 1); |
391 | int index = codecs->FindFormatForExtension(s); | 391 | int index = codecs->FindFormatForExtension(s); |
392 | if (index >= 0 && s == L"001") | 392 | if (index >= 0 && s.IsEqualTo("001")) |
393 | { | 393 | { |
394 | s = arcPath.Left(pos); | 394 | s = arcPath.Left(pos); |
395 | pos = s.ReverseFind(L'.'); | 395 | pos = s.ReverseFind(L'.'); |
diff --git a/CPP/7zip/UI/Common/ExtractingFilePath.cpp b/CPP/7zip/UI/Common/ExtractingFilePath.cpp index 88da4ad..5ca5e66 100644 --- a/CPP/7zip/UI/Common/ExtractingFilePath.cpp +++ b/CPP/7zip/UI/Common/ExtractingFilePath.cpp | |||
@@ -208,7 +208,7 @@ void Correct_FsPath(bool absIsAllowed, bool keepAndReplaceEmptyPrefixes, UString | |||
208 | if (parts.Size() > 1 && parts[1].IsEmpty()) | 208 | if (parts.Size() > 1 && parts[1].IsEmpty()) |
209 | { | 209 | { |
210 | i = 2; | 210 | i = 2; |
211 | if (parts.Size() > 2 && parts[2] == L"?") | 211 | if (parts.Size() > 2 && parts[2].IsEqualTo("?")) |
212 | { | 212 | { |
213 | i = 3; | 213 | i = 3; |
214 | if (parts.Size() > 3 && NWindows::NFile::NName::IsDrivePath2(parts[3])) | 214 | if (parts.Size() > 3 && NWindows::NFile::NName::IsDrivePath2(parts[3])) |
diff --git a/CPP/7zip/UI/Common/HashCalc.cpp b/CPP/7zip/UI/Common/HashCalc.cpp index f3d65ef..f026f80 100644 --- a/CPP/7zip/UI/Common/HashCalc.cpp +++ b/CPP/7zip/UI/Common/HashCalc.cpp | |||
@@ -62,7 +62,7 @@ HRESULT CHashBundle::SetMethods(DECL_EXTERNAL_CODECS_LOC_VARS const UStringVecto | |||
62 | if (m.MethodName.IsEmpty()) | 62 | if (m.MethodName.IsEmpty()) |
63 | m.MethodName = k_DefaultHashMethod; | 63 | m.MethodName = k_DefaultHashMethod; |
64 | 64 | ||
65 | if (m.MethodName == "*") | 65 | if (m.MethodName.IsEqualTo("*")) |
66 | { | 66 | { |
67 | CRecordVector<CMethodId> tempMethods; | 67 | CRecordVector<CMethodId> tempMethods; |
68 | GetHashMethods(EXTERNAL_CODECS_LOC_VARS tempMethods); | 68 | GetHashMethods(EXTERNAL_CODECS_LOC_VARS tempMethods); |
@@ -431,6 +431,19 @@ static void WriteLine(CDynLimBuf &hashFileString, | |||
431 | } | 431 | } |
432 | 432 | ||
433 | 433 | ||
434 | static void Convert_TagName_to_MethodName(AString &method) | ||
435 | { | ||
436 | // we need to convert at least SHA512/256 to SHA512-256, and SHA512/224 to SHA512-224 | ||
437 | // but we convert any '/' to '-'. | ||
438 | method.Replace('/', '-'); | ||
439 | } | ||
440 | |||
441 | static void Convert_MethodName_to_TagName(AString &method) | ||
442 | { | ||
443 | if (method.IsPrefixedBy_Ascii_NoCase("SHA512-2")) | ||
444 | method.ReplaceOneCharAtPos(6, '/'); | ||
445 | } | ||
446 | |||
434 | 447 | ||
435 | static void WriteLine(CDynLimBuf &hashFileString, | 448 | static void WriteLine(CDynLimBuf &hashFileString, |
436 | const CHashOptionsLocal &options, | 449 | const CHashOptionsLocal &options, |
@@ -440,8 +453,10 @@ static void WriteLine(CDynLimBuf &hashFileString, | |||
440 | { | 453 | { |
441 | AString methodName; | 454 | AString methodName; |
442 | if (!hb.Hashers.IsEmpty()) | 455 | if (!hb.Hashers.IsEmpty()) |
456 | { | ||
443 | methodName = hb.Hashers[0].Name; | 457 | methodName = hb.Hashers[0].Name; |
444 | 458 | Convert_MethodName_to_TagName(methodName); | |
459 | } | ||
445 | AString hashesString; | 460 | AString hashesString; |
446 | AddHashResultLine(hashesString, hb.Hashers); | 461 | AddHashResultLine(hashesString, hb.Hashers); |
447 | WriteLine(hashFileString, options, path, isDir, methodName, hashesString); | 462 | WriteLine(hashFileString, options, path, isDir, methodName, hashesString); |
@@ -752,7 +767,7 @@ bool CHashPair::ParseCksum(const char *s) | |||
752 | Name = end; | 767 | Name = end; |
753 | 768 | ||
754 | Hash.Alloc(4); | 769 | Hash.Alloc(4); |
755 | SetBe32(Hash, crc) | 770 | SetBe32a(Hash, crc) |
756 | 771 | ||
757 | Size_from_Arc = size; | 772 | Size_from_Arc = size; |
758 | Size_from_Arc_Defined = true; | 773 | Size_from_Arc_Defined = true; |
@@ -773,48 +788,87 @@ static const char * const k_CsumMethodNames[] = | |||
773 | { | 788 | { |
774 | "sha256" | 789 | "sha256" |
775 | , "sha224" | 790 | , "sha224" |
776 | // , "sha512/224" | 791 | , "sha512-224" |
777 | // , "sha512/256" | 792 | , "sha512-256" |
778 | , "sha512" | ||
779 | , "sha384" | 793 | , "sha384" |
794 | , "sha512" | ||
795 | , "sha3-224" | ||
796 | , "sha3-256" | ||
797 | , "sha3-384" | ||
798 | , "sha3-512" | ||
799 | // , "shake128" | ||
800 | // , "shake256" | ||
780 | , "sha1" | 801 | , "sha1" |
802 | , "sha2" | ||
803 | , "sha3" | ||
804 | , "sha" | ||
781 | , "md5" | 805 | , "md5" |
806 | , "blake2s" | ||
782 | , "blake2b" | 807 | , "blake2b" |
783 | , "crc64" | 808 | , "blake2sp" |
809 | , "xxh64" | ||
784 | , "crc32" | 810 | , "crc32" |
811 | , "crc64" | ||
785 | , "cksum" | 812 | , "cksum" |
786 | }; | 813 | }; |
787 | 814 | ||
788 | static UString GetMethod_from_FileName(const UString &name) | 815 | |
816 | // returns true, if (method) is known hash method or hash method group name. | ||
817 | static bool GetMethod_from_FileName(const UString &name, AString &method) | ||
789 | { | 818 | { |
819 | method.Empty(); | ||
790 | AString s; | 820 | AString s; |
791 | ConvertUnicodeToUTF8(name, s); | 821 | ConvertUnicodeToUTF8(name, s); |
792 | const int dotPos = s.ReverseFind_Dot(); | 822 | const int dotPos = s.ReverseFind_Dot(); |
793 | const char *src = s.Ptr(); | ||
794 | bool isExtension = false; | ||
795 | if (dotPos >= 0) | 823 | if (dotPos >= 0) |
796 | { | 824 | { |
797 | isExtension = true; | 825 | method = s.Ptr(dotPos + 1); |
798 | src = s.Ptr(dotPos + 1); | 826 | if (method.IsEqualTo_Ascii_NoCase("txt") || |
827 | method.IsEqualTo_Ascii_NoCase("asc")) | ||
828 | { | ||
829 | method.Empty(); | ||
830 | const int dotPos2 = s.Find('.'); | ||
831 | if (dotPos2 >= 0) | ||
832 | s.DeleteFrom(dotPos2); | ||
833 | } | ||
799 | } | 834 | } |
800 | const char *m = ""; | 835 | if (method.IsEmpty()) |
836 | { | ||
837 | // we support file names with "sum" and "sums" postfixes: "sha256sum", "sha256sums" | ||
838 | unsigned size; | ||
839 | if (s.Len() > 4 && StringsAreEqualNoCase_Ascii(s.RightPtr(4), "sums")) | ||
840 | size = 4; | ||
841 | else if (s.Len() > 3 && StringsAreEqualNoCase_Ascii(s.RightPtr(3), "sum")) | ||
842 | size = 3; | ||
843 | else | ||
844 | return false; | ||
845 | method = s; | ||
846 | method.DeleteFrom(s.Len() - size); | ||
847 | } | ||
848 | |||
801 | unsigned i; | 849 | unsigned i; |
802 | for (i = 0; i < Z7_ARRAY_SIZE(k_CsumMethodNames); i++) | 850 | for (i = 0; i < Z7_ARRAY_SIZE(k_CsumMethodNames); i++) |
803 | { | 851 | { |
804 | m = k_CsumMethodNames[i]; | 852 | const char *m = k_CsumMethodNames[i]; |
805 | if (isExtension) | 853 | if (method.IsEqualTo_Ascii_NoCase(m)) |
806 | { | 854 | { |
807 | if (StringsAreEqual_Ascii(src, m)) | 855 | // method = m; // we can get lowcase |
808 | break; | 856 | return true; |
809 | } | 857 | } |
810 | else if (IsString1PrefixedByString2_NoCase_Ascii(src, m)) | ||
811 | if (StringsAreEqual_Ascii(src + strlen(m), "sums")) | ||
812 | break; | ||
813 | } | 858 | } |
814 | UString res; | 859 | |
815 | if (i != Z7_ARRAY_SIZE(k_CsumMethodNames)) | 860 | /* |
816 | res = m; | 861 | for (i = 0; i < Z7_ARRAY_SIZE(k_CsumMethodNames); i++) |
817 | return res; | 862 | { |
863 | const char *m = k_CsumMethodNames[i]; | ||
864 | if (method.IsPrefixedBy_Ascii_NoCase(m)) | ||
865 | { | ||
866 | method = m; // we get lowcase | ||
867 | return true; | ||
868 | } | ||
869 | } | ||
870 | */ | ||
871 | return false; | ||
818 | } | 872 | } |
819 | 873 | ||
820 | 874 | ||
@@ -1039,7 +1093,7 @@ Z7_COM7F_IMF(CHandler::GetRawProp(UInt32 index, PROPID propID, const void **data | |||
1039 | if (propID == kpidChecksum) | 1093 | if (propID == kpidChecksum) |
1040 | { | 1094 | { |
1041 | const CHashPair &hp = HashPairs[index]; | 1095 | const CHashPair &hp = HashPairs[index]; |
1042 | if (hp.Hash.Size() > 0) | 1096 | if (hp.Hash.Size() != 0) |
1043 | { | 1097 | { |
1044 | *data = hp.Hash; | 1098 | *data = hp.Hash; |
1045 | *dataSize = (UInt32)hp.Hash.Size(); | 1099 | *dataSize = (UInt32)hp.Hash.Size(); |
@@ -1092,11 +1146,6 @@ Z7_COM7F_IMF(CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value)) | |||
1092 | s.Add_UInt32(_hashSize * 8); | 1146 | s.Add_UInt32(_hashSize * 8); |
1093 | s += "-bit"; | 1147 | s += "-bit"; |
1094 | } | 1148 | } |
1095 | if (!_nameExtenstion.IsEmpty()) | ||
1096 | { | ||
1097 | s.Add_Space_if_NotEmpty(); | ||
1098 | s += _nameExtenstion; | ||
1099 | } | ||
1100 | if (_is_PgpMethod) | 1149 | if (_is_PgpMethod) |
1101 | { | 1150 | { |
1102 | Add_OptSpace_String(s, "PGP"); | 1151 | Add_OptSpace_String(s, "PGP"); |
@@ -1112,6 +1161,18 @@ Z7_COM7F_IMF(CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value)) | |||
1112 | Add_OptSpace_String(s, "TAG"); | 1161 | Add_OptSpace_String(s, "TAG"); |
1113 | if (_are_there_Dirs) | 1162 | if (_are_there_Dirs) |
1114 | Add_OptSpace_String(s, "DIRS"); | 1163 | Add_OptSpace_String(s, "DIRS"); |
1164 | if (!_method_from_FileName.IsEmpty()) | ||
1165 | { | ||
1166 | Add_OptSpace_String(s, "filename_method:"); | ||
1167 | s += _method_from_FileName; | ||
1168 | if (!_is_KnownMethod_in_FileName) | ||
1169 | s += ":UNKNOWN"; | ||
1170 | } | ||
1171 | if (!_methods.IsEmpty()) | ||
1172 | { | ||
1173 | Add_OptSpace_String(s, "cmd_method:"); | ||
1174 | s += _methods[0]; | ||
1175 | } | ||
1115 | prop = s; | 1176 | prop = s; |
1116 | break; | 1177 | break; |
1117 | } | 1178 | } |
@@ -1220,6 +1281,15 @@ static HRESULT ReadStream_to_Buf(IInStream *stream, CByteBuffer &buf, IArchiveOp | |||
1220 | } | 1281 | } |
1221 | 1282 | ||
1222 | 1283 | ||
1284 | static bool isThere_Zero_Byte(const Byte *data, size_t size) | ||
1285 | { | ||
1286 | for (size_t i = 0; i < size; i++) | ||
1287 | if (data[i] == 0) | ||
1288 | return true; | ||
1289 | return false; | ||
1290 | } | ||
1291 | |||
1292 | |||
1223 | Z7_COM7F_IMF(CHandler::Open(IInStream *stream, const UInt64 *, IArchiveOpenCallback *openCallback)) | 1293 | Z7_COM7F_IMF(CHandler::Open(IInStream *stream, const UInt64 *, IArchiveOpenCallback *openCallback)) |
1224 | { | 1294 | { |
1225 | COM_TRY_BEGIN | 1295 | COM_TRY_BEGIN |
@@ -1231,17 +1301,9 @@ Z7_COM7F_IMF(CHandler::Open(IInStream *stream, const UInt64 *, IArchiveOpenCallb | |||
1231 | 1301 | ||
1232 | CObjectVector<CHashPair> &pairs = HashPairs; | 1302 | CObjectVector<CHashPair> &pairs = HashPairs; |
1233 | 1303 | ||
1234 | bool zeroMode = false; | 1304 | const bool zeroMode = isThere_Zero_Byte(buf, buf.Size()); |
1235 | bool cr_lf_Mode = false; | ||
1236 | { | ||
1237 | for (size_t i = 0; i < buf.Size(); i++) | ||
1238 | if (buf.ConstData()[i] == 0) | ||
1239 | { | ||
1240 | zeroMode = true; | ||
1241 | break; | ||
1242 | } | ||
1243 | } | ||
1244 | _is_ZeroMode = zeroMode; | 1305 | _is_ZeroMode = zeroMode; |
1306 | bool cr_lf_Mode = false; | ||
1245 | if (!zeroMode) | 1307 | if (!zeroMode) |
1246 | cr_lf_Mode = Is_CR_LF_Data(buf, buf.Size()); | 1308 | cr_lf_Mode = Is_CR_LF_Data(buf, buf.Size()); |
1247 | 1309 | ||
@@ -1255,13 +1317,21 @@ Z7_COM7F_IMF(CHandler::Open(IInStream *stream, const UInt64 *, IArchiveOpenCallb | |||
1255 | NCOM::CPropVariant prop; | 1317 | NCOM::CPropVariant prop; |
1256 | RINOK(openVolumeCallback->GetProperty(kpidName, &prop)) | 1318 | RINOK(openVolumeCallback->GetProperty(kpidName, &prop)) |
1257 | if (prop.vt == VT_BSTR) | 1319 | if (prop.vt == VT_BSTR) |
1258 | _nameExtenstion = GetMethod_from_FileName(prop.bstrVal); | 1320 | _is_KnownMethod_in_FileName = GetMethod_from_FileName(prop.bstrVal, _method_from_FileName); |
1259 | } | 1321 | } |
1260 | } | 1322 | } |
1261 | 1323 | ||
1262 | bool cksumMode = false; | 1324 | if (!_methods.IsEmpty()) |
1263 | if (_nameExtenstion.IsEqualTo_Ascii_NoCase("cksum")) | 1325 | { |
1264 | cksumMode = true; | 1326 | ConvertUnicodeToUTF8(_methods[0], _method_for_Extraction); |
1327 | } | ||
1328 | if (_method_for_Extraction.IsEmpty()) | ||
1329 | { | ||
1330 | // if (_is_KnownMethod_in_FileName) | ||
1331 | _method_for_Extraction = _method_from_FileName; | ||
1332 | } | ||
1333 | |||
1334 | const bool cksumMode = _method_for_Extraction.IsEqualTo_Ascii_NoCase("cksum"); | ||
1265 | _is_CksumMode = cksumMode; | 1335 | _is_CksumMode = cksumMode; |
1266 | 1336 | ||
1267 | size_t pos = 0; | 1337 | size_t pos = 0; |
@@ -1358,6 +1428,7 @@ void CHandler::ClearVars() | |||
1358 | _is_ZeroMode = false; | 1428 | _is_ZeroMode = false; |
1359 | _are_there_Tags = false; | 1429 | _are_there_Tags = false; |
1360 | _are_there_Dirs = false; | 1430 | _are_there_Dirs = false; |
1431 | _is_KnownMethod_in_FileName = false; | ||
1361 | _hashSize_Defined = false; | 1432 | _hashSize_Defined = false; |
1362 | _hashSize = 0; | 1433 | _hashSize = 0; |
1363 | } | 1434 | } |
@@ -1366,7 +1437,8 @@ void CHandler::ClearVars() | |||
1366 | Z7_COM7F_IMF(CHandler::Close()) | 1437 | Z7_COM7F_IMF(CHandler::Close()) |
1367 | { | 1438 | { |
1368 | ClearVars(); | 1439 | ClearVars(); |
1369 | _nameExtenstion.Empty(); | 1440 | _method_from_FileName.Empty(); |
1441 | _method_for_Extraction.Empty(); | ||
1370 | _pgpMethod.Empty(); | 1442 | _pgpMethod.Empty(); |
1371 | HashPairs.Clear(); | 1443 | HashPairs.Clear(); |
1372 | return S_OK; | 1444 | return S_OK; |
@@ -1393,19 +1465,73 @@ static bool CheckDigests(const Byte *a, const Byte *b, size_t size) | |||
1393 | } | 1465 | } |
1394 | 1466 | ||
1395 | 1467 | ||
1396 | static void AddDefaultMethod(UStringVector &methods, unsigned size) | 1468 | static void AddDefaultMethod(UStringVector &methods, |
1469 | const char *name, unsigned size) | ||
1397 | { | 1470 | { |
1471 | int shaVersion = -1; | ||
1472 | if (name) | ||
1473 | { | ||
1474 | if (StringsAreEqualNoCase_Ascii(name, "sha")) | ||
1475 | { | ||
1476 | shaVersion = 0; | ||
1477 | if (size == 0) | ||
1478 | size = 32; | ||
1479 | } | ||
1480 | else if (StringsAreEqualNoCase_Ascii(name, "sha1")) | ||
1481 | { | ||
1482 | shaVersion = 1; | ||
1483 | if (size == 0) | ||
1484 | size = 20; | ||
1485 | } | ||
1486 | else if (StringsAreEqualNoCase_Ascii(name, "sha2")) | ||
1487 | { | ||
1488 | shaVersion = 2; | ||
1489 | if (size == 0) | ||
1490 | size = 32; | ||
1491 | } | ||
1492 | else if (StringsAreEqualNoCase_Ascii(name, "sha3")) | ||
1493 | { | ||
1494 | if (size == 0 || | ||
1495 | size == 32) name = "sha3-256"; | ||
1496 | else if (size == 28) name = "sha3-224"; | ||
1497 | else if (size == 48) name = "sha3-384"; | ||
1498 | else if (size == 64) name = "sha3-512"; | ||
1499 | } | ||
1500 | else if (StringsAreEqualNoCase_Ascii(name, "sha512")) | ||
1501 | { | ||
1502 | // we allow any sha512 derived hash inside .sha512 file: | ||
1503 | if (size == 48) name = "sha384"; | ||
1504 | else if (size == 32) name = "sha512-256"; | ||
1505 | else if (size == 28) name = "sha512-224"; | ||
1506 | } | ||
1507 | if (shaVersion >= 0) | ||
1508 | name = NULL; | ||
1509 | } | ||
1510 | |||
1398 | const char *m = NULL; | 1511 | const char *m = NULL; |
1399 | if (size == 32) m = "sha256"; | 1512 | if (name) |
1400 | else if (size == 20) m = "sha1"; | 1513 | m = name; |
1401 | else if (size == 16) m = "md5"; | ||
1402 | else if (size == 8) m = "crc64"; | ||
1403 | else if (size == 4) m = "crc32"; | ||
1404 | else | 1514 | else |
1515 | { | ||
1516 | if (size == 64) m = "sha512"; | ||
1517 | else if (size == 48) m = "sha384"; | ||
1518 | else if (size == 32) m = "sha256"; | ||
1519 | else if (size == 28) m = "sha224"; | ||
1520 | else if (size == 20) m = "sha1"; | ||
1521 | else if (shaVersion < 0) | ||
1522 | { | ||
1523 | if (size == 16) m = "md5"; | ||
1524 | else if (size == 8) m = "crc64"; | ||
1525 | else if (size == 4) m = "crc32"; | ||
1526 | } | ||
1527 | } | ||
1528 | |||
1529 | if (!m) | ||
1405 | return; | 1530 | return; |
1406 | #ifdef Z7_EXTERNAL_CODECS | 1531 | |
1532 | #ifdef Z7_EXTERNAL_CODECS | ||
1407 | const CExternalCodecs *_externalCodecs = g_ExternalCodecs_Ptr; | 1533 | const CExternalCodecs *_externalCodecs = g_ExternalCodecs_Ptr; |
1408 | #endif | 1534 | #endif |
1409 | CMethodId id; | 1535 | CMethodId id; |
1410 | if (FindHashMethod(EXTERNAL_CODECS_LOC_VARS | 1536 | if (FindHashMethod(EXTERNAL_CODECS_LOC_VARS |
1411 | AString(m), id)) | 1537 | AString(m), id)) |
@@ -1436,15 +1562,15 @@ Z7_COM7F_IMF(CHandler::Extract(const UInt32 *indices, UInt32 numItems, | |||
1436 | CHashBundle hb_Glob; | 1562 | CHashBundle hb_Glob; |
1437 | // UStringVector methods = options.Methods; | 1563 | // UStringVector methods = options.Methods; |
1438 | UStringVector methods; | 1564 | UStringVector methods; |
1439 | 1565 | ||
1440 | if (methods.IsEmpty() && !_nameExtenstion.IsEmpty()) | 1566 | /* |
1567 | if (methods.IsEmpty() && !utf_nameExtenstion.IsEmpty() && !_hashSize_Defined) | ||
1441 | { | 1568 | { |
1442 | AString utf; | ||
1443 | ConvertUnicodeToUTF8(_nameExtenstion, utf); | ||
1444 | CMethodId id; | 1569 | CMethodId id; |
1445 | if (FindHashMethod(EXTERNAL_CODECS_LOC_VARS utf, id)) | 1570 | if (FindHashMethod(EXTERNAL_CODECS_LOC_VARS utf_nameExtenstion, id)) |
1446 | methods.Add(_nameExtenstion); | 1571 | methods.Add(_nameExtenstion); |
1447 | } | 1572 | } |
1573 | */ | ||
1448 | 1574 | ||
1449 | if (methods.IsEmpty() && !_pgpMethod.IsEmpty()) | 1575 | if (methods.IsEmpty() && !_pgpMethod.IsEmpty()) |
1450 | { | 1576 | { |
@@ -1453,12 +1579,21 @@ Z7_COM7F_IMF(CHandler::Extract(const UInt32 *indices, UInt32 numItems, | |||
1453 | methods.Add(UString(_pgpMethod)); | 1579 | methods.Add(UString(_pgpMethod)); |
1454 | } | 1580 | } |
1455 | 1581 | ||
1582 | /* | ||
1456 | if (methods.IsEmpty() && _pgpMethod.IsEmpty() && _hashSize_Defined) | 1583 | if (methods.IsEmpty() && _pgpMethod.IsEmpty() && _hashSize_Defined) |
1457 | AddDefaultMethod(methods, _hashSize); | 1584 | { |
1585 | AddDefaultMethod(methods, | ||
1586 | utf_nameExtenstion.IsEmpty() ? NULL : utf_nameExtenstion.Ptr(), | ||
1587 | _hashSize); | ||
1588 | } | ||
1589 | */ | ||
1458 | 1590 | ||
1459 | RINOK(hb_Glob.SetMethods( | 1591 | if (!methods.IsEmpty()) |
1592 | { | ||
1593 | RINOK(hb_Glob.SetMethods( | ||
1460 | EXTERNAL_CODECS_LOC_VARS | 1594 | EXTERNAL_CODECS_LOC_VARS |
1461 | methods)) | 1595 | methods)) |
1596 | } | ||
1462 | 1597 | ||
1463 | Z7_DECL_CMyComPtr_QI_FROM( | 1598 | Z7_DECL_CMyComPtr_QI_FROM( |
1464 | IArchiveUpdateCallbackFile, | 1599 | IArchiveUpdateCallbackFile, |
@@ -1553,9 +1688,11 @@ Z7_COM7F_IMF(CHandler::Extract(const UInt32 *indices, UInt32 numItems, | |||
1553 | { | 1688 | { |
1554 | hb_Use = &hb_Loc; | 1689 | hb_Use = &hb_Loc; |
1555 | CMethodId id; | 1690 | CMethodId id; |
1556 | if (FindHashMethod(EXTERNAL_CODECS_LOC_VARS hp.Method, id)) | 1691 | AString methodName = hp.Method; |
1692 | Convert_TagName_to_MethodName(methodName); | ||
1693 | if (FindHashMethod(EXTERNAL_CODECS_LOC_VARS methodName, id)) | ||
1557 | { | 1694 | { |
1558 | methods_loc.Add(UString(hp.Method)); | 1695 | methods_loc.Add(UString(methodName)); |
1559 | RINOK(hb_Loc.SetMethods( | 1696 | RINOK(hb_Loc.SetMethods( |
1560 | EXTERNAL_CODECS_LOC_VARS | 1697 | EXTERNAL_CODECS_LOC_VARS |
1561 | methods_loc)) | 1698 | methods_loc)) |
@@ -1565,7 +1702,10 @@ Z7_COM7F_IMF(CHandler::Extract(const UInt32 *indices, UInt32 numItems, | |||
1565 | } | 1702 | } |
1566 | else if (methods.IsEmpty()) | 1703 | else if (methods.IsEmpty()) |
1567 | { | 1704 | { |
1568 | AddDefaultMethod(methods_loc, (unsigned)hp.Hash.Size()); | 1705 | AddDefaultMethod(methods_loc, |
1706 | _method_for_Extraction.IsEmpty() ? NULL : | ||
1707 | _method_for_Extraction.Ptr(), | ||
1708 | (unsigned)hp.Hash.Size()); | ||
1569 | if (!methods_loc.IsEmpty()) | 1709 | if (!methods_loc.IsEmpty()) |
1570 | { | 1710 | { |
1571 | hb_Use = &hb_Loc; | 1711 | hb_Use = &hb_Loc; |
@@ -1613,7 +1753,7 @@ Z7_COM7F_IMF(CHandler::Extract(const UInt32 *indices, UInt32 numItems, | |||
1613 | Int32 opRes = NArchive::NExtract::NOperationResult::kUnsupportedMethod; | 1753 | Int32 opRes = NArchive::NExtract::NOperationResult::kUnsupportedMethod; |
1614 | if (isSupportedMode | 1754 | if (isSupportedMode |
1615 | && res_SetMethods != E_NOTIMPL | 1755 | && res_SetMethods != E_NOTIMPL |
1616 | && hb_Use->Hashers.Size() > 0 | 1756 | && !hb_Use->Hashers.IsEmpty() |
1617 | ) | 1757 | ) |
1618 | { | 1758 | { |
1619 | const CHasherState &hs = hb_Use->Hashers[0]; | 1759 | const CHasherState &hs = hb_Use->Hashers[0]; |
@@ -1766,10 +1906,6 @@ Z7_COM7F_IMF(CHandler::UpdateItems(ISequentialOutStream *outStream, UInt32 numIt | |||
1766 | methods.Add(_methods[k]); | 1906 | methods.Add(_methods[k]); |
1767 | } | 1907 | } |
1768 | } | 1908 | } |
1769 | else if (_crcSize_WasSet) | ||
1770 | { | ||
1771 | AddDefaultMethod(methods, _crcSize); | ||
1772 | } | ||
1773 | else | 1909 | else |
1774 | { | 1910 | { |
1775 | Z7_DECL_CMyComPtr_QI_FROM( | 1911 | Z7_DECL_CMyComPtr_QI_FROM( |
@@ -1781,12 +1917,23 @@ Z7_COM7F_IMF(CHandler::UpdateItems(ISequentialOutStream *outStream, UInt32 numIt | |||
1781 | RINOK(getRootProps->GetRootProp(kpidArcFileName, &prop)) | 1917 | RINOK(getRootProps->GetRootProp(kpidArcFileName, &prop)) |
1782 | if (prop.vt == VT_BSTR) | 1918 | if (prop.vt == VT_BSTR) |
1783 | { | 1919 | { |
1784 | const UString method = GetMethod_from_FileName(prop.bstrVal); | 1920 | AString method; |
1921 | /* const bool isKnownMethod = */ GetMethod_from_FileName(prop.bstrVal, method); | ||
1785 | if (!method.IsEmpty()) | 1922 | if (!method.IsEmpty()) |
1786 | methods.Add(method); | 1923 | { |
1924 | AddDefaultMethod(methods, method, _crcSize_WasSet ? _crcSize : 0); | ||
1925 | if (methods.IsEmpty()) | ||
1926 | return E_NOTIMPL; | ||
1927 | } | ||
1787 | } | 1928 | } |
1788 | } | 1929 | } |
1789 | } | 1930 | } |
1931 | if (methods.IsEmpty() && _crcSize_WasSet) | ||
1932 | { | ||
1933 | AddDefaultMethod(methods, | ||
1934 | NULL, // name | ||
1935 | _crcSize); | ||
1936 | } | ||
1790 | 1937 | ||
1791 | RINOK(hb.SetMethods(EXTERNAL_CODECS_LOC_VARS methods)) | 1938 | RINOK(hb.SetMethods(EXTERNAL_CODECS_LOC_VARS methods)) |
1792 | 1939 | ||
@@ -2030,6 +2177,15 @@ HRESULT CHandler::SetProperty(const wchar_t *nameSpec, const PROPVARIANT &value) | |||
2030 | } | 2177 | } |
2031 | 2178 | ||
2032 | 2179 | ||
2180 | void CHandler::InitProps() | ||
2181 | { | ||
2182 | _supportWindowsBackslash = true; | ||
2183 | _crcSize_WasSet = false; | ||
2184 | _crcSize = 4; | ||
2185 | _methods.Clear(); | ||
2186 | _options.Init_HashOptionsLocal(); | ||
2187 | } | ||
2188 | |||
2033 | Z7_COM7F_IMF(CHandler::SetProperties(const wchar_t * const *names, const PROPVARIANT *values, UInt32 numProps)) | 2189 | Z7_COM7F_IMF(CHandler::SetProperties(const wchar_t * const *names, const PROPVARIANT *values, UInt32 numProps)) |
2034 | { | 2190 | { |
2035 | COM_TRY_BEGIN | 2191 | COM_TRY_BEGIN |
@@ -2076,11 +2232,32 @@ void Codecs_AddHashArcHandler(CCodecs *codecs) | |||
2076 | 2232 | ||
2077 | // ubuntu uses "SHA256SUMS" file | 2233 | // ubuntu uses "SHA256SUMS" file |
2078 | item.AddExts(UString ( | 2234 | item.AddExts(UString ( |
2079 | "sha256 sha512 sha224 sha384 sha1 sha md5" | 2235 | "sha256" |
2080 | // "b2sum" | 2236 | " sha512" |
2081 | " crc32 crc64" | 2237 | " sha384" |
2082 | " asc" | 2238 | " sha224" |
2239 | " sha512-224" | ||
2240 | " sha512-256" | ||
2241 | " sha3-224" | ||
2242 | " sha3-256" | ||
2243 | " sha3-384" | ||
2244 | " sha3-512" | ||
2245 | // " shake128" | ||
2246 | // " shake256" | ||
2247 | " sha1" | ||
2248 | " sha2" | ||
2249 | " sha3" | ||
2250 | " sha" | ||
2251 | " md5" | ||
2252 | " blake2s" | ||
2253 | " blake2b" | ||
2254 | " blake2sp" | ||
2255 | " xxh64" | ||
2256 | " crc32" | ||
2257 | " crc64" | ||
2083 | " cksum" | 2258 | " cksum" |
2259 | " asc" | ||
2260 | // " b2sum" | ||
2084 | ), | 2261 | ), |
2085 | UString()); | 2262 | UString()); |
2086 | 2263 | ||
diff --git a/CPP/7zip/UI/Common/HashCalc.h b/CPP/7zip/UI/Common/HashCalc.h index 1e9dbf4..b8f867f 100644 --- a/CPP/7zip/UI/Common/HashCalc.h +++ b/CPP/7zip/UI/Common/HashCalc.h | |||
@@ -279,32 +279,25 @@ Z7_CLASS_IMP_CHandler_IInArchive_3( | |||
279 | bool _isArc; | 279 | bool _isArc; |
280 | bool _supportWindowsBackslash; | 280 | bool _supportWindowsBackslash; |
281 | bool _crcSize_WasSet; | 281 | bool _crcSize_WasSet; |
282 | UInt64 _phySize; | ||
283 | CObjectVector<CHashPair> HashPairs; | ||
284 | UString _nameExtenstion; | ||
285 | // UString _method_fromName; | ||
286 | AString _pgpMethod; | ||
287 | bool _is_CksumMode; | 282 | bool _is_CksumMode; |
288 | bool _is_PgpMethod; | 283 | bool _is_PgpMethod; |
289 | bool _is_ZeroMode; | 284 | bool _is_ZeroMode; |
290 | bool _are_there_Tags; | 285 | bool _are_there_Tags; |
291 | bool _are_there_Dirs; | 286 | bool _are_there_Dirs; |
287 | bool _is_KnownMethod_in_FileName; | ||
292 | bool _hashSize_Defined; | 288 | bool _hashSize_Defined; |
293 | unsigned _hashSize; | 289 | unsigned _hashSize; |
294 | UInt32 _crcSize; | 290 | UInt32 _crcSize; |
291 | UInt64 _phySize; | ||
292 | CObjectVector<CHashPair> HashPairs; | ||
295 | UStringVector _methods; | 293 | UStringVector _methods; |
294 | AString _method_from_FileName; | ||
295 | AString _pgpMethod; | ||
296 | AString _method_for_Extraction; | ||
296 | CHashOptionsLocal _options; | 297 | CHashOptionsLocal _options; |
297 | 298 | ||
298 | void ClearVars(); | 299 | void ClearVars(); |
299 | 300 | void InitProps(); | |
300 | void InitProps() | ||
301 | { | ||
302 | _supportWindowsBackslash = true; | ||
303 | _crcSize_WasSet = false; | ||
304 | _crcSize = 4; | ||
305 | _methods.Clear(); | ||
306 | _options.Init_HashOptionsLocal(); | ||
307 | } | ||
308 | 301 | ||
309 | bool CanUpdate() const | 302 | bool CanUpdate() const |
310 | { | 303 | { |
diff --git a/CPP/7zip/UI/Common/LoadCodecs.cpp b/CPP/7zip/UI/Common/LoadCodecs.cpp index 6bf53ea..943435a 100644 --- a/CPP/7zip/UI/Common/LoadCodecs.cpp +++ b/CPP/7zip/UI/Common/LoadCodecs.cpp | |||
@@ -170,7 +170,7 @@ void CArcInfoEx::AddExts(const UString &ext, const UString &addExt) | |||
170 | if (i < addExts.Size()) | 170 | if (i < addExts.Size()) |
171 | { | 171 | { |
172 | extInfo.AddExt = addExts[i]; | 172 | extInfo.AddExt = addExts[i]; |
173 | if (extInfo.AddExt == L"*") | 173 | if (extInfo.AddExt.IsEqualTo("*")) |
174 | extInfo.AddExt.Empty(); | 174 | extInfo.AddExt.Empty(); |
175 | } | 175 | } |
176 | Exts.Add(extInfo); | 176 | Exts.Add(extInfo); |
@@ -931,8 +931,8 @@ bool CCodecs::FindFormatForArchiveType(const UString &arcType, CIntVector &forma | |||
931 | const UString name = arcType.Mid(pos, (unsigned)pos2 - pos); | 931 | const UString name = arcType.Mid(pos, (unsigned)pos2 - pos); |
932 | if (name.IsEmpty()) | 932 | if (name.IsEmpty()) |
933 | return false; | 933 | return false; |
934 | int index = FindFormatForArchiveType(name); | 934 | const int index = FindFormatForArchiveType(name); |
935 | if (index < 0 && name != L"*") | 935 | if (index < 0 && !name.IsEqualTo("*")) |
936 | { | 936 | { |
937 | formatIndices.Clear(); | 937 | formatIndices.Clear(); |
938 | return false; | 938 | return false; |
diff --git a/CPP/7zip/UI/Common/TempFiles.cpp b/CPP/7zip/UI/Common/TempFiles.cpp index 2f86838..ad16e36 100644 --- a/CPP/7zip/UI/Common/TempFiles.cpp +++ b/CPP/7zip/UI/Common/TempFiles.cpp | |||
@@ -13,7 +13,8 @@ void CTempFiles::Clear() | |||
13 | { | 13 | { |
14 | while (!Paths.IsEmpty()) | 14 | while (!Paths.IsEmpty()) |
15 | { | 15 | { |
16 | NDir::DeleteFileAlways(Paths.Back()); | 16 | if (NeedDeleteFiles) |
17 | NDir::DeleteFileAlways(Paths.Back()); | ||
17 | Paths.DeleteBack(); | 18 | Paths.DeleteBack(); |
18 | } | 19 | } |
19 | } | 20 | } |
diff --git a/CPP/7zip/UI/Common/TempFiles.h b/CPP/7zip/UI/Common/TempFiles.h index dd4ac20..83c741f 100644 --- a/CPP/7zip/UI/Common/TempFiles.h +++ b/CPP/7zip/UI/Common/TempFiles.h | |||
@@ -10,6 +10,9 @@ class CTempFiles | |||
10 | void Clear(); | 10 | void Clear(); |
11 | public: | 11 | public: |
12 | FStringVector Paths; | 12 | FStringVector Paths; |
13 | bool NeedDeleteFiles; | ||
14 | |||
15 | CTempFiles(): NeedDeleteFiles(true) {} | ||
13 | ~CTempFiles() { Clear(); } | 16 | ~CTempFiles() { Clear(); } |
14 | }; | 17 | }; |
15 | 18 | ||
diff --git a/CPP/7zip/UI/Common/Update.cpp b/CPP/7zip/UI/Common/Update.cpp index ed48605..1c2754e 100644 --- a/CPP/7zip/UI/Common/Update.cpp +++ b/CPP/7zip/UI/Common/Update.cpp | |||
@@ -474,7 +474,7 @@ static HRESULT Compress( | |||
474 | 474 | ||
475 | CArcToDoStat stat2; | 475 | CArcToDoStat stat2; |
476 | 476 | ||
477 | if (options.RenamePairs.Size() != 0) | 477 | if (options.RenameMode || options.RenamePairs.Size() != 0) |
478 | { | 478 | { |
479 | FOR_VECTOR (i, arcItems) | 479 | FOR_VECTOR (i, arcItems) |
480 | { | 480 | { |
@@ -1096,6 +1096,30 @@ typedef Z7_WIN_MAPISENDMAILW FAR *Z7_WIN_LPMAPISENDMAILW; | |||
1096 | #endif // _WIN32 | 1096 | #endif // _WIN32 |
1097 | 1097 | ||
1098 | 1098 | ||
1099 | struct C_CopyFileProgress_to_IUpdateCallbackUI2 Z7_final: | ||
1100 | public ICopyFileProgress | ||
1101 | { | ||
1102 | IUpdateCallbackUI2 *Callback; | ||
1103 | HRESULT CallbackResult; | ||
1104 | // bool Disable_Break; | ||
1105 | |||
1106 | virtual DWORD CopyFileProgress(UInt64 total, UInt64 current) Z7_override | ||
1107 | { | ||
1108 | const HRESULT res = Callback->MoveArc_Progress(total, current); | ||
1109 | CallbackResult = res; | ||
1110 | // if (Disable_Break && res == E_ABORT) res = S_OK; | ||
1111 | return res == S_OK ? PROGRESS_CONTINUE : PROGRESS_CANCEL; | ||
1112 | } | ||
1113 | |||
1114 | C_CopyFileProgress_to_IUpdateCallbackUI2( | ||
1115 | IUpdateCallbackUI2 *callback) : | ||
1116 | Callback(callback), | ||
1117 | CallbackResult(S_OK) | ||
1118 | // , Disable_Break(false) | ||
1119 | {} | ||
1120 | }; | ||
1121 | |||
1122 | |||
1099 | HRESULT UpdateArchive( | 1123 | HRESULT UpdateArchive( |
1100 | CCodecs *codecs, | 1124 | CCodecs *codecs, |
1101 | const CObjectVector<COpenType> &types, | 1125 | const CObjectVector<COpenType> &types, |
@@ -1311,7 +1335,7 @@ HRESULT UpdateArchive( | |||
1311 | return E_NOTIMPL; | 1335 | return E_NOTIMPL; |
1312 | } | 1336 | } |
1313 | 1337 | ||
1314 | bool thereIsInArchive = arcLink.IsOpen; | 1338 | const bool thereIsInArchive = arcLink.IsOpen; |
1315 | if (!thereIsInArchive && renameMode) | 1339 | if (!thereIsInArchive && renameMode) |
1316 | return E_FAIL; | 1340 | return E_FAIL; |
1317 | 1341 | ||
@@ -1588,7 +1612,14 @@ HRESULT UpdateArchive( | |||
1588 | multiStreams.DisableDeletion(); | 1612 | multiStreams.DisableDeletion(); |
1589 | RINOK(multiStreams.Destruct()) | 1613 | RINOK(multiStreams.Destruct()) |
1590 | 1614 | ||
1591 | tempFiles.Paths.Clear(); | 1615 | // here we disable deleting of temp archives. |
1616 | // note: archive moving can fail, or it can be interrupted, | ||
1617 | // if we move new temp update from another volume. | ||
1618 | // And we still want to keep temp archive in that case, | ||
1619 | // because we will have deleted original archive. | ||
1620 | tempFiles.NeedDeleteFiles = false; | ||
1621 | // tempFiles.Paths.Clear(); | ||
1622 | |||
1592 | if (createTempFile) | 1623 | if (createTempFile) |
1593 | { | 1624 | { |
1594 | try | 1625 | try |
@@ -1603,16 +1634,29 @@ HRESULT UpdateArchive( | |||
1603 | if (!DeleteFileAlways(us2fs(arcPath))) | 1634 | if (!DeleteFileAlways(us2fs(arcPath))) |
1604 | return errorInfo.SetFromLastError("cannot delete the file", us2fs(arcPath)); | 1635 | return errorInfo.SetFromLastError("cannot delete the file", us2fs(arcPath)); |
1605 | } | 1636 | } |
1606 | 1637 | ||
1607 | if (!MyMoveFile(tempPath, us2fs(arcPath))) | 1638 | UInt64 totalArcSize = 0; |
1639 | { | ||
1640 | NFind::CFileInfo fi; | ||
1641 | if (fi.Find(tempPath)) | ||
1642 | totalArcSize = fi.Size; | ||
1643 | } | ||
1644 | RINOK(callback->MoveArc_Start(fs2us(tempPath), arcPath, | ||
1645 | totalArcSize, BoolToInt(thereIsInArchive))) | ||
1646 | |||
1647 | C_CopyFileProgress_to_IUpdateCallbackUI2 prox(callback); | ||
1648 | // if we update archive, we have removed original archive. | ||
1649 | // So if we break archive moving, we will have only temporary archive. | ||
1650 | // We can disable breaking here: | ||
1651 | // prox.Disable_Break = thereIsInArchive; | ||
1652 | |||
1653 | if (!MyMoveFile_with_Progress(tempPath, us2fs(arcPath), &prox)) | ||
1608 | { | 1654 | { |
1609 | errorInfo.SystemError = ::GetLastError(); | 1655 | errorInfo.SystemError = ::GetLastError(); |
1610 | errorInfo.Message = "cannot move the file"; | 1656 | errorInfo.Message = "cannot move the file"; |
1611 | if (errorInfo.SystemError == ERROR_INVALID_PARAMETER) | 1657 | if (errorInfo.SystemError == ERROR_INVALID_PARAMETER) |
1612 | { | 1658 | { |
1613 | NFind::CFileInfo fi; | 1659 | if (totalArcSize > (UInt32)(Int32)-1) |
1614 | if (fi.Find(tempPath) && | ||
1615 | fi.Size > (UInt32)(Int32)-1) | ||
1616 | { | 1660 | { |
1617 | // bool isFsDetected = false; | 1661 | // bool isFsDetected = false; |
1618 | // if (NSystem::Is_File_LimitedBy_4GB(us2fs(arcPath), isFsDetected) || !isFsDetected) | 1662 | // if (NSystem::Is_File_LimitedBy_4GB(us2fs(arcPath), isFsDetected) || !isFsDetected) |
@@ -1622,10 +1666,20 @@ HRESULT UpdateArchive( | |||
1622 | } | 1666 | } |
1623 | } | 1667 | } |
1624 | } | 1668 | } |
1669 | // if there was no input archive, and we have operation breaking. | ||
1670 | // then we can remove temporary archive, because we still have original uncompressed files. | ||
1671 | if (!thereIsInArchive | ||
1672 | && prox.CallbackResult == E_ABORT) | ||
1673 | tempFiles.NeedDeleteFiles = true; | ||
1625 | errorInfo.FileNames.Add(tempPath); | 1674 | errorInfo.FileNames.Add(tempPath); |
1626 | errorInfo.FileNames.Add(us2fs(arcPath)); | 1675 | errorInfo.FileNames.Add(us2fs(arcPath)); |
1676 | RINOK(prox.CallbackResult) | ||
1627 | return errorInfo.Get_HRESULT_Error(); | 1677 | return errorInfo.Get_HRESULT_Error(); |
1628 | } | 1678 | } |
1679 | |||
1680 | // MoveArc_Finish() can return delayed user break (E_ABORT) status, | ||
1681 | // if callback callee ignored interruption to finish archive creation operation. | ||
1682 | RINOK(callback->MoveArc_Finish()) | ||
1629 | 1683 | ||
1630 | /* | 1684 | /* |
1631 | if (attrib != INVALID_FILE_ATTRIBUTES && (attrib & FILE_ATTRIBUTE_READONLY)) | 1685 | if (attrib != INVALID_FILE_ATTRIBUTES && (attrib & FILE_ATTRIBUTE_READONLY)) |
@@ -1866,7 +1920,7 @@ Z7_DIAGNOSTIC_IGNORE_CAST_FUNCTION | |||
1866 | if (NFind::DoesDirExist(phyPath)) | 1920 | if (NFind::DoesDirExist(phyPath)) |
1867 | { | 1921 | { |
1868 | RINOK(callback->DeletingAfterArchiving(phyPath, true)) | 1922 | RINOK(callback->DeletingAfterArchiving(phyPath, true)) |
1869 | RemoveDir(phyPath); | 1923 | RemoveDirAlways_if_Empty(phyPath); |
1870 | } | 1924 | } |
1871 | } | 1925 | } |
1872 | 1926 | ||
diff --git a/CPP/7zip/UI/Common/Update.h b/CPP/7zip/UI/Common/Update.h index a9459ff..ae141e5 100644 --- a/CPP/7zip/UI/Common/Update.h +++ b/CPP/7zip/UI/Common/Update.h | |||
@@ -12,8 +12,6 @@ | |||
12 | #include "UpdateAction.h" | 12 | #include "UpdateAction.h" |
13 | #include "UpdateCallback.h" | 13 | #include "UpdateCallback.h" |
14 | 14 | ||
15 | #include "DirItem.h" | ||
16 | |||
17 | enum EArcNameMode | 15 | enum EArcNameMode |
18 | { | 16 | { |
19 | k_ArcNameMode_Smart, | 17 | k_ArcNameMode_Smart, |
@@ -96,6 +94,7 @@ struct CUpdateOptions | |||
96 | 94 | ||
97 | bool DeleteAfterCompressing; | 95 | bool DeleteAfterCompressing; |
98 | bool SetArcMTime; | 96 | bool SetArcMTime; |
97 | bool RenameMode; | ||
99 | 98 | ||
100 | CBoolPair NtSecurity; | 99 | CBoolPair NtSecurity; |
101 | CBoolPair AltStreams; | 100 | CBoolPair AltStreams; |
@@ -141,6 +140,7 @@ struct CUpdateOptions | |||
141 | 140 | ||
142 | DeleteAfterCompressing(false), | 141 | DeleteAfterCompressing(false), |
143 | SetArcMTime(false), | 142 | SetArcMTime(false), |
143 | RenameMode(false), | ||
144 | 144 | ||
145 | ArcNameMode(k_ArcNameMode_Smart), | 145 | ArcNameMode(k_ArcNameMode_Smart), |
146 | PathMode(NWildcard::k_RelatPath) | 146 | PathMode(NWildcard::k_RelatPath) |
@@ -195,6 +195,9 @@ Z7_PURE_INTERFACES_BEGIN | |||
195 | virtual HRESULT FinishArchive(const CFinishArchiveStat &st) x \ | 195 | virtual HRESULT FinishArchive(const CFinishArchiveStat &st) x \ |
196 | virtual HRESULT DeletingAfterArchiving(const FString &path, bool isDir) x \ | 196 | virtual HRESULT DeletingAfterArchiving(const FString &path, bool isDir) x \ |
197 | virtual HRESULT FinishDeletingAfterArchiving() x \ | 197 | virtual HRESULT FinishDeletingAfterArchiving() x \ |
198 | virtual HRESULT MoveArc_Start(const wchar_t *srcTempPath, const wchar_t *destFinalPath, UInt64 size, Int32 updateMode) x \ | ||
199 | virtual HRESULT MoveArc_Progress(UInt64 total, UInt64 current) x \ | ||
200 | virtual HRESULT MoveArc_Finish() x \ | ||
198 | 201 | ||
199 | DECLARE_INTERFACE(IUpdateCallbackUI2): | 202 | DECLARE_INTERFACE(IUpdateCallbackUI2): |
200 | public IUpdateCallbackUI, | 203 | public IUpdateCallbackUI, |
diff --git a/CPP/7zip/UI/Common/UpdateCallback.cpp b/CPP/7zip/UI/Common/UpdateCallback.cpp index d3ee639..e2f1866 100644 --- a/CPP/7zip/UI/Common/UpdateCallback.cpp +++ b/CPP/7zip/UI/Common/UpdateCallback.cpp | |||
@@ -32,6 +32,7 @@ | |||
32 | #include "../../../Windows/PropVariant.h" | 32 | #include "../../../Windows/PropVariant.h" |
33 | 33 | ||
34 | #include "../../Common/StreamObjects.h" | 34 | #include "../../Common/StreamObjects.h" |
35 | #include "../../Archive/Common/ItemNameUtils.h" | ||
35 | 36 | ||
36 | #include "UpdateCallback.h" | 37 | #include "UpdateCallback.h" |
37 | 38 | ||
@@ -306,7 +307,7 @@ Z7_COM7F_IMF(CArchiveUpdateCallback::GetRawProp(UInt32 index, PROPID propID, con | |||
306 | 307 | ||
307 | #if defined(_WIN32) && !defined(UNDER_CE) | 308 | #if defined(_WIN32) && !defined(UNDER_CE) |
308 | 309 | ||
309 | static UString GetRelativePath(const UString &to, const UString &from) | 310 | static UString GetRelativePath(const UString &to, const UString &from, bool isWSL) |
310 | { | 311 | { |
311 | UStringVector partsTo, partsFrom; | 312 | UStringVector partsTo, partsFrom; |
312 | SplitPathToParts(to, partsTo); | 313 | SplitPathToParts(to, partsTo); |
@@ -324,11 +325,12 @@ static UString GetRelativePath(const UString &to, const UString &from) | |||
324 | 325 | ||
325 | if (i == 0) | 326 | if (i == 0) |
326 | { | 327 | { |
327 | #ifdef _WIN32 | 328 | #ifdef _WIN32 |
328 | if (NName::IsDrivePath(to) || | 329 | if (isWSL || |
329 | NName::IsDrivePath(from)) | 330 | (NName::IsDrivePath(to) || |
331 | NName::IsDrivePath(from))) | ||
330 | return to; | 332 | return to; |
331 | #endif | 333 | #endif |
332 | } | 334 | } |
333 | 335 | ||
334 | UString s; | 336 | UString s; |
@@ -373,54 +375,87 @@ Z7_COM7F_IMF(CArchiveUpdateCallback::GetProperty(UInt32 index, PROPID propID, PR | |||
373 | return S_OK; | 375 | return S_OK; |
374 | } | 376 | } |
375 | 377 | ||
376 | #if !defined(UNDER_CE) | 378 | #if !defined(UNDER_CE) |
377 | |||
378 | if (up.DirIndex >= 0) | 379 | if (up.DirIndex >= 0) |
379 | { | 380 | { |
380 | const CDirItem &di = DirItems->Items[(unsigned)up.DirIndex]; | 381 | const CDirItem &di = DirItems->Items[(unsigned)up.DirIndex]; |
381 | 382 | if (di.ReparseData.Size()) | |
382 | #ifdef _WIN32 | ||
383 | // if (di.IsDir()) | ||
384 | { | 383 | { |
384 | #ifdef _WIN32 | ||
385 | CReparseAttr attr; | 385 | CReparseAttr attr; |
386 | if (attr.Parse(di.ReparseData, di.ReparseData.Size())) | 386 | if (attr.Parse(di.ReparseData, di.ReparseData.Size())) |
387 | { | 387 | { |
388 | const UString simpleName = attr.GetPath(); | 388 | UString path = attr.GetPath(); |
389 | if (!attr.IsSymLink_WSL() && attr.IsRelative_Win()) | 389 | if (!path.IsEmpty()) |
390 | prop = simpleName; | ||
391 | else | ||
392 | { | 390 | { |
393 | const FString phyPath = DirItems->GetPhyPath((unsigned)up.DirIndex); | 391 | bool isWSL = attr.IsSymLink_WSL(); |
394 | FString fullPath; | 392 | if (isWSL) |
395 | if (NDir::MyGetFullPathName(phyPath, fullPath)) | 393 | NArchive::NItemName::ReplaceToWinSlashes(path, true); // useBackslashReplacement |
394 | // it's expected that (path) now uses windows slashes. | ||
395 | // CReparseAttr::IsRelative_Win() returns true if FLAG_RELATIVE is set | ||
396 | // CReparseAttr::IsRelative_Win() returns true for "\dir1\path" | ||
397 | // but we want to store real relative paths without "\" root prefix. | ||
398 | // so we parse path instead of IsRelative_Win() calling. | ||
399 | if (// attr.IsRelative_Win() || | ||
400 | (isWSL ? | ||
401 | IS_PATH_SEPAR(path[0]) : | ||
402 | NName::IsAbsolutePath(path))) | ||
396 | { | 403 | { |
397 | prop = GetRelativePath(simpleName, fs2us(fullPath)); | 404 | // (path) is abolute path or relative to root: "\path" |
405 | // we try to convert (path) to relative path for writing to archive. | ||
406 | const FString phyPath = DirItems->GetPhyPath((unsigned)up.DirIndex); | ||
407 | FString fullPath; | ||
408 | if (NDir::MyGetFullPathName(phyPath, fullPath)) | ||
409 | { | ||
410 | if (IS_PATH_SEPAR(path[0]) && | ||
411 | !IS_PATH_SEPAR(path[1])) | ||
412 | { | ||
413 | // path is relative to root of (fullPath): "\path" | ||
414 | const unsigned prefixSize = NName::GetRootPrefixSize(fullPath); | ||
415 | if (prefixSize) | ||
416 | { | ||
417 | path.DeleteFrontal(1); | ||
418 | path.Insert(0, fs2us(fullPath.Left(prefixSize))); | ||
419 | // we have changed "\" prefix to drive prefix "c:\" in (path). | ||
420 | // (path) is Windows path now. | ||
421 | isWSL = false; | ||
422 | } | ||
423 | } | ||
424 | } | ||
425 | path = GetRelativePath(path, fs2us(fullPath), isWSL); | ||
398 | } | 426 | } |
427 | #if WCHAR_PATH_SEPARATOR != L'/' | ||
428 | // 7-Zip's TAR handler in Windows replaces windows slashes to linux slashes. | ||
429 | // so we can return any slashes to TAR handler. | ||
430 | // or we can convert to linux slashes here, | ||
431 | // because input IInArchive handler uses linux slashes for kpidSymLink. | ||
432 | // path.Replace(WCHAR_PATH_SEPARATOR, L'/'); | ||
433 | #endif | ||
434 | if (!path.IsEmpty()) | ||
435 | prop = path; | ||
399 | } | 436 | } |
400 | prop.Detach(value); | ||
401 | return S_OK; | ||
402 | } | 437 | } |
403 | } | 438 | #else // ! _WIN32 |
404 | |||
405 | #else // _WIN32 | ||
406 | |||
407 | if (di.ReparseData.Size() != 0) | ||
408 | { | ||
409 | AString utf; | 439 | AString utf; |
410 | utf.SetFrom_CalcLen((const char *)(const Byte *)di.ReparseData, (unsigned)di.ReparseData.Size()); | 440 | utf.SetFrom_CalcLen((const char *)(const Byte *)di.ReparseData, (unsigned)di.ReparseData.Size()); |
411 | 441 | #if 0 // 0 - for debug | |
442 | // it's expected that link data uses system codepage. | ||
443 | // fs2us() ignores conversion errors. But we want correct path | ||
444 | UString us (fs2us(utf)); | ||
445 | #else | ||
412 | UString us; | 446 | UString us; |
413 | if (ConvertUTF8ToUnicode(utf, us)) | 447 | if (ConvertUTF8ToUnicode(utf, us)) |
448 | #endif | ||
414 | { | 449 | { |
415 | prop = us; | 450 | if (!us.IsEmpty()) |
416 | prop.Detach(value); | 451 | prop = us; |
417 | return S_OK; | ||
418 | } | 452 | } |
453 | #endif // ! _WIN32 | ||
419 | } | 454 | } |
420 | 455 | prop.Detach(value); | |
421 | #endif // _WIN32 | 456 | return S_OK; |
422 | } | 457 | } |
423 | #endif // !defined(UNDER_CE) | 458 | #endif // !defined(UNDER_CE) |
424 | } | 459 | } |
425 | else if (propID == kpidHardLink) | 460 | else if (propID == kpidHardLink) |
426 | { | 461 | { |
@@ -428,7 +463,12 @@ Z7_COM7F_IMF(CArchiveUpdateCallback::GetProperty(UInt32 index, PROPID propID, PR | |||
428 | { | 463 | { |
429 | const CKeyKeyValPair &pair = _map[_hardIndex_To]; | 464 | const CKeyKeyValPair &pair = _map[_hardIndex_To]; |
430 | const CUpdatePair2 &up2 = (*UpdatePairs)[pair.Value]; | 465 | const CUpdatePair2 &up2 = (*UpdatePairs)[pair.Value]; |
431 | prop = DirItems->GetLogPath((unsigned)up2.DirIndex); | 466 | const UString path = DirItems->GetLogPath((unsigned)up2.DirIndex); |
467 | #if WCHAR_PATH_SEPARATOR != L'/' | ||
468 | // 7-Zip's TAR handler in Windows replaces windows slashes to linux slashes. | ||
469 | // path.Replace(WCHAR_PATH_SEPARATOR, L'/'); | ||
470 | #endif | ||
471 | prop = path; | ||
432 | prop.Detach(value); | 472 | prop.Detach(value); |
433 | return S_OK; | 473 | return S_OK; |
434 | } | 474 | } |
@@ -438,7 +478,7 @@ Z7_COM7F_IMF(CArchiveUpdateCallback::GetProperty(UInt32 index, PROPID propID, PR | |||
438 | return S_OK; | 478 | return S_OK; |
439 | } | 479 | } |
440 | } | 480 | } |
441 | } | 481 | } // if (up.NewData) |
442 | 482 | ||
443 | if (up.IsAnti | 483 | if (up.IsAnti |
444 | && propID != kpidIsDir | 484 | && propID != kpidIsDir |
diff --git a/CPP/7zip/UI/Common/WorkDir.cpp b/CPP/7zip/UI/Common/WorkDir.cpp index cfec635..a492967 100644 --- a/CPP/7zip/UI/Common/WorkDir.cpp +++ b/CPP/7zip/UI/Common/WorkDir.cpp | |||
@@ -63,24 +63,22 @@ HRESULT CWorkDirTempFile::CreateTempFile(const FString &originalPath) | |||
63 | NWorkDir::CInfo workDirInfo; | 63 | NWorkDir::CInfo workDirInfo; |
64 | workDirInfo.Load(); | 64 | workDirInfo.Load(); |
65 | FString namePart; | 65 | FString namePart; |
66 | const FString workDir = GetWorkDir(workDirInfo, originalPath, namePart); | 66 | FString path = GetWorkDir(workDirInfo, originalPath, namePart); |
67 | CreateComplexDir(workDir); | 67 | CreateComplexDir(path); |
68 | path += namePart; | ||
68 | _outStreamSpec = new COutFileStream; | 69 | _outStreamSpec = new COutFileStream; |
69 | OutStream = _outStreamSpec; | 70 | OutStream = _outStreamSpec; |
70 | if (!_tempFile.Create(workDir + namePart, &_outStreamSpec->File)) | 71 | if (!_tempFile.Create(path, &_outStreamSpec->File)) |
71 | { | ||
72 | return GetLastError_noZero_HRESULT(); | 72 | return GetLastError_noZero_HRESULT(); |
73 | } | ||
74 | _originalPath = originalPath; | 73 | _originalPath = originalPath; |
75 | return S_OK; | 74 | return S_OK; |
76 | } | 75 | } |
77 | 76 | ||
78 | HRESULT CWorkDirTempFile::MoveToOriginal(bool deleteOriginal) | 77 | HRESULT CWorkDirTempFile::MoveToOriginal(bool deleteOriginal, |
78 | NWindows::NFile::NDir::ICopyFileProgress *progress) | ||
79 | { | 79 | { |
80 | OutStream.Release(); | 80 | OutStream.Release(); |
81 | if (!_tempFile.MoveTo(_originalPath, deleteOriginal)) | 81 | if (!_tempFile.MoveTo(_originalPath, deleteOriginal, progress)) |
82 | { | ||
83 | return GetLastError_noZero_HRESULT(); | 82 | return GetLastError_noZero_HRESULT(); |
84 | } | ||
85 | return S_OK; | 83 | return S_OK; |
86 | } | 84 | } |
diff --git a/CPP/7zip/UI/Common/WorkDir.h b/CPP/7zip/UI/Common/WorkDir.h index d32ab9d..fed8c4a 100644 --- a/CPP/7zip/UI/Common/WorkDir.h +++ b/CPP/7zip/UI/Common/WorkDir.h | |||
@@ -11,7 +11,7 @@ | |||
11 | 11 | ||
12 | FString GetWorkDir(const NWorkDir::CInfo &workDirInfo, const FString &path, FString &fileName); | 12 | FString GetWorkDir(const NWorkDir::CInfo &workDirInfo, const FString &path, FString &fileName); |
13 | 13 | ||
14 | class CWorkDirTempFile | 14 | class CWorkDirTempFile MY_UNCOPYABLE |
15 | { | 15 | { |
16 | FString _originalPath; | 16 | FString _originalPath; |
17 | NWindows::NFile::NDir::CTempFile _tempFile; | 17 | NWindows::NFile::NDir::CTempFile _tempFile; |
@@ -19,8 +19,12 @@ class CWorkDirTempFile | |||
19 | public: | 19 | public: |
20 | CMyComPtr<IOutStream> OutStream; | 20 | CMyComPtr<IOutStream> OutStream; |
21 | 21 | ||
22 | const FString &Get_OriginalFilePath() const { return _originalPath; } | ||
23 | const FString &Get_TempFilePath() const { return _tempFile.GetPath(); } | ||
24 | |||
22 | HRESULT CreateTempFile(const FString &originalPath); | 25 | HRESULT CreateTempFile(const FString &originalPath); |
23 | HRESULT MoveToOriginal(bool deleteOriginal); | 26 | HRESULT MoveToOriginal(bool deleteOriginal, |
27 | NWindows::NFile::NDir::ICopyFileProgress *progress = NULL); | ||
24 | }; | 28 | }; |
25 | 29 | ||
26 | #endif | 30 | #endif |
diff --git a/CPP/7zip/UI/Common/ZipRegistry.cpp b/CPP/7zip/UI/Common/ZipRegistry.cpp index 73c56cf..936b888 100644 --- a/CPP/7zip/UI/Common/ZipRegistry.cpp +++ b/CPP/7zip/UI/Common/ZipRegistry.cpp | |||
@@ -45,8 +45,8 @@ static void Key_Set_UInt32(CKey &key, LPCTSTR name, UInt32 value) | |||
45 | 45 | ||
46 | static void Key_Get_UInt32(CKey &key, LPCTSTR name, UInt32 &value) | 46 | static void Key_Get_UInt32(CKey &key, LPCTSTR name, UInt32 &value) |
47 | { | 47 | { |
48 | if (key.QueryValue(name, value) != ERROR_SUCCESS) | 48 | value = (UInt32)(Int32)-1; |
49 | value = (UInt32)(Int32)-1; | 49 | key.GetValue_UInt32_IfOk(name, value); |
50 | } | 50 | } |
51 | 51 | ||
52 | 52 | ||
@@ -59,7 +59,7 @@ static void Key_Set_BoolPair(CKey &key, LPCTSTR name, const CBoolPair &b) | |||
59 | static void Key_Set_bool_if_Changed(CKey &key, LPCTSTR name, bool val) | 59 | static void Key_Set_bool_if_Changed(CKey &key, LPCTSTR name, bool val) |
60 | { | 60 | { |
61 | bool oldVal = false; | 61 | bool oldVal = false; |
62 | if (key.GetValue_IfOk(name, oldVal) == ERROR_SUCCESS) | 62 | if (key.GetValue_bool_IfOk(name, oldVal) == ERROR_SUCCESS) |
63 | if (val == oldVal) | 63 | if (val == oldVal) |
64 | return; | 64 | return; |
65 | key.SetValue(name, val); | 65 | key.SetValue(name, val); |
@@ -76,13 +76,13 @@ static void Key_Set_BoolPair_Delete_IfNotDef(CKey &key, LPCTSTR name, const CBoo | |||
76 | static void Key_Get_BoolPair(CKey &key, LPCTSTR name, CBoolPair &b) | 76 | static void Key_Get_BoolPair(CKey &key, LPCTSTR name, CBoolPair &b) |
77 | { | 77 | { |
78 | b.Val = false; | 78 | b.Val = false; |
79 | b.Def = (key.GetValue_IfOk(name, b.Val) == ERROR_SUCCESS); | 79 | b.Def = (key.GetValue_bool_IfOk(name, b.Val) == ERROR_SUCCESS); |
80 | } | 80 | } |
81 | 81 | ||
82 | static void Key_Get_BoolPair_true(CKey &key, LPCTSTR name, CBoolPair &b) | 82 | static void Key_Get_BoolPair_true(CKey &key, LPCTSTR name, CBoolPair &b) |
83 | { | 83 | { |
84 | b.Val = true; | 84 | b.Val = true; |
85 | b.Def = (key.GetValue_IfOk(name, b.Val) == ERROR_SUCCESS); | 85 | b.Def = (key.GetValue_bool_IfOk(name, b.Val) == ERROR_SUCCESS); |
86 | } | 86 | } |
87 | 87 | ||
88 | namespace NExtract | 88 | namespace NExtract |
@@ -155,12 +155,12 @@ void CInfo::Load() | |||
155 | 155 | ||
156 | key.GetValue_Strings(kPathHistory, Paths); | 156 | key.GetValue_Strings(kPathHistory, Paths); |
157 | UInt32 v; | 157 | UInt32 v; |
158 | if (key.QueryValue(kExtractMode, v) == ERROR_SUCCESS && v <= NPathMode::kAbsPaths) | 158 | if (key.GetValue_UInt32_IfOk(kExtractMode, v) == ERROR_SUCCESS && v <= NPathMode::kAbsPaths) |
159 | { | 159 | { |
160 | PathMode = (NPathMode::EEnum)v; | 160 | PathMode = (NPathMode::EEnum)v; |
161 | PathMode_Force = true; | 161 | PathMode_Force = true; |
162 | } | 162 | } |
163 | if (key.QueryValue(kOverwriteMode, v) == ERROR_SUCCESS && v <= NOverwriteMode::kRenameExisting) | 163 | if (key.GetValue_UInt32_IfOk(kOverwriteMode, v) == ERROR_SUCCESS && v <= NOverwriteMode::kRenameExisting) |
164 | { | 164 | { |
165 | OverwriteMode = (NOverwriteMode::EEnum)v; | 165 | OverwriteMode = (NOverwriteMode::EEnum)v; |
166 | OverwriteMode_Force = true; | 166 | OverwriteMode_Force = true; |
@@ -181,7 +181,7 @@ bool Read_ShowPassword() | |||
181 | bool showPassword = false; | 181 | bool showPassword = false; |
182 | if (OpenMainKey(key, kKeyName) != ERROR_SUCCESS) | 182 | if (OpenMainKey(key, kKeyName) != ERROR_SUCCESS) |
183 | return showPassword; | 183 | return showPassword; |
184 | key.GetValue_IfOk(kShowPassword, showPassword); | 184 | key.GetValue_bool_IfOk(kShowPassword, showPassword); |
185 | return showPassword; | 185 | return showPassword; |
186 | } | 186 | } |
187 | 187 | ||
@@ -189,13 +189,10 @@ UInt32 Read_LimitGB() | |||
189 | { | 189 | { |
190 | CS_LOCK | 190 | CS_LOCK |
191 | CKey key; | 191 | CKey key; |
192 | UInt32 v = (UInt32)(Int32)-1; | ||
192 | if (OpenMainKey(key, kKeyName) == ERROR_SUCCESS) | 193 | if (OpenMainKey(key, kKeyName) == ERROR_SUCCESS) |
193 | { | 194 | key.GetValue_UInt32_IfOk(kMemLimit, v); |
194 | UInt32 v; | 195 | return v; |
195 | if (key.QueryValue(kMemLimit, v) == ERROR_SUCCESS) | ||
196 | return v; | ||
197 | } | ||
198 | return (UInt32)(Int32)-1; | ||
199 | } | 196 | } |
200 | 197 | ||
201 | } | 198 | } |
@@ -371,9 +368,9 @@ void CInfo::Load() | |||
371 | UString a; | 368 | UString a; |
372 | if (key.QueryValue(kArchiver, a) == ERROR_SUCCESS) | 369 | if (key.QueryValue(kArchiver, a) == ERROR_SUCCESS) |
373 | ArcType = a; | 370 | ArcType = a; |
374 | key.GetValue_IfOk(kLevel, Level); | 371 | key.GetValue_UInt32_IfOk(kLevel, Level); |
375 | key.GetValue_IfOk(kShowPassword, ShowPassword); | 372 | key.GetValue_bool_IfOk(kShowPassword, ShowPassword); |
376 | key.GetValue_IfOk(kEncryptHeaders, EncryptHeaders); | 373 | key.GetValue_bool_IfOk(kEncryptHeaders, EncryptHeaders); |
377 | } | 374 | } |
378 | 375 | ||
379 | 376 | ||
@@ -517,7 +514,7 @@ void CInfo::Load() | |||
517 | return; | 514 | return; |
518 | 515 | ||
519 | UInt32 dirType; | 516 | UInt32 dirType; |
520 | if (key.QueryValue(kWorkDirType, dirType) != ERROR_SUCCESS) | 517 | if (key.GetValue_UInt32_IfOk(kWorkDirType, dirType) != ERROR_SUCCESS) |
521 | return; | 518 | return; |
522 | switch (dirType) | 519 | switch (dirType) |
523 | { | 520 | { |
@@ -535,7 +532,7 @@ void CInfo::Load() | |||
535 | if (Mode == NMode::kSpecified) | 532 | if (Mode == NMode::kSpecified) |
536 | Mode = NMode::kSystem; | 533 | Mode = NMode::kSystem; |
537 | } | 534 | } |
538 | key.GetValue_IfOk(kTempRemovableOnly, ForRemovableOnly); | 535 | key.GetValue_bool_IfOk(kTempRemovableOnly, ForRemovableOnly); |
539 | } | 536 | } |
540 | 537 | ||
541 | } | 538 | } |
@@ -598,5 +595,5 @@ void CContextMenuInfo::Load() | |||
598 | 595 | ||
599 | Key_Get_UInt32(key, kWriteZoneId, WriteZone); | 596 | Key_Get_UInt32(key, kWriteZoneId, WriteZone); |
600 | 597 | ||
601 | Flags_Def = (key.GetValue_IfOk(kContextMenu, Flags) == ERROR_SUCCESS); | 598 | Flags_Def = (key.GetValue_UInt32_IfOk(kContextMenu, Flags) == ERROR_SUCCESS); |
602 | } | 599 | } |