summaryrefslogtreecommitdiffstats
path: root/src/libs/7zip/unix/CPP/7zip/UI
diff options
context:
space:
mode:
Diffstat (limited to 'src/libs/7zip/unix/CPP/7zip/UI')
-rw-r--r--src/libs/7zip/unix/CPP/7zip/UI/Common/ArchiveCommandLine.cpp1216
-rw-r--r--src/libs/7zip/unix/CPP/7zip/UI/Common/ArchiveCommandLine.h79
-rw-r--r--src/libs/7zip/unix/CPP/7zip/UI/Common/ArchiveExtractCallback.cpp999
-rw-r--r--src/libs/7zip/unix/CPP/7zip/UI/Common/ArchiveExtractCallback.h208
-rw-r--r--src/libs/7zip/unix/CPP/7zip/UI/Common/ArchiveName.cpp54
-rw-r--r--src/libs/7zip/unix/CPP/7zip/UI/Common/ArchiveName.h10
-rw-r--r--src/libs/7zip/unix/CPP/7zip/UI/Common/ArchiveOpenCallback.cpp46
-rw-r--r--src/libs/7zip/unix/CPP/7zip/UI/Common/ArchiveOpenCallback.h38
-rw-r--r--src/libs/7zip/unix/CPP/7zip/UI/Common/Bench.cpp1028
-rw-r--r--src/libs/7zip/unix/CPP/7zip/UI/Common/Bench.h42
-rw-r--r--src/libs/7zip/unix/CPP/7zip/UI/Common/Common.pri43
-rw-r--r--src/libs/7zip/unix/CPP/7zip/UI/Common/DefaultName.cpp6
-rw-r--r--src/libs/7zip/unix/CPP/7zip/UI/Common/DefaultName.h6
-rw-r--r--src/libs/7zip/unix/CPP/7zip/UI/Common/DirItem.h91
-rw-r--r--src/libs/7zip/unix/CPP/7zip/UI/Common/EnumDirItems.cpp678
-rw-r--r--src/libs/7zip/unix/CPP/7zip/UI/Common/EnumDirItems.h18
-rw-r--r--src/libs/7zip/unix/CPP/7zip/UI/Common/ExitCode.h27
-rw-r--r--src/libs/7zip/unix/CPP/7zip/UI/Common/Extract.cpp370
-rw-r--r--src/libs/7zip/unix/CPP/7zip/UI/Common/Extract.h54
-rw-r--r--src/libs/7zip/unix/CPP/7zip/UI/Common/ExtractMode.h42
-rw-r--r--src/libs/7zip/unix/CPP/7zip/UI/Common/ExtractingFilePath.cpp114
-rw-r--r--src/libs/7zip/unix/CPP/7zip/UI/Common/ExtractingFilePath.h12
-rw-r--r--src/libs/7zip/unix/CPP/7zip/UI/Common/HashCalc.cpp361
-rw-r--r--src/libs/7zip/unix/CPP/7zip/UI/Common/HashCalc.h107
-rw-r--r--src/libs/7zip/unix/CPP/7zip/UI/Common/IFileExtractCallback.h32
-rw-r--r--src/libs/7zip/unix/CPP/7zip/UI/Common/LoadCodecs.cpp796
-rw-r--r--src/libs/7zip/unix/CPP/7zip/UI/Common/LoadCodecs.h190
-rw-r--r--src/libs/7zip/unix/CPP/7zip/UI/Common/OpenArchive.cpp3170
-rw-r--r--src/libs/7zip/unix/CPP/7zip/UI/Common/OpenArchive.h351
-rw-r--r--src/libs/7zip/unix/CPP/7zip/UI/Common/PropIDUtils.cpp549
-rw-r--r--src/libs/7zip/unix/CPP/7zip/UI/Common/PropIDUtils.h13
-rw-r--r--src/libs/7zip/unix/CPP/7zip/UI/Common/Property.h6
-rw-r--r--src/libs/7zip/unix/CPP/7zip/UI/Common/SetProperties.cpp31
-rw-r--r--src/libs/7zip/unix/CPP/7zip/UI/Common/SortUtils.cpp17
-rw-r--r--src/libs/7zip/unix/CPP/7zip/UI/Common/SortUtils.h8
-rw-r--r--src/libs/7zip/unix/CPP/7zip/UI/Common/TempFiles.cpp9
-rw-r--r--src/libs/7zip/unix/CPP/7zip/UI/Common/TempFiles.h8
-rw-r--r--src/libs/7zip/unix/CPP/7zip/UI/Common/Update.cpp1124
-rw-r--r--src/libs/7zip/unix/CPP/7zip/UI/Common/Update.h145
-rw-r--r--src/libs/7zip/unix/CPP/7zip/UI/Common/UpdateAction.cpp10
-rw-r--r--src/libs/7zip/unix/CPP/7zip/UI/Common/UpdateAction.h29
-rw-r--r--src/libs/7zip/unix/CPP/7zip/UI/Common/UpdateCallback.cpp455
-rw-r--r--src/libs/7zip/unix/CPP/7zip/UI/Common/UpdateCallback.h64
-rw-r--r--src/libs/7zip/unix/CPP/7zip/UI/Common/UpdatePair.cpp214
-rw-r--r--src/libs/7zip/unix/CPP/7zip/UI/Common/UpdatePair.h4
-rw-r--r--src/libs/7zip/unix/CPP/7zip/UI/Common/UpdateProduce.cpp27
-rw-r--r--src/libs/7zip/unix/CPP/7zip/UI/Common/UpdateProduce.h26
-rw-r--r--src/libs/7zip/unix/CPP/7zip/UI/Common/WorkDir.cpp59
-rw-r--r--src/libs/7zip/unix/CPP/7zip/UI/Common/WorkDir.h10
-rw-r--r--src/libs/7zip/unix/CPP/7zip/UI/Common/ZipRegistry.h105
-rw-r--r--src/libs/7zip/unix/CPP/7zip/UI/Console/BenchCon.cpp297
-rw-r--r--src/libs/7zip/unix/CPP/7zip/UI/Console/BenchCon.h16
-rw-r--r--src/libs/7zip/unix/CPP/7zip/UI/Console/Console.pri2
-rw-r--r--src/libs/7zip/unix/CPP/7zip/UI/Console/ConsoleClose.cpp49
-rw-r--r--src/libs/7zip/unix/CPP/7zip/UI/Console/ConsoleClose.h26
-rw-r--r--src/libs/7zip/unix/CPP/7zip/UI/Console/ExtractCallbackConsole.cpp228
-rw-r--r--src/libs/7zip/unix/CPP/7zip/UI/Console/ExtractCallbackConsole.h73
-rw-r--r--src/libs/7zip/unix/CPP/7zip/UI/Console/List.cpp654
-rw-r--r--src/libs/7zip/unix/CPP/7zip/UI/Console/List.h20
-rw-r--r--src/libs/7zip/unix/CPP/7zip/UI/Console/Main.cpp628
-rw-r--r--src/libs/7zip/unix/CPP/7zip/UI/Console/MainAr.cpp127
-rw-r--r--src/libs/7zip/unix/CPP/7zip/UI/Console/OpenCallbackConsole.cpp58
-rw-r--r--src/libs/7zip/unix/CPP/7zip/UI/Console/OpenCallbackConsole.h24
-rw-r--r--src/libs/7zip/unix/CPP/7zip/UI/Console/PercentPrinter.cpp40
-rw-r--r--src/libs/7zip/unix/CPP/7zip/UI/Console/PercentPrinter.h11
-rw-r--r--src/libs/7zip/unix/CPP/7zip/UI/Console/UpdateCallbackConsole.cpp261
-rw-r--r--src/libs/7zip/unix/CPP/7zip/UI/Console/UpdateCallbackConsole.h62
-rw-r--r--src/libs/7zip/unix/CPP/7zip/UI/Console/UserInputUtils.cpp96
-rw-r--r--src/libs/7zip/unix/CPP/7zip/UI/Console/UserInputUtils.h24
69 files changed, 9483 insertions, 6314 deletions
diff --git a/src/libs/7zip/unix/CPP/7zip/UI/Common/ArchiveCommandLine.cpp b/src/libs/7zip/unix/CPP/7zip/UI/Common/ArchiveCommandLine.cpp
index d954129f3..48587264f 100644
--- a/src/libs/7zip/unix/CPP/7zip/UI/Common/ArchiveCommandLine.cpp
+++ b/src/libs/7zip/unix/CPP/7zip/UI/Common/ArchiveCommandLine.cpp
@@ -1,6 +1,8 @@
// ArchiveCommandLine.cpp
#include "StdAfx.h"
+#undef printf
+#undef sprintf
#ifdef _WIN32
#ifndef UNDER_CE
@@ -9,15 +11,15 @@
#endif
#include <stdio.h>
-#include "Common/ListFileUtils.h"
-#include "Common/StringConvert.h"
-#include "Common/StringToInt.h"
+#include "../../../Common/ListFileUtils.h"
+#include "../../../Common/StringConvert.h"
+#include "../../../Common/StringToInt.h"
-#include "Windows/FileDir.h"
-#include "Windows/FileName.h"
+#include "../../../Windows/FileDir.h"
+#include "../../../Windows/FileName.h"
#ifdef _WIN32
-#include "Windows/FileMapping.h"
-#include "Windows/Synchronization.h"
+#include "../../../Windows/FileMapping.h"
+#include "../../../Windows/Synchronization.h"
#else
#include "myPrivate.h"
#endif
@@ -50,6 +52,32 @@ using namespace NCommandLineParser;
using namespace NWindows;
using namespace NFile;
+static bool StringToUInt32(const wchar_t *s, UInt32 &v)
+{
+ if (*s == 0)
+ return false;
+ const wchar_t *end;
+ v = ConvertStringToUInt32(s, &end);
+ return *end == 0;
+}
+
+static void AddNewLine(UString &s)
+{
+ s += L'\n';
+}
+
+CArcCmdLineException::CArcCmdLineException(const char *a, const wchar_t *u)
+{
+ (*this) += MultiByteToUnicodeString(a);
+ if (u)
+ {
+ AddNewLine(*this);
+ (*this) += u;
+ }
+}
+
+int g_CodePage = -1;
+
namespace NKey {
enum Enum
{
@@ -81,22 +109,55 @@ enum Enum
kEmail,
kShowDialog,
kLargePages,
- kUseLStat,
+ // kListfileCharSet,
+ // kConsoleCharSet,
kTechMode,
+#ifdef _WIN32
+ kShareForWrite,
+#endif
+ kUseLStat,
kCaseSensitive,
- kCalcCrc
+ kHash,
+ kArcNameMode,
+
+ kDisableWildcardParsing,
+ kElimDup,
+ kFullPathMode,
+
+ kHardLinks,
+ kSymLinks,
+ kNtSecurity,
+ kAltStreams,
+ kReplaceColonForAltStream,
+ kWriteToAltStreamIfColon,
+
+ kDeleteAfterCompressing,
+ kSetArcMTime,
+ kExcludedArcType
};
}
-static const wchar_t kRecursedIDChar = 'R';
-static const wchar_t *kRecursedPostCharSet = L"0-";
+static const wchar_t kRecursedIDChar = 'r';
+static const char *kRecursedPostCharSet = "0-";
+
+static const char *k_ArcNameMode_PostCharSet = "sea";
+
+static inline const EArcNameMode ParseArcNameMode(int postCharIndex)
+{
+ switch (postCharIndex)
+ {
+ case 1: return k_ArcNameMode_Exact;
+ case 2: return k_ArcNameMode_Add;
+ default: return k_ArcNameMode_Smart;
+ }
+}
namespace NRecursedPostCharIndex {
enum EEnum
{
- kWildCardRecursionOnly = 0,
+ kWildcardRecursionOnly = 0,
kNoRecursion = 1
};
}
@@ -108,133 +169,128 @@ static const char kFileListID = '@';
static const char kSomeCludePostStringMinSize = 2; // at least <@|!><N>ame must be
static const char kSomeCludeAfterRecursedPostStringMinSize = 2; // at least <@|!><N>ame must be
-static const wchar_t *kOverwritePostCharSet = L"asut";
+static const char *kOverwritePostCharSet = "asut";
NExtract::NOverwriteMode::EEnum k_OverwriteModes[] =
{
- NExtract::NOverwriteMode::kWithoutPrompt,
- NExtract::NOverwriteMode::kSkipExisting,
- NExtract::NOverwriteMode::kAutoRename,
- NExtract::NOverwriteMode::kAutoRenameExisting
+ NExtract::NOverwriteMode::kOverwrite,
+ NExtract::NOverwriteMode::kSkip,
+ NExtract::NOverwriteMode::kRename,
+ NExtract::NOverwriteMode::kRenameExisting
};
static const CSwitchForm kSwitchForms[] =
- {
- { L"?", NSwitchType::kSimple, false },
- { L"H", NSwitchType::kSimple, false },
- { L"-HELP", NSwitchType::kSimple, false },
- { L"BA", NSwitchType::kSimple, false },
- { L"BD", NSwitchType::kSimple, false },
- { L"T", NSwitchType::kUnLimitedPostString, false, 1 },
- { L"Y", NSwitchType::kSimple, false },
- #ifndef _NO_CRYPTO
- { L"P", NSwitchType::kUnLimitedPostString, false, 0 },
- #endif
- { L"M", NSwitchType::kUnLimitedPostString, true, 1 },
- { L"O", NSwitchType::kUnLimitedPostString, false, 1 },
- { L"W", NSwitchType::kUnLimitedPostString, false, 0 },
- { L"I", NSwitchType::kUnLimitedPostString, true, kSomeCludePostStringMinSize},
- { L"X", NSwitchType::kUnLimitedPostString, true, kSomeCludePostStringMinSize},
- { L"AI", NSwitchType::kUnLimitedPostString, true, kSomeCludePostStringMinSize},
- { L"AX", NSwitchType::kUnLimitedPostString, true, kSomeCludePostStringMinSize},
- { L"AN", NSwitchType::kSimple, false },
- { L"U", NSwitchType::kUnLimitedPostString, true, 1},
- { L"V", NSwitchType::kUnLimitedPostString, true, 1},
- { L"R", NSwitchType::kPostChar, false, 0, 0, kRecursedPostCharSet },
- { L"SFX", NSwitchType::kUnLimitedPostString, false, 0 },
- { L"SI", NSwitchType::kUnLimitedPostString, false, 0 },
- { L"SO", NSwitchType::kSimple, false, 0 },
- { L"AO", NSwitchType::kPostChar, false, 1, 1, kOverwritePostCharSet},
- { L"SEML", NSwitchType::kUnLimitedPostString, false, 0},
- { L"AD", NSwitchType::kSimple, false },
- { L"SLP", NSwitchType::kUnLimitedPostString, false, 0},
- { L"L", NSwitchType::kSimple, false },
- { L"SLT", NSwitchType::kSimple, false },
- { L"SSC", NSwitchType::kPostChar, false, 0, 0, L"-" },
- { L"SCRC", NSwitchType::kSimple, false }
- };
-
-static const CCommandForm g_CommandForms[] =
-{
- { L"A", false },
- { L"U", false },
- { L"D", false },
- { L"T", false },
- { L"E", false },
- { L"X", false },
- { L"L", false },
- { L"B", false },
- { L"I", false }
+{
+ { "?" },
+ { "h" },
+ { "-help" },
+ { "ba" },
+ { "bd" },
+ { "t", NSwitchType::kString, false, 1 },
+ { "y" },
+ #ifndef _NO_CRYPTO
+ { "p", NSwitchType::kString },
+ #endif
+ { "m", NSwitchType::kString, true, 1 },
+ { "o", NSwitchType::kString, false, 1 },
+ { "w", NSwitchType::kString },
+ { "i", NSwitchType::kString, true, kSomeCludePostStringMinSize},
+ { "x", NSwitchType::kString, true, kSomeCludePostStringMinSize},
+ { "ai", NSwitchType::kString, true, kSomeCludePostStringMinSize},
+ { "ax", NSwitchType::kString, true, kSomeCludePostStringMinSize},
+ { "an" },
+ { "u", NSwitchType::kString, true, 1},
+ { "v", NSwitchType::kString, true, 1},
+ { "r", NSwitchType::kChar, false, 0, kRecursedPostCharSet },
+ { "sfx", NSwitchType::kString },
+ { "si", NSwitchType::kString },
+ { "so" },
+ { "ao", NSwitchType::kChar, false, 1, kOverwritePostCharSet},
+ { "seml", NSwitchType::kString, false, 0},
+ { "ad" },
+ { "slp", NSwitchType::kMinus },
+ // { "scs", NSwitchType::kString },
+ // { "scc", NSwitchType::kString },
+ { "slt" },
+ // { "ssw" },
+ { "l" },
+ { "ssc", NSwitchType::kMinus },
+ { "scrc", NSwitchType::kString, true, 0 },
+ { "sa", NSwitchType::kChar, false, 1, k_ArcNameMode_PostCharSet },
+
+ { "spd" },
+ { "spe", NSwitchType::kMinus },
+ { "spf", NSwitchType::kString, false, 0 },
+
+ { "snh", NSwitchType::kMinus },
+ { "snl", NSwitchType::kMinus },
+ { "sni" },
+ { "sns", NSwitchType::kMinus },
+
+ { "snr" },
+ { "snc" },
+
+ { "sdel" },
+ { "stl" },
+ { "stx", NSwitchType::kString, true, 1 }
};
-static const int kNumCommandForms = sizeof(g_CommandForms) / sizeof(g_CommandForms[0]);
-
static const wchar_t *kUniversalWildcard = L"*";
static const int kMinNonSwitchWords = 1;
static const int kCommandIndex = 0;
-// ---------------------------
-// exception messages
-
-static const char *kUserErrorMessage = "Incorrect command line";
+// static const char *kUserErrorMessage = "Incorrect command line";
static const char *kCannotFindListFile = "Cannot find listfile";
static const char *kIncorrectListFile = "Incorrect item in listfile.\nCheck charset encoding and -scs switch.";
-static const char *kIncorrectWildCardInListFile = "Incorrect wildcard in listfile";
-static const char *kIncorrectWildCardInCommandLine = "Incorrect wildcard in command line";
+static const char *kIncorrectWildcardInListFile = "Incorrect wildcard in listfile";
+static const char *kIncorrectWildcardInCommandLine = "Incorrect wildcard in command line";
static const char *kTerminalOutError = "I won't write compressed data to a terminal";
static const char *kSameTerminalError = "I won't write data and program's messages to same terminal";
static const char *kEmptyFilePath = "Empty file path";
+static const char *kCannotFindArchive = "Cannot find archive";
-static void ThrowException(const char *errorMessage)
+bool CArcCommand::IsFromExtractGroup() const
{
- throw CArchiveCommandLineException(errorMessage);
-}
-
-static void ThrowUserErrorException()
-{
- ThrowException(kUserErrorMessage);
-}
-
-// ---------------------------
-
-bool CArchiveCommand::IsFromExtractGroup() const
-{
- switch(CommandType)
+ switch (CommandType)
{
case NCommandType::kTest:
case NCommandType::kExtract:
- case NCommandType::kFullExtract:
+ case NCommandType::kExtractFull:
return true;
- default:
- return false;
}
+ return false;
}
-NExtract::NPathMode::EEnum CArchiveCommand::GetPathMode() const
+NExtract::NPathMode::EEnum CArcCommand::GetPathMode() const
{
- switch(CommandType)
+ switch (CommandType)
{
case NCommandType::kTest:
- case NCommandType::kFullExtract:
- return NExtract::NPathMode::kFullPathnames;
- default:
- return NExtract::NPathMode::kNoPathnames;
+ case NCommandType::kExtractFull:
+ return NExtract::NPathMode::kFullPaths;
}
+ return NExtract::NPathMode::kNoPaths;
}
-bool CArchiveCommand::IsFromUpdateGroup() const
+bool CArcCommand::IsFromUpdateGroup() const
{
- return (CommandType == NCommandType::kAdd ||
- CommandType == NCommandType::kUpdate ||
- CommandType == NCommandType::kDelete);
+ switch (CommandType)
+ {
+ case NCommandType::kAdd:
+ case NCommandType::kUpdate:
+ case NCommandType::kDelete:
+ case NCommandType::kRename:
+ return true;
+ }
+ return false;
}
static NRecursedType::EEnum GetRecursedTypeFromIndex(int index)
{
switch (index)
{
- case NRecursedPostCharIndex::kWildCardRecursionOnly:
- return NRecursedType::kWildCardOnlyRecursed;
+ case NRecursedPostCharIndex::kWildcardRecursionOnly:
+ return NRecursedType::kWildcardOnlyRecursed;
case NRecursedPostCharIndex::kNoRecursion:
return NRecursedType::kNonRecursed;
default:
@@ -242,170 +298,281 @@ static NRecursedType::EEnum GetRecursedTypeFromIndex(int index)
}
}
-static bool ParseArchiveCommand(const UString &commandString, CArchiveCommand &command)
+static const char *g_Commands = "audtexlbih";
+
+static bool ParseArchiveCommand(const UString &commandString, CArcCommand &command)
{
- UString commandStringUpper = commandString;
- commandStringUpper.MakeUpper();
- UString postString;
- int commandIndex = ParseCommand(kNumCommandForms, g_CommandForms, commandStringUpper,
- postString) ;
- if (commandIndex < 0)
- return false;
- command.CommandType = (NCommandType::EEnum)commandIndex;
- return true;
+ UString s = commandString;
+ s.MakeLower_Ascii();
+ if (s.Len() == 1)
+ {
+ if (s[0] > 0x7F)
+ return false;
+ int index = FindCharPosInString(g_Commands, (char)s[0]);
+ if (index < 0)
+ return false;
+ command.CommandType = (NCommandType::EEnum)index;
+ return true;
+ }
+ if (s.Len() == 2 && s[0] == 'r' && s[1] == 'n')
+ {
+ command.CommandType = (NCommandType::kRename);
+ return true;
+ }
+ return false;
}
// ------------------------------------------------------------------
// filenames functions
-static void AddNameToCensor(NWildcard::CCensor &wildcardCensor,
- const UString &name, bool include, NRecursedType::EEnum type)
+static void AddNameToCensor(NWildcard::CCensor &censor,
+ const UString &name, bool include, NRecursedType::EEnum type, bool wildcardMatching)
{
bool recursed = false;
switch (type)
{
- case NRecursedType::kWildCardOnlyRecursed:
- recursed = DoesNameContainWildCard(name);
+ case NRecursedType::kWildcardOnlyRecursed:
+ recursed = DoesNameContainWildcard(name);
break;
case NRecursedType::kRecursed:
recursed = true;
break;
}
- wildcardCensor.AddItem(include, name, recursed);
+ censor.AddPreItem(include, name, recursed, wildcardMatching);
}
-static void AddToCensorFromListFile(NWildcard::CCensor &wildcardCensor,
- LPCWSTR fileName, bool include, NRecursedType::EEnum type, UINT codePage)
+static void AddRenamePair(CObjectVector<CRenamePair> *renamePairs,
+ const UString &oldName, const UString &newName, NRecursedType::EEnum type,
+ bool wildcardMatching)
+{
+ CRenamePair &pair = renamePairs->AddNew();
+ pair.OldName = oldName;
+ pair.NewName = newName;
+ pair.RecursedType = type;
+ pair.WildcardParsing = wildcardMatching;
+
+ if (!pair.Prepare())
+ {
+ UString val;
+ val += pair.OldName;
+ AddNewLine(val);
+ val += pair.NewName;
+ AddNewLine(val);
+ if (type == NRecursedType::kRecursed)
+ val += L"-r";
+ else if (type == NRecursedType::kRecursed)
+ val += L"-r0";
+ throw CArcCmdLineException("Unsupported rename command:", val);
+ }
+}
+
+static void AddToCensorFromListFile(
+ CObjectVector<CRenamePair> *renamePairs,
+ NWildcard::CCensor &censor,
+ LPCWSTR fileName, bool include, NRecursedType::EEnum type, bool wildcardMatching, Int32 codePage)
{
UStringVector names;
- if (!NFind::DoesFileExist(fileName))
- throw kCannotFindListFile;
- if (!ReadNamesFromListFile(fileName, names, codePage))
- throw kIncorrectListFile;
- for (int i = 0; i < names.Size(); i++)
- AddNameToCensor(wildcardCensor, names[i], include, type);
+ if (!NFind::DoesFileExist(us2fs(fileName)))
+ throw CArcCmdLineException(kCannotFindListFile, fileName);
+ if (!ReadNamesFromListFile(us2fs(fileName), names, codePage))
+ throw CArcCmdLineException(kIncorrectListFile, fileName);
+ if (renamePairs)
+ {
+ if ((names.Size() & 1) != 0)
+ throw CArcCmdLineException(kIncorrectListFile, fileName);
+ for (unsigned i = 0; i < names.Size(); i += 2)
+ {
+ // change type !!!!
+ AddRenamePair(renamePairs, names[i], names[i + 1], type, wildcardMatching);
+ }
+ }
+ else
+ FOR_VECTOR (i, names)
+ AddNameToCensor(censor, names[i], include, type, wildcardMatching);
}
static void AddToCensorFromNonSwitchesStrings(
- int startIndex,
- NWildcard::CCensor &wildcardCensor,
+ CObjectVector<CRenamePair> *renamePairs,
+ unsigned startIndex,
+ NWildcard::CCensor &censor,
const UStringVector &nonSwitchStrings, NRecursedType::EEnum type,
- bool thereAreSwitchIncludes, UINT codePage)
+ bool wildcardMatching,
+ bool thereAreSwitchIncludes, Int32 codePage)
{
- if (nonSwitchStrings.Size() == startIndex && (!thereAreSwitchIncludes))
- AddNameToCensor(wildcardCensor, kUniversalWildcard, true, type);
- for (int i = startIndex; i < nonSwitchStrings.Size(); i++)
+ if ((renamePairs || nonSwitchStrings.Size() == startIndex) && !thereAreSwitchIncludes)
+ AddNameToCensor(censor, kUniversalWildcard, true, type,
+ true // wildcardMatching
+ );
+
+ int oldIndex = -1;
+
+ for (unsigned i = startIndex; i < nonSwitchStrings.Size(); i++)
{
const UString &s = nonSwitchStrings[i];
if (s.IsEmpty())
- throw kEmptyFilePath;
+ throw CArcCmdLineException(kEmptyFilePath);
if (s[0] == kFileListID)
- AddToCensorFromListFile(wildcardCensor, s.Mid(1), true, type, codePage);
- else
- AddNameToCensor(wildcardCensor, s, true, type);
- }
-}
-
-#ifdef _WIN32
-static void ParseMapWithPaths(NWildcard::CCensor &wildcardCensor,
- const UString &switchParam, bool include,
- NRecursedType::EEnum commonRecursedType)
-{
- int splitPos = switchParam.Find(L':');
- if (splitPos < 0)
- ThrowUserErrorException();
- UString mappingName = switchParam.Left(splitPos);
-
- UString switchParam2 = switchParam.Mid(splitPos + 1);
- splitPos = switchParam2.Find(L':');
- if (splitPos < 0)
- ThrowUserErrorException();
-
- UString mappingSize = switchParam2.Left(splitPos);
- UString eventName = switchParam2.Mid(splitPos + 1);
-
- UInt64 dataSize64 = ConvertStringToUInt64(mappingSize, NULL);
- UInt32 dataSize = (UInt32)dataSize64;
- {
- CFileMapping fileMapping;
- if (fileMapping.Open(FILE_MAP_READ, GetSystemString(mappingName)) != 0)
- ThrowException("Can not open mapping");
- LPVOID data = fileMapping.Map(FILE_MAP_READ, 0, dataSize);
- if (data == NULL)
- ThrowException("MapViewOfFile error");
- try
+ AddToCensorFromListFile(renamePairs, censor, s.Ptr(1), true, type, wildcardMatching, codePage);
+ else if (renamePairs)
{
- const wchar_t *curData = (const wchar_t *)data;
- if (*curData != 0)
- ThrowException("Incorrect mapping data");
- UInt32 numChars = dataSize / sizeof(wchar_t);
- UString name;
- for (UInt32 i = 1; i < numChars; i++)
+ if (oldIndex == -1)
+ oldIndex = startIndex;
+ else
{
- wchar_t c = curData[i];
- if (c == L'\0')
- {
- AddNameToCensor(wildcardCensor, name, include, commonRecursedType);
- name.Empty();
- }
- else
- name += c;
+ // NRecursedType::EEnum type is used for global wildcard (-i! switches)
+ AddRenamePair(renamePairs, nonSwitchStrings[oldIndex], s, NRecursedType::kNonRecursed, wildcardMatching);
+ // AddRenamePair(renamePairs, nonSwitchStrings[oldIndex], s, type);
+ oldIndex = -1;
}
- if (!name.IsEmpty())
- ThrowException("data error");
}
- catch(...)
- {
- UnmapViewOfFile(data);
- throw;
- }
- UnmapViewOfFile(data);
+ else
+ AddNameToCensor(censor, s, true, type, wildcardMatching);
}
-
+
+ if (oldIndex != -1)
+ {
+ throw CArcCmdLineException("There is no second file name for rename pair:", nonSwitchStrings[oldIndex]);
+ }
+}
+
+#ifdef _WIN32
+
+struct CEventSetEnd
+{
+ UString Name;
+
+ CEventSetEnd(const wchar_t *name): Name(name) {}
+ ~CEventSetEnd()
{
NSynchronization::CManualResetEvent event;
- if (event.Open(EVENT_MODIFY_STATE, false, GetSystemString(eventName)) == S_OK)
+ if (event.Open(EVENT_MODIFY_STATE, false, GetSystemString(Name)) == 0)
event.Set();
}
+};
+
+const char *k_IncorrectMapCommand = "Incorrect Map command";
+
+static const char *ParseMapWithPaths(
+ NWildcard::CCensor &censor,
+ const UString &s2, bool include,
+ NRecursedType::EEnum commonRecursedType,
+ bool wildcardMatching)
+{
+ UString s = s2;
+ int pos = s.Find(L':');
+ if (pos < 0)
+ return k_IncorrectMapCommand;
+ int pos2 = s.Find(L':', pos + 1);
+ if (pos2 < 0)
+ return k_IncorrectMapCommand;
+
+ CEventSetEnd eventSetEnd((const wchar_t *)s + (pos2 + 1));
+ s.DeleteFrom(pos2);
+ UInt32 size;
+ if (!StringToUInt32(s.Ptr(pos + 1), size)
+ || size < sizeof(wchar_t)
+ || size > ((UInt32)1 << 31)
+ || size % sizeof(wchar_t) != 0)
+ return "Unsupported Map data size";
+
+ s.DeleteFrom(pos);
+ CFileMapping map;
+ if (map.Open(FILE_MAP_READ, GetSystemString(s)) != 0)
+ return "Can not open mapping";
+ LPVOID data = map.Map(FILE_MAP_READ, 0, size);
+ if (!data)
+ return "MapViewOfFile error";
+ CFileUnmapper unmapper(data);
+
+ UString name;
+ const wchar_t *p = (const wchar_t *)data;
+ if (*p != 0) // data format marker
+ return "Unsupported Map data";
+ UInt32 numChars = size / sizeof(wchar_t);
+ for (UInt32 i = 1; i < numChars; i++)
+ {
+ wchar_t c = p[i];
+ if (c == 0)
+ {
+ // MessageBoxW(0, name, L"7-Zip", 0);
+ AddNameToCensor(censor, name, include, commonRecursedType, wildcardMatching);
+ name.Empty();
+ }
+ else
+ name += c;
+ }
+ if (!name.IsEmpty())
+ return "Map data error";
+
+ return NULL;
}
+
#endif
-static void AddSwitchWildCardsToCensor(NWildcard::CCensor &wildcardCensor,
+static void AddSwitchWildcardsToCensor(
+ NWildcard::CCensor &censor,
const UStringVector &strings, bool include,
- NRecursedType::EEnum commonRecursedType, UINT codePage)
+ NRecursedType::EEnum commonRecursedType,
+ bool wildcardMatching,
+ Int32 codePage)
{
- for (int i = 0; i < strings.Size(); i++)
+ const char *errorMessage = NULL;
+ unsigned i;
+ for (i = 0; i < strings.Size(); i++)
{
const UString &name = strings[i];
NRecursedType::EEnum recursedType;
- int pos = 0;
- if (name.Length() < kSomeCludePostStringMinSize)
- ThrowUserErrorException();
- if (::MyCharUpper(name[pos]) == kRecursedIDChar)
+ unsigned pos = 0;
+
+ if (name.Len() < kSomeCludePostStringMinSize)
+ {
+ errorMessage = "Too short switch";
+ break;
+ }
+
+ if (::MyCharLower_Ascii(name[pos]) == kRecursedIDChar)
{
pos++;
- int index = UString(kRecursedPostCharSet).Find(name[pos]);
+ wchar_t c = name[pos];
+ int index = -1;
+ if (c <= 0x7F)
+ index = FindCharPosInString(kRecursedPostCharSet, (char)c);
recursedType = GetRecursedTypeFromIndex(index);
if (index >= 0)
pos++;
}
else
recursedType = commonRecursedType;
- if (name.Length() < pos + kSomeCludeAfterRecursedPostStringMinSize)
- ThrowUserErrorException();
- UString tail = name.Mid(pos + 1);
+
+ if (name.Len() < pos + kSomeCludeAfterRecursedPostStringMinSize)
+ {
+ errorMessage = "Too short switch";
+ break;
+ }
+
+ UString tail = name.Ptr(pos + 1);
+
if (name[pos] == kImmediateNameID)
- AddNameToCensor(wildcardCensor, tail, include, recursedType);
+ AddNameToCensor(censor, tail, include, recursedType, wildcardMatching);
else if (name[pos] == kFileListID)
- AddToCensorFromListFile(wildcardCensor, tail, include, recursedType, codePage);
+ AddToCensorFromListFile(NULL, censor, tail, include, recursedType, wildcardMatching, codePage);
#ifdef _WIN32
else if (name[pos] == kMapNameID)
- ParseMapWithPaths(wildcardCensor, tail, include, recursedType);
+ {
+ errorMessage = ParseMapWithPaths(censor, tail, include, recursedType, wildcardMatching);
+ if (errorMessage)
+ break;
+ }
#endif
else
- ThrowUserErrorException();
+ {
+ errorMessage = "Incorrect wildcarc type marker";
+ break;
+ }
}
+ if (i != strings.Size())
+ throw CArcCmdLineException(errorMessage, strings[i]);
}
#ifdef _WIN32
@@ -414,20 +581,25 @@ static void AddSwitchWildCardsToCensor(NWildcard::CCensor &wildcardCensor,
static void ConvertToLongName(const UString &prefix, UString &name)
{
- if (name.IsEmpty() || DoesNameContainWildCard(name))
+ if (name.IsEmpty() || DoesNameContainWildcard(name))
return;
- NFind::CFileInfoW fi;
- if (fi.Find(prefix + name))
- name = fi.Name;
+ NFind::CFileInfo fi;
+ const FString path = us2fs(prefix + name);
+ if (NFile::NName::IsDevicePath(path))
+ return;
+ if (fi.Find(path))
+ name = fs2us(fi.Name);
}
static void ConvertToLongNames(const UString &prefix, CObjectVector<NWildcard::CItem> &items)
{
- for (int i = 0; i < items.Size(); i++)
+ FOR_VECTOR (i, items)
{
NWildcard::CItem &item = items[i];
if (item.Recursive || item.PathParts.Size() != 1)
continue;
+ if (prefix.IsEmpty() && item.IsDriveItem())
+ continue;
ConvertToLongName(prefix, item.PathParts.Front());
}
}
@@ -436,17 +608,22 @@ static void ConvertToLongNames(const UString &prefix, NWildcard::CCensorNode &no
{
ConvertToLongNames(prefix, node.IncludeItems);
ConvertToLongNames(prefix, node.ExcludeItems);
- int i;
+ unsigned i;
for (i = 0; i < node.SubNodes.Size(); i++)
- ConvertToLongName(prefix, node.SubNodes[i].Name);
+ {
+ UString &name = node.SubNodes[i].Name;
+ if (prefix.IsEmpty() && NWildcard::IsDriveColonName(name))
+ continue;
+ ConvertToLongName(prefix, name);
+ }
// mix folders with same name
for (i = 0; i < node.SubNodes.Size(); i++)
{
NWildcard::CCensorNode &nextNode1 = node.SubNodes[i];
- for (int j = i + 1; j < node.SubNodes.Size();)
+ for (unsigned j = i + 1; j < node.SubNodes.Size();)
{
const NWildcard::CCensorNode &nextNode2 = node.SubNodes[j];
- if (nextNode1.Name.CompareNoCase(nextNode2.Name) == 0)
+ if (nextNode1.Name.IsEqualToNoCase(nextNode2.Name))
{
nextNode1.IncludeItems += nextNode2.IncludeItems;
nextNode1.ExcludeItems += nextNode2.ExcludeItems;
@@ -459,13 +636,13 @@ static void ConvertToLongNames(const UString &prefix, NWildcard::CCensorNode &no
for (i = 0; i < node.SubNodes.Size(); i++)
{
NWildcard::CCensorNode &nextNode = node.SubNodes[i];
- ConvertToLongNames(prefix + nextNode.Name + wchar_t(NFile::NName::kDirDelimiter), nextNode);
+ ConvertToLongNames(prefix + nextNode.Name + WCHAR_PATH_SEPARATOR, nextNode);
}
}
-static void ConvertToLongNames(NWildcard::CCensor &censor)
+void ConvertToLongNames(NWildcard::CCensor &censor)
{
- for (int i = 0; i < censor.Pairs.Size(); i++)
+ FOR_VECTOR (i, censor.Pairs)
{
NWildcard::CPair &pair = censor.Pairs[i];
ConvertToLongNames(pair.Prefix, pair.Head);
@@ -474,9 +651,10 @@ static void ConvertToLongNames(NWildcard::CCensor &censor)
#endif
+/*
static NUpdateArchive::NPairAction::EEnum GetUpdatePairActionType(int i)
{
- switch(i)
+ switch (i)
{
case NUpdateArchive::NPairAction::kIgnore: return NUpdateArchive::NPairAction::kIgnore;
case NUpdateArchive::NPairAction::kCopy: return NUpdateArchive::NPairAction::kCopy;
@@ -485,35 +663,36 @@ static NUpdateArchive::NPairAction::EEnum GetUpdatePairActionType(int i)
}
throw 98111603;
}
+*/
-const UString kUpdatePairStateIDSet = L"PQRXYZW";
-const int kUpdatePairStateNotSupportedActions[] = {2, 2, 1, -1, -1, -1, -1};
+static const wchar_t *kUpdatePairStateIDSet = L"pqrxyzw";
+static const int kUpdatePairStateNotSupportedActions[] = {2, 2, 1, -1, -1, -1, -1};
-const UString kUpdatePairActionIDSet = L"0123"; //Ignore, Copy, Compress, Create Anti
-
-const wchar_t *kUpdateIgnoreItselfPostStringID = L"-";
-const wchar_t kUpdateNewArchivePostCharID = '!';
+static const unsigned kNumUpdatePairActions = 4;
+static const char *kUpdateIgnoreItselfPostStringID = "-";
+static const wchar_t kUpdateNewArchivePostCharID = '!';
static bool ParseUpdateCommandString2(const UString &command,
NUpdateArchive::CActionSet &actionSet, UString &postString)
{
- for (int i = 0; i < command.Length();)
+ for (unsigned i = 0; i < command.Len();)
{
- wchar_t c = MyCharUpper(command[i]);
- int statePos = kUpdatePairStateIDSet.Find(c);
+ wchar_t c = MyCharLower_Ascii(command[i]);
+ int statePos = FindCharPosInString(kUpdatePairStateIDSet, c);
if (statePos < 0)
{
- postString = command.Mid(i);
+ postString = command.Ptr(i);
return true;
}
i++;
- if (i >= command.Length())
+ if (i >= command.Len())
return false;
- int actionPos = kUpdatePairActionIDSet.Find(::MyCharUpper(command[i]));
- if (actionPos < 0)
+ c = command[i];
+ if (c < '0' || c >= '0' + kNumUpdatePairActions)
return false;
- actionSet.StateActions[statePos] = GetUpdatePairActionType(actionPos);
+ int actionPos = c - '0';
+ actionSet.StateActions[statePos] = (NUpdateArchive::NPairAction::EEnum)(actionPos);
if (kUpdatePairStateNotSupportedActions[statePos] == actionPos)
return false;
i++;
@@ -526,10 +705,12 @@ static void ParseUpdateCommandString(CUpdateOptions &options,
const UStringVector &updatePostStrings,
const NUpdateArchive::CActionSet &defaultActionSet)
{
- for (int i = 0; i < updatePostStrings.Size(); i++)
+ const char *errorMessage = "incorrect update switch command";
+ unsigned i;
+ for (i = 0; i < updatePostStrings.Size(); i++)
{
const UString &updateString = updatePostStrings[i];
- if (updateString.CompareNoCase(kUpdateIgnoreItselfPostStringID) == 0)
+ if (updateString.IsEqualTo(kUpdateIgnoreItselfPostStringID))
{
if (options.UpdateArchiveItself)
{
@@ -543,7 +724,7 @@ static void ParseUpdateCommandString(CUpdateOptions &options,
UString postString;
if (!ParseUpdateCommandString2(updateString, actionSet, postString))
- ThrowUserErrorException();
+ break;
if (postString.IsEmpty())
{
if (options.UpdateArchiveItself)
@@ -551,64 +732,23 @@ static void ParseUpdateCommandString(CUpdateOptions &options,
}
else
{
- if (MyCharUpper(postString[0]) != kUpdateNewArchivePostCharID)
- ThrowUserErrorException();
+ if (postString[0] != kUpdateNewArchivePostCharID)
+ break;
CUpdateArchiveCommand uc;
- UString archivePath = postString.Mid(1);
+ UString archivePath = postString.Ptr(1);
if (archivePath.IsEmpty())
- ThrowUserErrorException();
+ break;
uc.UserArchivePath = archivePath;
uc.ActionSet = actionSet;
options.Commands.Add(uc);
}
}
}
+ if (i != updatePostStrings.Size())
+ throw CArcCmdLineException(errorMessage, updatePostStrings[i]);
}
-static const char kByteSymbol = 'B';
-static const char kKiloSymbol = 'K';
-static const char kMegaSymbol = 'M';
-static const char kGigaSymbol = 'G';
-
-static bool ParseComplexSize(const UString &src, UInt64 &result)
-{
- UString s = src;
- s.MakeUpper();
-
- const wchar_t *start = s;
- const wchar_t *end;
- UInt64 number = ConvertStringToUInt64(start, &end);
- int numDigits = (int)(end - start);
- if (numDigits == 0 || s.Length() > numDigits + 1)
- return false;
- if (s.Length() == numDigits)
- {
- result = number;
- return true;
- }
- int numBits;
- switch (s[numDigits])
- {
- case kByteSymbol:
- result = number;
- return true;
- case kKiloSymbol:
- numBits = 10;
- break;
- case kMegaSymbol:
- numBits = 20;
- break;
- case kGigaSymbol:
- numBits = 30;
- break;
- default:
- return false;
- }
- if (number >= ((UInt64)1 << (64 - numBits)))
- return false;
- result = number << numBits;
- return true;
-}
+bool ParseComplexSize(const wchar_t *s, UInt64 &result);
static void SetAddCommandOptions(
NCommandType::EEnum commandType,
@@ -616,20 +756,20 @@ static void SetAddCommandOptions(
CUpdateOptions &options)
{
NUpdateArchive::CActionSet defaultActionSet;
- switch(commandType)
+ switch (commandType)
{
case NCommandType::kAdd:
- defaultActionSet = NUpdateArchive::kAddActionSet;
+ defaultActionSet = NUpdateArchive::k_ActionSet_Add;
break;
case NCommandType::kDelete:
- defaultActionSet = NUpdateArchive::kDeleteActionSet;
+ defaultActionSet = NUpdateArchive::k_ActionSet_Delete;
break;
default:
- defaultActionSet = NUpdateArchive::kUpdateActionSet;
+ defaultActionSet = NUpdateArchive::k_ActionSet_Update;
}
-
+
options.UpdateArchiveItself = true;
-
+
options.Commands.Clear();
CUpdateArchiveCommand updateMainCommand;
updateMainCommand.ActionSet = defaultActionSet;
@@ -641,22 +781,22 @@ static void SetAddCommandOptions(
{
const UString &postString = parser[NKey::kWorkingDir].PostStrings[0];
if (postString.IsEmpty())
- NDirectory::MyGetTempPath(options.WorkingDir);
+ NDir::MyGetTempPath(options.WorkingDir);
else
- options.WorkingDir = postString;
+ options.WorkingDir = us2fs(postString);
}
options.SfxMode = parser[NKey::kSfx].ThereIs;
if (options.SfxMode)
- options.SfxModule = parser[NKey::kSfx].PostStrings[0];
+ options.SfxModule = us2fs(parser[NKey::kSfx].PostStrings[0]);
if (parser[NKey::kVolume].ThereIs)
{
const UStringVector &sv = parser[NKey::kVolume].PostStrings;
- for (int i = 0; i < sv.Size(); i++)
+ FOR_VECTOR (i, sv)
{
UInt64 size;
- if (!ParseComplexSize(sv[i], size))
- ThrowException("Incorrect volume size");
+ if (!ParseComplexSize(sv[i], size) || size == 0)
+ throw CArcCmdLineException("Incorrect volume size:", sv[i]);
options.VolumesSizes.Add(size);
}
}
@@ -666,38 +806,28 @@ static void SetMethodOptions(const CParser &parser, CObjectVector<CProperty> &pr
{
if (parser[NKey::kProperty].ThereIs)
{
- // options.MethodMode.Properties.Clear();
- for (int i = 0; i < parser[NKey::kProperty].PostStrings.Size(); i++)
+ FOR_VECTOR (i, parser[NKey::kProperty].PostStrings)
{
- CProperty property;
- const UString &postString = parser[NKey::kProperty].PostStrings[i];
- int index = postString.Find(L'=');
- if (index < 0)
- property.Name = postString;
- else
+ CProperty prop;
+ prop.Name = parser[NKey::kProperty].PostStrings[i];
+ int index = prop.Name.Find(L'=');
+ if (index >= 0)
{
- property.Name = postString.Left(index);
- property.Value = postString.Mid(index + 1);
+ prop.Value = prop.Name.Ptr(index + 1);
+ prop.Name.DeleteFrom(index);
}
- properties.Add(property);
+ properties.Add(prop);
}
}
}
-CArchiveCommandLineParser::CArchiveCommandLineParser():
- parser(sizeof(kSwitchForms) / sizeof(kSwitchForms[0])) {}
+CArcCmdLineParser::CArcCmdLineParser(): parser(ARRAY_SIZE(kSwitchForms)) {}
-void CArchiveCommandLineParser::Parse1(const UStringVector &commandStrings,
- CArchiveCommandLineOptions &options)
+void CArcCmdLineParser::Parse1(const UStringVector &commandStrings,
+ CArcCmdLineOptions &options)
{
- try
- {
- parser.ParseStrings(kSwitchForms, commandStrings);
- }
- catch(...)
- {
- ThrowUserErrorException();
- }
+ if (!parser.ParseStrings(kSwitchForms, commandStrings))
+ throw CArcCmdLineException(parser.ErrorMessage, parser.ErrorLine);
options.IsInTerminal = MY_IS_TERMINAL(stdin);
options.IsStdOutTerminal = MY_IS_TERMINAL(stdout);
@@ -707,44 +837,160 @@ void CArchiveCommandLineParser::Parse1(const UStringVector &commandStrings,
options.EnableHeaders = !parser[NKey::kDisableHeaders].ThereIs;
options.HelpMode = parser[NKey::kHelp1].ThereIs || parser[NKey::kHelp2].ThereIs || parser[NKey::kHelp3].ThereIs;
+ if (parser[NKey::kCaseSensitive].ThereIs)
+ {
+ g_CaseSensitive = !parser[NKey::kCaseSensitive].WithMinus;
+ options.CaseSensitiveChange = true;
+ options.CaseSensitive = g_CaseSensitive;
+ }
+
#ifdef _7ZIP_LARGE_PAGES
options.LargePages = false;
if (parser[NKey::kLargePages].ThereIs)
{
- const UString &postString = parser[NKey::kLargePages].PostStrings.Front();
- if (postString.IsEmpty())
- options.LargePages = true;
+ options.LargePages = !parser[NKey::kLargePages].WithMinus;
}
#endif
}
-static bool ConvertStringToUInt32(const wchar_t *s, UInt32 &v)
+struct CCodePagePair
{
- const wchar_t *end;
- UInt64 number = ConvertStringToUInt64(s, &end);
- if (*end != 0)
- return false;
- if (number > (UInt32)0xFFFFFFFF)
- return false;
- v = (UInt32)number;
- return true;
+ const char *Name;
+ Int32 CodePage;
+};
+
+static const unsigned kNumByteOnlyCodePages = 3;
+
+static CCodePagePair g_CodePagePairs[] =
+{
+ { "utf-8", CP_UTF8 },
+ { "win", CP_ACP },
+ { "dos", CP_OEMCP },
+ { "utf-16le", MY__CP_UTF16 },
+ { "utf-16be", MY__CP_UTF16BE }
+};
+
+static Int32 FindCharset(const NCommandLineParser::CParser &parser, int keyIndex,
+ bool byteOnlyCodePages, Int32 defaultVal)
+{
+ if (!parser[keyIndex].ThereIs)
+ return defaultVal;
+
+ UString name = parser[keyIndex].PostStrings.Back();
+ UInt32 v;
+ if (StringToUInt32(name, v))
+ if (v < ((UInt32)1 << 16))
+ return (Int32)v;
+ name.MakeLower_Ascii();
+ unsigned num = byteOnlyCodePages ? kNumByteOnlyCodePages : ARRAY_SIZE(g_CodePagePairs);
+ for (unsigned i = 0;; i++)
+ {
+ if (i == num) // to disable warnings from different compilers
+ throw CArcCmdLineException("Unsupported charset:", name);
+ const CCodePagePair &pair = g_CodePagePairs[i];
+ if (name.IsEqualTo(pair.Name))
+ return pair.CodePage;
+ }
}
-void CArchiveCommandLineParser::Parse2(CArchiveCommandLineOptions &options)
+void EnumerateDirItemsAndSort(
+ bool storeAltStreams,
+ NWildcard::CCensor &censor,
+ NWildcard::ECensorPathMode censorPathMode,
+ const UString &addPathPrefix,
+ UStringVector &sortedPaths,
+ UStringVector &sortedFullPaths)
+{
+ UStringVector paths;
+ {
+ CDirItems dirItems;
+ {
+ dirItems.ScanAltStreams = storeAltStreams;
+ HRESULT res = EnumerateItems(censor, censorPathMode, addPathPrefix, dirItems, NULL);
+ if (res != S_OK || dirItems.ErrorPaths.Size() > 0)
+ {
+ UString errorPath;
+ if (dirItems.ErrorPaths.Size() > 0)
+ errorPath = fs2us(dirItems.ErrorPaths[0]);
+ throw CArcCmdLineException(kCannotFindArchive,
+ dirItems.ErrorPaths.Size() > 0 ? (const wchar_t *)errorPath : NULL);
+ }
+ }
+ FOR_VECTOR (i, dirItems.Items)
+ {
+ const CDirItem &dirItem = dirItems.Items[i];
+ if (!dirItem.IsDir())
+ paths.Add(dirItems.GetPhyPath(i));
+ }
+ }
+
+ if (paths.Size() == 0)
+ throw CArcCmdLineException(kCannotFindArchive);
+
+ UStringVector fullPaths;
+
+ unsigned i;
+ for (i = 0; i < paths.Size(); i++)
+ {
+ FString fullPath;
+ NFile::NDir::MyGetFullPathName(us2fs(paths[i]), fullPath);
+ fullPaths.Add(fs2us(fullPath));
+ }
+ CUIntVector indices;
+ SortFileNames(fullPaths, indices);
+ sortedPaths.ClearAndReserve(indices.Size());
+ sortedFullPaths.ClearAndReserve(indices.Size());
+ for (i = 0; i < indices.Size(); i++)
+ {
+ unsigned index = indices[i];
+ sortedPaths.AddInReserved(paths[index]);
+ sortedFullPaths.AddInReserved(fullPaths[index]);
+ if (i > 0 && CompareFileNames(sortedFullPaths[i], sortedFullPaths[i - 1]) == 0)
+ throw CArcCmdLineException("Duplicate archive path:", sortedFullPaths[i]);
+ }
+}
+
+static void SetBoolPair(NCommandLineParser::CParser &parser, unsigned switchID, CBoolPair &bp)
+{
+ bp.Def = parser[switchID].ThereIs;
+ if (bp.Def)
+ bp.Val = !parser[switchID].WithMinus;
+}
+
+void CArcCmdLineParser::Parse2(CArcCmdLineOptions &options)
{
const UStringVector &nonSwitchStrings = parser.NonSwitchStrings;
int numNonSwitchStrings = nonSwitchStrings.Size();
if (numNonSwitchStrings < kMinNonSwitchWords)
- ThrowUserErrorException();
+ throw CArcCmdLineException("The command must be spcified");
if (!ParseArchiveCommand(nonSwitchStrings[kCommandIndex], options.Command))
- ThrowUserErrorException();
+ throw CArcCmdLineException("Unsupported command:", nonSwitchStrings[kCommandIndex]);
options.TechMode = parser[NKey::kTechMode].ThereIs;
- options.CalcCrc = parser[NKey::kCalcCrc].ThereIs;
+ if (parser[NKey::kHash].ThereIs)
+ options.HashMethods = parser[NKey::kHash].PostStrings;
- if (parser[NKey::kCaseSensitive].ThereIs)
- g_CaseSensitive = (parser[NKey::kCaseSensitive].PostCharIndex < 0);
+ if (parser[NKey::kElimDup].ThereIs)
+ {
+ options.ExtractOptions.ElimDup.Def = true;
+ options.ExtractOptions.ElimDup.Val = !parser[NKey::kElimDup].WithMinus;
+ }
+
+ NWildcard::ECensorPathMode censorPathMode = NWildcard::k_RelatPath;
+ bool fullPathMode = parser[NKey::kFullPathMode].ThereIs;
+ if (fullPathMode)
+ {
+ censorPathMode = NWildcard::k_AbsPath;
+ const UString &s = parser[NKey::kFullPathMode].PostStrings[0];
+ if (!s.IsEmpty())
+ {
+ if (s == L"2")
+ censorPathMode = NWildcard::k_FullPath;
+ else
+ throw CArcCmdLineException("Unsupported -spf:", s);
+ }
+ }
NRecursedType::EEnum recursedType;
if (parser[NKey::kRecursed].ThereIs)
@@ -752,48 +998,57 @@ void CArchiveCommandLineParser::Parse2(CArchiveCommandLineOptions &options)
else
recursedType = NRecursedType::kNonRecursed;
- UINT codePage = CP_ACP;
+ bool wildcardMatching = true;
+ if (parser[NKey::kDisableWildcardParsing].ThereIs)
+ wildcardMatching = false;
+
+ Int32 codePage = CP_ACP;
bool thereAreSwitchIncludes = false;
+
if (parser[NKey::kInclude].ThereIs)
{
thereAreSwitchIncludes = true;
- AddSwitchWildCardsToCensor(options.WildcardCensor,
- parser[NKey::kInclude].PostStrings, true, recursedType, codePage);
+ AddSwitchWildcardsToCensor(options.Censor,
+ parser[NKey::kInclude].PostStrings, true, recursedType, wildcardMatching, codePage);
}
+
if (parser[NKey::kExclude].ThereIs)
- AddSwitchWildCardsToCensor(options.WildcardCensor,
- parser[NKey::kExclude].PostStrings, false, recursedType, codePage);
-
+ AddSwitchWildcardsToCensor(options.Censor,
+ parser[NKey::kExclude].PostStrings, false, recursedType, wildcardMatching, codePage);
+
int curCommandIndex = kCommandIndex + 1;
bool thereIsArchiveName = !parser[NKey::kNoArName].ThereIs &&
options.Command.CommandType != NCommandType::kBenchmark &&
- options.Command.CommandType != NCommandType::kInfo;
+ options.Command.CommandType != NCommandType::kInfo &&
+ options.Command.CommandType != NCommandType::kHash;
bool isExtractGroupCommand = options.Command.IsFromExtractGroup();
bool isExtractOrList = isExtractGroupCommand || options.Command.CommandType == NCommandType::kList;
+ bool isRename = options.Command.CommandType == NCommandType::kRename;
- if (isExtractOrList && options.StdInMode)
+ if ((isExtractOrList || isRename) && options.StdInMode)
thereIsArchiveName = false;
+ if (parser[NKey::kArcNameMode].ThereIs)
+ options.UpdateOptions.ArcNameMode = ParseArcNameMode(parser[NKey::kArcNameMode].PostCharIndex);
+
if (thereIsArchiveName)
{
if (curCommandIndex >= numNonSwitchStrings)
- ThrowUserErrorException();
+ throw CArcCmdLineException("Cannot find archive name");
options.ArchiveName = nonSwitchStrings[curCommandIndex++];
if (options.ArchiveName.IsEmpty())
- ThrowUserErrorException();
+ throw CArcCmdLineException("Archive name cannot by empty");
}
- AddToCensorFromNonSwitchesStrings(
- curCommandIndex, options.WildcardCensor,
- nonSwitchStrings, recursedType, thereAreSwitchIncludes, codePage);
+ AddToCensorFromNonSwitchesStrings(isRename ? &options.UpdateOptions.RenamePairs : NULL,
+ curCommandIndex, options.Censor,
+ nonSwitchStrings, recursedType, wildcardMatching,
+ thereAreSwitchIncludes, codePage);
options.YesToAll = parser[NKey::kYes].ThereIs;
-#ifdef ENV_HAVE_LSTAT
- global_use_lstat = !parser[NKey::kUseLStat].ThereIs;
-#endif
#ifndef _NO_CRYPTO
options.PasswordEnabled = parser[NKey::kPassword].ThereIs;
@@ -806,35 +1061,73 @@ void CArchiveCommandLineParser::Parse2(CArchiveCommandLineOptions &options)
if (parser[NKey::kArchiveType].ThereIs)
options.ArcType = parser[NKey::kArchiveType].PostStrings[0];
+ options.ExcludedArcTypes = parser[NKey::kExcludedArcType].PostStrings;
+
+ SetMethodOptions(parser, options.Properties);
+
+ options.EnablePercents = !parser[NKey::kDisablePercents].ThereIs;
+
+ if (options.EnablePercents)
+ {
+ if ((options.StdOutMode && !options.IsStdErrTerminal) ||
+ (!options.StdOutMode && !options.IsStdOutTerminal))
+ options.EnablePercents = false;
+ }
+
+ if (parser[NKey::kNtSecurity].ThereIs) options.NtSecurity.SetTrueTrue();
+
+ SetBoolPair(parser, NKey::kAltStreams, options.AltStreams);
+ SetBoolPair(parser, NKey::kHardLinks, options.HardLinks);
+ SetBoolPair(parser, NKey::kSymLinks, options.SymLinks);
+
if (isExtractOrList)
{
- if (!options.WildcardCensor.AllAreRelative())
- ThrowException("Cannot use absolute pathnames for this command");
+ CExtractOptionsBase &eo = options.ExtractOptions;
+
+ {
+ CExtractNtOptions &nt = eo.NtOptions;
+ nt.NtSecurity = options.NtSecurity;
- NWildcard::CCensor archiveWildcardCensor;
+ nt.AltStreams = options.AltStreams;
+ if (!options.AltStreams.Def)
+ nt.AltStreams.Val = true;
+
+ nt.HardLinks = options.HardLinks;
+ if (!options.HardLinks.Def)
+ nt.HardLinks.Val = true;
+
+ nt.SymLinks = options.SymLinks;
+ if (!options.SymLinks.Def)
+ nt.SymLinks.Val = true;
+
+ nt.ReplaceColonForAltStream = parser[NKey::kReplaceColonForAltStream].ThereIs;
+ nt.WriteToAltStreamIfColon = parser[NKey::kWriteToAltStreamIfColon].ThereIs;
+ }
+
+ options.Censor.AddPathsToCensor(NWildcard::k_AbsPath);
+ options.Censor.ExtendExclude();
+
+ // are there paths that look as non-relative (!Prefix.IsEmpty())
+ if (!options.Censor.AllAreRelative())
+ throw CArcCmdLineException("Cannot use absolute pathnames for this command");
+
+ NWildcard::CCensor arcCensor;
if (parser[NKey::kArInclude].ThereIs)
- AddSwitchWildCardsToCensor(archiveWildcardCensor,
- parser[NKey::kArInclude].PostStrings, true, NRecursedType::kNonRecursed, codePage);
+ AddSwitchWildcardsToCensor(arcCensor, parser[NKey::kArInclude].PostStrings, true, NRecursedType::kNonRecursed, wildcardMatching, codePage);
if (parser[NKey::kArExclude].ThereIs)
- AddSwitchWildCardsToCensor(archiveWildcardCensor,
- parser[NKey::kArExclude].PostStrings, false, NRecursedType::kNonRecursed, codePage);
-
- bool directlyAddArchiveName = false;
- if (thereIsArchiveName) {
- if ((options.ArchiveName.Find(kUniversalWildcard) == -1) && (options.ArchiveName.Find(L"?") == -1)) {
- // no wildcard => no need to scan
- directlyAddArchiveName = true;
- } else {
- AddNameToCensor(archiveWildcardCensor, options.ArchiveName, true, NRecursedType::kNonRecursed);
- }
- }
+ AddSwitchWildcardsToCensor(arcCensor, parser[NKey::kArExclude].PostStrings, false, NRecursedType::kNonRecursed, wildcardMatching, codePage);
+
+ if (thereIsArchiveName)
+ AddNameToCensor(arcCensor, options.ArchiveName, true, NRecursedType::kNonRecursed, wildcardMatching);
+
+ arcCensor.AddPathsToCensor(NWildcard::k_RelatPath);
#ifdef _WIN32
- ConvertToLongNames(archiveWildcardCensor);
+ ConvertToLongNames(arcCensor);
#endif
- archiveWildcardCensor.ExtendExclude();
+ arcCensor.ExtendExclude();
if (options.StdInMode)
{
@@ -844,95 +1137,78 @@ void CArchiveCommandLineParser::Parse2(CArchiveCommandLineOptions &options)
}
else
{
-
- UStringVector archivePaths;
-
- {
- CDirItems dirItems;
- {
- UStringVector errorPaths;
- CRecordVector<DWORD> errorCodes;
- HRESULT res = EnumerateItems(archiveWildcardCensor, dirItems, NULL, errorPaths, errorCodes);
- if (res != S_OK || errorPaths.Size() > 0)
- throw "cannot find archive";
- }
- for (int i = 0; i < dirItems.Items.Size(); i++)
- {
- const CDirItem &dirItem = dirItems.Items[i];
- if (!dirItem.IsDir())
- archivePaths.Add(dirItems.GetPhyPath(i));
- }
+ EnumerateDirItemsAndSort(
+ false, // scanAltStreams
+ arcCensor,
+ NWildcard::k_RelatPath,
+ UString(), // addPathPrefix
+ options.ArchivePathsSorted,
+ options.ArchivePathsFullSorted);
}
- // Because the pathname of archive can be a symbolic link
- // do not use "AddCommandLineWildCardToCensr(archiveWildcardCensor, options.ArchiveName"
- if (directlyAddArchiveName)
- archivePaths.Add(options.ArchiveName);
-
- if (archivePaths.Size() == 0)
- throw "there is no such archive";
-
- UStringVector archivePathsFull;
-
- int i;
- for (i = 0; i < archivePaths.Size(); i++)
- {
- UString fullPath;
- NFile::NDirectory::MyGetFullPathName(archivePaths[i], fullPath);
- archivePathsFull.Add(fullPath);
- }
- CIntVector indices;
- SortFileNames(archivePathsFull, indices);
- options.ArchivePathsSorted.Reserve(indices.Size());
- options.ArchivePathsFullSorted.Reserve(indices.Size());
- for (i = 0; i < indices.Size(); i++)
- {
- options.ArchivePathsSorted.Add(archivePaths[indices[i]]);
- options.ArchivePathsFullSorted.Add(archivePathsFull[indices[i]]);
- }
-
- }
-
if (isExtractGroupCommand)
{
- SetMethodOptions(parser, options.ExtractProperties);
if (options.StdOutMode && options.IsStdOutTerminal && options.IsStdErrTerminal)
- throw kSameTerminalError;
+ throw CArcCmdLineException(kSameTerminalError);
if (parser[NKey::kOutputDir].ThereIs)
{
- options.OutputDir = parser[NKey::kOutputDir].PostStrings[0];
- NFile::NName::NormalizeDirPathPrefix(options.OutputDir);
+ eo.OutputDir = us2fs(parser[NKey::kOutputDir].PostStrings[0]);
+ NFile::NName::NormalizeDirPathPrefix(eo.OutputDir);
}
- options.OverwriteMode = NExtract::NOverwriteMode::kAskBefore;
+ eo.OverwriteMode = NExtract::NOverwriteMode::kAsk;
if (parser[NKey::kOverwrite].ThereIs)
- options.OverwriteMode = k_OverwriteModes[parser[NKey::kOverwrite].PostCharIndex];
+ {
+ eo.OverwriteMode = k_OverwriteModes[parser[NKey::kOverwrite].PostCharIndex];
+ eo.OverwriteMode_Force = true;
+ }
else if (options.YesToAll)
- options.OverwriteMode = NExtract::NOverwriteMode::kWithoutPrompt;
+ {
+ eo.OverwriteMode = NExtract::NOverwriteMode::kOverwrite;
+ eo.OverwriteMode_Force = true;
+ }
+ }
+
+ eo.PathMode = options.Command.GetPathMode();
+ if (censorPathMode == NWildcard::k_AbsPath)
+ {
+ eo.PathMode = NExtract::NPathMode::kAbsPaths;
+ eo.PathMode_Force = true;
+ }
+ else if (censorPathMode == NWildcard::k_FullPath)
+ {
+ eo.PathMode = NExtract::NPathMode::kFullPaths;
+ eo.PathMode_Force = true;
}
}
else if (options.Command.IsFromUpdateGroup())
{
+ if (parser[NKey::kArInclude].ThereIs)
+ throw CArcCmdLineException("-ai switch is not supported for this command");
+
CUpdateOptions &updateOptions = options.UpdateOptions;
SetAddCommandOptions(options.Command.CommandType, parser, updateOptions);
-
- SetMethodOptions(parser, updateOptions.MethodMode.Properties);
- options.EnablePercents = !parser[NKey::kDisablePercents].ThereIs;
+ updateOptions.MethodMode.Properties = options.Properties;
- if (options.EnablePercents)
- {
- if ((options.StdOutMode && !options.IsStdErrTerminal) ||
- (!options.StdOutMode && !options.IsStdOutTerminal))
- options.EnablePercents = false;
- }
+#ifdef _WIN32
+ if (parser[NKey::kShareForWrite].ThereIs)
+ updateOptions.OpenShareForWrite = true;
+#endif
+
+ updateOptions.PathMode = censorPathMode;
+
+ updateOptions.AltStreams = options.AltStreams;
+ updateOptions.NtSecurity = options.NtSecurity;
+ updateOptions.HardLinks = options.HardLinks;
+ updateOptions.SymLinks = options.SymLinks;
updateOptions.EMailMode = parser[NKey::kEmail].ThereIs;
if (updateOptions.EMailMode)
{
updateOptions.EMailAddress = parser[NKey::kEmail].PostStrings.Front();
- if (updateOptions.EMailAddress.Length() > 0)
+ if (updateOptions.EMailAddress.Len() > 0)
if (updateOptions.EMailAddress[0] == L'.')
{
updateOptions.EMailRemoveAfter = true;
@@ -943,68 +1219,48 @@ void CArchiveCommandLineParser::Parse2(CArchiveCommandLineOptions &options)
updateOptions.StdOutMode = options.StdOutMode;
updateOptions.StdInMode = options.StdInMode;
+ updateOptions.DeleteAfterCompressing = parser[NKey::kDeleteAfterCompressing].ThereIs;
+ updateOptions.SetArcMTime = parser[NKey::kSetArcMTime].ThereIs;
+
if (updateOptions.StdOutMode && updateOptions.EMailMode)
- throw "stdout mode and email mode cannot be combined";
+ throw CArcCmdLineException("stdout mode and email mode cannot be combined");
if (updateOptions.StdOutMode && options.IsStdOutTerminal)
- throw kTerminalOutError;
+ throw CArcCmdLineException(kTerminalOutError);
if (updateOptions.StdInMode)
updateOptions.StdInFileName = parser[NKey::kStdIn].PostStrings.Front();
- #ifdef _WIN32
- ConvertToLongNames(options.WildcardCensor);
- #endif
+ if (options.Command.CommandType == NCommandType::kRename)
+ if (updateOptions.Commands.Size() != 1)
+ throw CArcCmdLineException("Only one archive can be created with rename command");
}
else if (options.Command.CommandType == NCommandType::kBenchmark)
{
- options.NumThreads = (UInt32)-1;
- options.DictionarySize = (UInt32)-1;
options.NumIterations = 1;
if (curCommandIndex < numNonSwitchStrings)
{
- if (!ConvertStringToUInt32(nonSwitchStrings[curCommandIndex++], options.NumIterations))
- ThrowUserErrorException();
- }
- for (int i = 0; i < parser[NKey::kProperty].PostStrings.Size(); i++)
- {
- UString postString = parser[NKey::kProperty].PostStrings[i];
- postString.MakeUpper();
- if (postString.Length() < 2)
- ThrowUserErrorException();
- if (postString[0] == 'D')
- {
- int pos = 1;
- if (postString[pos] == '=')
- pos++;
- UInt32 logSize;
- if (!ConvertStringToUInt32((const wchar_t *)postString + pos, logSize))
- ThrowUserErrorException();
- if (logSize > 31)
- ThrowUserErrorException();
- options.DictionarySize = 1 << logSize;
- }
- else if (postString[0] == 'M' && postString[1] == 'T' )
- {
- int pos = 2;
- if (postString[pos] == '=')
- pos++;
- if (postString[pos] != 0)
- if (!ConvertStringToUInt32((const wchar_t *)postString + pos, options.NumThreads))
- ThrowUserErrorException();
- }
- else if (postString[0] == 'M' && postString[1] == '=' )
- {
- int pos = 2;
- if (postString[pos] != 0)
- options.Method = postString.Mid(2);
- }
- else
- ThrowUserErrorException();
+ if (!StringToUInt32(nonSwitchStrings[curCommandIndex], options.NumIterations))
+ throw CArcCmdLineException("Incorrect Number of benmchmark iterations", nonSwitchStrings[curCommandIndex]);
+ curCommandIndex++;
}
}
+ else if (options.Command.CommandType == NCommandType::kHash)
+ {
+ options.Censor.AddPathsToCensor(censorPathMode);
+ options.Censor.ExtendExclude();
+
+ CHashOptions &hashOptions = options.HashOptions;
+ hashOptions.PathMode = censorPathMode;
+ hashOptions.Methods = options.HashMethods;
+#ifdef _WIN32
+ if (parser[NKey::kShareForWrite].ThereIs)
+ hashOptions.OpenShareForWrite = true;
+#endif
+ hashOptions.StdInMode = options.StdInMode;
+ hashOptions.AltStreamsMode = options.AltStreams.Val;
+ }
else if (options.Command.CommandType == NCommandType::kInfo)
{
}
else
- ThrowUserErrorException();
- options.WildcardCensor.ExtendExclude();
+ throw 815676711; // FIXME 9815676711;
}
diff --git a/src/libs/7zip/unix/CPP/7zip/UI/Common/ArchiveCommandLine.h b/src/libs/7zip/unix/CPP/7zip/UI/Common/ArchiveCommandLine.h
index bc7a99b0d..255e12c3c 100644
--- a/src/libs/7zip/unix/CPP/7zip/UI/Common/ArchiveCommandLine.h
+++ b/src/libs/7zip/unix/CPP/7zip/UI/Common/ArchiveCommandLine.h
@@ -3,15 +3,16 @@
#ifndef __ARCHIVE_COMMAND_LINE_H
#define __ARCHIVE_COMMAND_LINE_H
-#include "Common/CommandLineParser.h"
-#include "Common/Wildcard.h"
+#include "../../../Common/CommandLineParser.h"
+#include "../../../Common/Wildcard.h"
#include "Extract.h"
+#include "HashCalc.h"
#include "Update.h"
-struct CArchiveCommandLineException: public AString
+struct CArcCmdLineException: public UString
{
- CArchiveCommandLineException(const char *errorMessage): AString(errorMessage) {}
+ CArcCmdLineException(const char *a, const wchar_t *u = NULL);
};
namespace NCommandType { enum EEnum
@@ -21,35 +22,33 @@ namespace NCommandType { enum EEnum
kDelete,
kTest,
kExtract,
- kFullExtract,
+ kExtractFull,
kList,
kBenchmark,
- kInfo
+ kInfo,
+ kHash,
+ kRename
};}
-namespace NRecursedType { enum EEnum
-{
- kRecursed,
- kWildCardOnlyRecursed,
- kNonRecursed
-};}
-
-struct CArchiveCommand
+struct CArcCommand
{
NCommandType::EEnum CommandType;
+
bool IsFromExtractGroup() const;
bool IsFromUpdateGroup() const;
- bool IsTestMode() const { return CommandType == NCommandType::kTest; }
+ bool IsTestCommand() const { return CommandType == NCommandType::kTest; }
NExtract::NPathMode::EEnum GetPathMode() const;
};
-struct CArchiveCommandLineOptions
+struct CArcCmdLineOptions
{
bool HelpMode;
#ifdef _7ZIP_LARGE_PAGES
bool LargePages;
#endif
+ bool CaseSensitiveChange;
+ bool CaseSensitive;
bool IsInTerminal;
bool IsStdOutTerminal;
@@ -60,10 +59,9 @@ struct CArchiveCommandLineOptions
bool YesToAll;
bool ShowDialog;
- // NWildcard::CCensor ArchiveWildcardCensor;
- NWildcard::CCensor WildcardCensor;
+ NWildcard::CCensor Censor;
- CArchiveCommand Command;
+ CArcCommand Command;
UString ArchiveName;
#ifndef _NO_CRYPTO
@@ -72,39 +70,52 @@ struct CArchiveCommandLineOptions
#endif
bool TechMode;
- // Extract
- bool CalcCrc;
+
+ UStringVector HashMethods;
+
bool AppendName;
- UString OutputDir;
- NExtract::NOverwriteMode::EEnum OverwriteMode;
UStringVector ArchivePathsSorted;
UStringVector ArchivePathsFullSorted;
- CObjectVector<CProperty> ExtractProperties;
+ CObjectVector<CProperty> Properties;
+
+ CExtractOptionsBase ExtractOptions;
+
+ CBoolPair NtSecurity;
+ CBoolPair AltStreams;
+ CBoolPair HardLinks;
+ CBoolPair SymLinks;
CUpdateOptions UpdateOptions;
+ CHashOptions HashOptions;
UString ArcType;
+ UStringVector ExcludedArcTypes;
bool EnablePercents;
// Benchmark
UInt32 NumIterations;
- UInt32 NumThreads;
- UInt32 DictionarySize;
- UString Method;
-
- CArchiveCommandLineOptions(): StdInMode(false), StdOutMode(false) {};
+ CArcCmdLineOptions():
+ StdInMode(false),
+ StdOutMode(false),
+ CaseSensitiveChange(false),
+ CaseSensitive(false)
+ {};
};
-class CArchiveCommandLineParser
+class CArcCmdLineParser
{
NCommandLineParser::CParser parser;
public:
- CArchiveCommandLineParser();
- void Parse1(const UStringVector &commandStrings, CArchiveCommandLineOptions &options);
- void Parse2(CArchiveCommandLineOptions &options);
+ CArcCmdLineParser();
+ void Parse1(const UStringVector &commandStrings, CArcCmdLineOptions &options);
+ void Parse2(CArcCmdLineOptions &options);
};
-void EnumerateDirItemsAndSort(NWildcard::CCensor &wildcardCensor,
+void EnumerateDirItemsAndSort(
+ bool storeAltStreams,
+ NWildcard::CCensor &censor,
+ NWildcard::ECensorPathMode pathMode,
+ const UString &addPathPrefix,
UStringVector &sortedPaths,
UStringVector &sortedFullPaths);
diff --git a/src/libs/7zip/unix/CPP/7zip/UI/Common/ArchiveExtractCallback.cpp b/src/libs/7zip/unix/CPP/7zip/UI/Common/ArchiveExtractCallback.cpp
index 4c0cc90b5..250f66797 100644
--- a/src/libs/7zip/unix/CPP/7zip/UI/Common/ArchiveExtractCallback.cpp
+++ b/src/libs/7zip/unix/CPP/7zip/UI/Common/ArchiveExtractCallback.cpp
@@ -2,40 +2,200 @@
#include "StdAfx.h"
-#include "Common/ComTry.h"
-#include "Common/Wildcard.h"
+#undef sprintf
+#undef printf
-#include "Windows/FileDir.h"
-#include "Windows/FileFind.h"
-#include "Windows/PropVariant.h"
-#include "Windows/PropVariantConversions.h"
+#include "../../../Common/ComTry.h"
+#include "../../../Common/StringConvert.h"
+#include "../../../Common/Wildcard.h"
+
+#include "../../../Windows/FileDir.h"
+#include "../../../Windows/FileFind.h"
+#include "../../../Windows/FileName.h"
+#include "../../../Windows/PropVariant.h"
+#include "../../../Windows/PropVariantConv.h"
+
+#if defined(_WIN32) && !defined(UNDER_CE) && !defined(_SFX)
+#define _USE_SECURITY_CODE
+#include "../../../Windows/SecurityUtils.h"
+#endif
#include "../../Common/FilePathAutoRename.h"
#include "../Common/ExtractingFilePath.h"
+#include "../Common/PropIDUtils.h"
#include "ArchiveExtractCallback.h"
using namespace NWindows;
+using namespace NFile;
+using namespace NDir;
+
+static const char *kCantAutoRename = "Can not create file with auto name";
+static const char *kCantRenameFile = "Can not rename existing file";
+static const char *kCantDeleteOutputFile = "Can not delete output file";
+static const char *kCantDeleteOutputDir = "Can not delete output folder";
+
+
+#ifndef _SFX
+
+STDMETHODIMP COutStreamWithHash::Write(const void *data, UInt32 size, UInt32 *processedSize)
+{
+ HRESULT result = S_OK;
+ if (_stream)
+ result = _stream->Write(data, size, &size);
+ if (_calculate)
+ _hash->Update(data, size);
+ _size += size;
+ if (processedSize)
+ *processedSize = size;
+ return result;
+}
+
+#endif
+
+#ifdef _USE_SECURITY_CODE
+bool InitLocalPrivileges()
+{
+ NSecurity::CAccessToken token;
+ if (!token.OpenProcessToken(GetCurrentProcess(),
+ TOKEN_QUERY | TOKEN_ADJUST_PRIVILEGES))
+ return false;
-static const wchar_t *kCantAutoRename = L"ERROR: Can not create file with auto name";
-static const wchar_t *kCantRenameFile = L"ERROR: Can not rename existing file ";
-static const wchar_t *kCantDeleteOutputFile = L"ERROR: Can not delete output file ";
+ TOKEN_PRIVILEGES tp;
+
+ tp.PrivilegeCount = 1;
+ tp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
+
+ if (!::LookupPrivilegeValue(NULL, SE_SECURITY_NAME, &tp.Privileges[0].Luid))
+ return false;
+ if (!token.AdjustPrivileges(&tp))
+ return false;
+ return (GetLastError() == ERROR_SUCCESS);
+}
+#endif
+
+#ifdef SUPPORT_LINKS
+
+int CHardLinkNode::Compare(const CHardLinkNode &a) const
+{
+ if (StreamId < a.StreamId) return -1;
+ if (StreamId > a.StreamId) return 1;
+ return MyCompare(INode, a.INode);
+}
+
+HRESULT Archive_Get_HardLinkNode(IInArchive *archive, UInt32 index, CHardLinkNode &h, bool &defined)
+{
+ h.INode = 0;
+ h.StreamId = (UInt64)(Int64)-1;
+ defined = false;
+ {
+ NCOM::CPropVariant prop;
+ RINOK(archive->GetProperty(index, kpidINode, &prop));
+ if (!ConvertPropVariantToUInt64(prop, h.INode))
+ return S_OK;
+ }
+ {
+ NCOM::CPropVariant prop;
+ RINOK(archive->GetProperty(index, kpidStreamId, &prop));
+ ConvertPropVariantToUInt64(prop, h.StreamId);
+ }
+ defined = true;
+ return S_OK;
+}
+
+
+HRESULT CArchiveExtractCallback::PrepareHardLinks(const CRecordVector<UInt32> *realIndices)
+{
+ _hardLinks.Clear();
+
+ if (!_arc->Ask_INode)
+ return S_OK;
+
+ IInArchive *archive = _arc->Archive;
+ CRecordVector<CHardLinkNode> &hardIDs = _hardLinks.IDs;
+
+ {
+ UInt32 numItems;
+ if (realIndices)
+ numItems = realIndices->Size();
+ else
+ {
+ RINOK(archive->GetNumberOfItems(&numItems));
+ }
+
+ for (UInt32 i = 0; i < numItems; i++)
+ {
+ CHardLinkNode h;
+ bool defined;
+ RINOK(Archive_Get_HardLinkNode(archive, realIndices ? (*realIndices)[i] : i, h, defined));
+ if (defined)
+ hardIDs.Add(h);
+ }
+ }
+
+ hardIDs.Sort2();
+
+ {
+ // wee keep only items that have 2 or more items
+ unsigned k = 0;
+ unsigned numSame = 1;
+ for (unsigned i = 1; i < hardIDs.Size(); i++)
+ {
+ if (hardIDs[i].Compare(hardIDs[i - 1]) != 0)
+ numSame = 1;
+ else if (++numSame == 2)
+ {
+ if (i - 1 != k)
+ hardIDs[k] = hardIDs[i - 1];
+ k++;
+ }
+ }
+ hardIDs.DeleteFrom(k);
+ }
+
+ _hardLinks.PrepareLinks();
+ return S_OK;
+}
+
+#endif
+
+CArchiveExtractCallback::CArchiveExtractCallback():
+ WriteCTime(true),
+ WriteATime(true),
+ WriteMTime(true),
+ _multiArchives(false)
+{
+ LocalProgressSpec = new CLocalProgress();
+ _localProgress = LocalProgressSpec;
+
+ #ifdef _USE_SECURITY_CODE
+ _saclEnabled = InitLocalPrivileges();
+ #endif
+}
void CArchiveExtractCallback::Init(
+ const CExtractNtOptions &ntOptions,
const NWildcard::CCensorNode *wildcardCensor,
const CArc *arc,
IFolderArchiveExtractCallback *extractCallback2,
- bool stdOutMode, bool testMode, bool crcMode,
- const UString &directoryPath,
+ bool stdOutMode, bool testMode,
+ const FString &directoryPath,
const UStringVector &removePathParts,
UInt64 packSize)
{
+ _extractedFolderPaths.Clear();
+ _extractedFolderIndices.Clear();
+
+ #ifdef SUPPORT_LINKS
+ _hardLinks.Clear();
+ #endif
+
+ _ntOptions = ntOptions;
_wildcardCensor = wildcardCensor;
_stdOutMode = stdOutMode;
_testMode = testMode;
- _crcMode = crcMode;
_unpTotal = 1;
_packTotal = packSize;
@@ -43,14 +203,31 @@ void CArchiveExtractCallback::Init(
_compressProgress.Release();
_extractCallback2.QueryInterface(IID_ICompressProgressInfo, &_compressProgress);
+ #ifndef _SFX
+
+ _extractCallback2.QueryInterface(IID_IFolderExtractToStreamCallback, &ExtractToStreamCallback);
+ if (ExtractToStreamCallback)
+ {
+ Int32 useStreams = 0;
+ if (ExtractToStreamCallback->UseExtractToStream(&useStreams) != S_OK)
+ useStreams = 0;
+ if (useStreams == 0)
+ ExtractToStreamCallback.Release();
+ }
+
+ #endif
+
LocalProgressSpec->Init(extractCallback2, true);
LocalProgressSpec->SendProgress = false;
-
_removePathParts = removePathParts;
+ _baseParentFolder = (UInt32)(Int32)-1;
+ _use_baseParentFolder_mode = false;
+
_arc = arc;
_directoryPath = directoryPath;
- NFile::NName::NormalizeDirPathPrefix(_directoryPath);
+ NName::NormalizeDirPathPrefix(_directoryPath);
+ NDir::MyGetFullPathName(directoryPath, _directoryPathFull);
}
STDMETHODIMP CArchiveExtractCallback::SetTotal(UInt64 size)
@@ -107,15 +284,48 @@ STDMETHODIMP CArchiveExtractCallback::SetRatioInfo(const UInt64 *inSize, const U
COM_TRY_END
}
-void CArchiveExtractCallback::CreateComplexDirectory(const UStringVector &dirPathParts, UString &fullPath)
+#define IS_LETTER_CHAR(c) ((c) >= 'a' && (c) <= 'z' || (c) >= 'A' && (c) <= 'Z')
+
+static inline bool IsDriveName(const UString &s)
{
- fullPath = _directoryPath;
- for (int i = 0; i < dirPathParts.Size(); i++)
+ return s.Len() == 2 && s[1] == ':' && IS_LETTER_CHAR(s[0]);
+}
+
+void CArchiveExtractCallback::CreateComplexDirectory(const UStringVector &dirPathParts, FString &fullPath)
+{
+ bool isAbsPath = false;
+
+ if (!dirPathParts.IsEmpty())
+ {
+ const UString &s = dirPathParts[0];
+ if (s.IsEmpty())
+ isAbsPath = true;
+ #ifdef _WIN32
+ else
+ {
+ if (dirPathParts.Size() > 1 && IsDriveName(s))
+ isAbsPath = true;
+ }
+ #endif
+ }
+
+ if (_pathMode == NExtract::NPathMode::kAbsPaths && isAbsPath)
+ fullPath.Empty();
+ else
+ fullPath = _directoryPath;
+
+ FOR_VECTOR (i, dirPathParts)
{
if (i > 0)
- fullPath += wchar_t(NFile::NName::kDirDelimiter);
- fullPath += dirPathParts[i];
- NFile::NDirectory::MyCreateDirectory(fullPath);
+ fullPath += FCHAR_PATH_SEPARATOR;
+ const UString &s = dirPathParts[i];
+ fullPath += us2fs(s);
+ #ifdef _WIN32
+ if (_pathMode == NExtract::NPathMode::kAbsPaths)
+ if (i == 0 && IsDriveName(s))
+ continue;
+ #endif
+ CreateDir(fullPath);
}
}
@@ -136,23 +346,100 @@ HRESULT CArchiveExtractCallback::GetTime(int index, PROPID propID, FILETIME &fil
HRESULT CArchiveExtractCallback::GetUnpackSize()
{
- NCOM::CPropVariant prop;
- RINOK(_arc->Archive->GetProperty(_index, kpidSize, &prop));
- _curSizeDefined = (prop.vt != VT_EMPTY);
- if (_curSizeDefined)
- _curSize = ConvertPropVariantToUInt64(prop);
- return S_OK;
+ return _arc->GetItemSize(_index, _curSize, _curSizeDefined);
}
+HRESULT CArchiveExtractCallback::SendMessageError(const char *message, const FString &path)
+{
+ return _extractCallback2->MessageError(
+ UString(L"ERROR: ") +
+ GetUnicodeString(message) + L": " + fs2us(path));
+}
+
+HRESULT CArchiveExtractCallback::SendMessageError2(const char *message, const FString &path1, const FString &path2)
+{
+ return _extractCallback2->MessageError(
+ UString(L"ERROR: ") +
+ GetUnicodeString(message) + UString(L": ") + fs2us(path1) + UString(L" : ") + fs2us(path2));
+}
+
+#ifndef _SFX
+
+STDMETHODIMP CGetProp::GetProp(PROPID propID, PROPVARIANT *value)
+{
+ if (propID == kpidName)
+ {
+ COM_TRY_BEGIN
+ NCOM::CPropVariant prop = Name.Ptr();
+ prop.Detach(value);
+ return S_OK;
+ COM_TRY_END
+ }
+ return Arc->Archive->GetProperty(IndexInArc, propID, value);
+}
+
+#endif
+
+
+#ifdef SUPPORT_LINKS
+
+static UString GetDirPrefixOf(const UString &src)
+{
+ UString s = src;
+ if (!s.IsEmpty())
+ {
+ if (s.Back() == WCHAR_PATH_SEPARATOR)
+ s.DeleteBack();
+ int pos = s.ReverseFind(WCHAR_PATH_SEPARATOR);
+ s.DeleteFrom(pos + 1);
+ }
+ return s;
+}
+
+static bool IsSafePath(const UString &path)
+{
+ UStringVector parts;
+ SplitPathToParts(path, parts);
+ int level = 0;
+ FOR_VECTOR(i, parts)
+ {
+ const UString &s = parts[i];
+ if (s.IsEmpty())
+ continue;
+ if (s == L".")
+ continue;
+ if (s == L"..")
+ {
+ if (level <= 0)
+ return false;
+ level--;
+ }
+ else
+ level++;
+ }
+ return level > 0;
+}
+
+#endif
+
+
STDMETHODIMP CArchiveExtractCallback::GetStream(UInt32 index, ISequentialOutStream **outStream, Int32 askExtractMode)
{
COM_TRY_BEGIN
- _crcStream.Release();
+
*outStream = 0;
+
+ #ifndef _SFX
+ if (_hashStream)
+ _hashStreamSpec->ReleaseStream();
+ _hashStreamWasUsed = false;
+ #endif
+
_outFileStream.Release();
_encrypted = false;
_isSplit = false;
+ _isAltStream = false;
_curSize = 0;
_curSizeDefined = false;
_index = index;
@@ -161,7 +448,7 @@ STDMETHODIMP CArchiveExtractCallback::GetStream(UInt32 index, ISequentialOutStre
IInArchive *archive = _arc->Archive;
RINOK(_arc->GetItemPath(index, fullPath));
- RINOK(IsArchiveItemFolder(archive, index, _fi.IsDir));
+ RINOK(Archive_IsItem_Folder(archive, index, _fi.IsDir));
_filePath = fullPath;
@@ -176,26 +463,220 @@ STDMETHODIMP CArchiveExtractCallback::GetStream(UInt32 index, ISequentialOutStre
_isSplit = true;
}
}
-
- RINOK(GetArchiveItemBoolProp(archive, index, kpidEncrypted, _encrypted));
+
+ #ifdef SUPPORT_LINKS
+
+ bool isHardLink = false;
+ bool isJunction = false;
+ bool isRelative = false;
+
+ UString linkPath;
+ // RINOK(Archive_GetItemBoolProp(archive, index, kpidIsHardLink, isHardLink));
+ // if (isHardLink)
+ {
+ NCOM::CPropVariant prop;
+ RINOK(archive->GetProperty(index, kpidHardLink, &prop));
+ if (prop.vt == VT_BSTR)
+ {
+ isHardLink = true;
+ linkPath = prop.bstrVal;
+ isRelative = false; // TAR: hard links are from root folder of archive
+ }
+ else if (prop.vt == VT_EMPTY)
+ {
+ // linkPath.Empty();
+ }
+ else
+ return E_FAIL;
+ }
+ {
+ NCOM::CPropVariant prop;
+ RINOK(archive->GetProperty(index, kpidSymLink, &prop));
+ if (prop.vt == VT_BSTR)
+ {
+ isHardLink = false;
+ linkPath = prop.bstrVal;
+ isRelative = true; // TAR: symbolic links are relative
+ }
+ else if (prop.vt == VT_EMPTY)
+ {
+ // linkPath.Empty();
+ }
+ else
+ return E_FAIL;
+ }
+
+ bool isOkReparse = false;
+
+ if (linkPath.IsEmpty() && _arc->GetRawProps)
+ {
+ const void *data;
+ UInt32 dataSize;
+ UInt32 propType;
+ _arc->GetRawProps->GetRawProp(_index, kpidNtReparse, &data, &dataSize, &propType);
+ if (dataSize != 0)
+ {
+ if (propType != NPropDataType::kRaw)
+ return E_FAIL;
+ UString s;
+ CReparseAttr reparse;
+ isOkReparse = reparse.Parse((const Byte *)data, dataSize);
+ if (isOkReparse)
+ {
+ isHardLink = false;
+ linkPath = reparse.GetPath();
+ isJunction = reparse.IsMountPoint();
+ isRelative = reparse.IsRelative();
+ #ifndef _WIN32
+ linkPath.Replace(WCHAR_PATH_SEPARATOR, '/', );
+ #endif
+ }
+ }
+ }
+
+ if (!linkPath.IsEmpty())
+ {
+ #ifdef _WIN32
+ linkPath.Replace('/', WCHAR_PATH_SEPARATOR);
+ #endif
+
+ for (;;)
+ // while (NName::IsAbsolutePath(linkPath))
+ {
+ unsigned n = NName::GetRootPrefixSize(linkPath);
+ if (n == 0)
+ break;
+ isRelative = false;
+ linkPath.DeleteFrontal(n);
+ }
+ }
+
+ if (!linkPath.IsEmpty() && !isRelative && _removePathParts.Size() != 0)
+ {
+ UStringVector pathParts;
+ SplitPathToParts(linkPath, pathParts);
+ bool badPrefix = false;
+ FOR_VECTOR (i, _removePathParts)
+ {
+ if (CompareFileNames(_removePathParts[i], pathParts[i]) != 0)
+ {
+ badPrefix = true;
+ break;
+ }
+ }
+ if (!badPrefix)
+ pathParts.DeleteFrontal(_removePathParts.Size());
+ linkPath = MakePathNameFromParts(pathParts);
+ }
+
+ #endif
+
+ RINOK(Archive_GetItemBoolProp(archive, index, kpidEncrypted, _encrypted));
RINOK(GetUnpackSize());
+ RINOK(Archive_IsItem_AltStream(archive, index, _isAltStream));
+
+ if (!_ntOptions.AltStreams.Val && _isAltStream)
+ return S_OK;
+
if (_wildcardCensor)
{
- if (!_wildcardCensor->CheckPath(fullPath, !_fi.IsDir))
+ if (!_wildcardCensor->CheckPath(_isAltStream, fullPath, !_fi.IsDir))
return S_OK;
}
- if (askExtractMode == NArchive::NExtract::NAskMode::kExtract && !_testMode)
+
+ UStringVector pathParts;
+
+ if (_use_baseParentFolder_mode)
+ {
+ int baseParent = _baseParentFolder;
+ if (_pathMode == NExtract::NPathMode::kFullPaths ||
+ _pathMode == NExtract::NPathMode::kAbsPaths)
+ baseParent = -1;
+ RINOK(_arc->GetItemPathToParent(index, baseParent, pathParts));
+ if (_pathMode == NExtract::NPathMode::kNoPaths && !pathParts.IsEmpty())
+ pathParts.DeleteFrontal(pathParts.Size() - 1);
+ }
+ else
+ {
+ SplitPathToParts(fullPath, pathParts);
+
+ if (pathParts.IsEmpty())
+ return E_FAIL;
+ unsigned numRemovePathParts = 0;
+
+ switch (_pathMode)
+ {
+ case NExtract::NPathMode::kCurPaths:
+ {
+ bool badPrefix = false;
+ if (pathParts.Size() <= _removePathParts.Size())
+ badPrefix = true;
+ else
+ {
+ FOR_VECTOR (i, _removePathParts)
+ {
+ if (!_removePathParts[i].IsEqualToNoCase(pathParts[i]))
+ {
+ badPrefix = true;
+ break;
+ }
+ }
+ }
+ if (badPrefix)
+ {
+ if (askExtractMode == NArchive::NExtract::NAskMode::kExtract && !_testMode)
+ return E_FAIL;
+ }
+ else
+ numRemovePathParts = _removePathParts.Size();
+ break;
+ }
+ case NExtract::NPathMode::kNoPaths:
+ {
+ numRemovePathParts = pathParts.Size() - 1;
+ break;
+ }
+ /*
+ case NExtract::NPathMode::kFullPaths:
+ case NExtract::NPathMode::kAbsPaths:
+ break;
+ */
+ }
+
+ pathParts.DeleteFrontal(numRemovePathParts);
+ }
+
+ #ifndef _SFX
+
+ if (ExtractToStreamCallback)
{
- if (_stdOutMode)
+ if (!GetProp)
{
- CMyComPtr<ISequentialOutStream> outStreamLoc = new CStdOutFileStream;
- *outStream = outStreamLoc.Detach();
- return S_OK;
+ GetProp_Spec = new CGetProp;
+ GetProp = GetProp_Spec;
}
+ GetProp_Spec->Arc = _arc;
+ GetProp_Spec->IndexInArc = index;
+ GetProp_Spec->Name = MakePathNameFromParts(pathParts);
+
+ return ExtractToStreamCallback->GetStream7(GetProp_Spec->Name, _fi.IsDir, outStream, askExtractMode, GetProp);
+ }
+
+ #endif
+ CMyComPtr<ISequentialOutStream> outStreamLoc;
+
+if (askExtractMode == NArchive::NExtract::NAskMode::kExtract && !_testMode)
+{
+ if (_stdOutMode)
+ {
+ outStreamLoc = new CStdOutFileStream;
+ }
+ else
+ {
{
NCOM::CPropVariant prop;
RINOK(archive->GetProperty(index, kpidAttrib, &prop));
@@ -217,35 +698,15 @@ STDMETHODIMP CArchiveExtractCallback::GetStream(UInt32 index, ISequentialOutStre
bool isAnti = false;
RINOK(_arc->IsItemAnti(index, isAnti));
- UStringVector pathParts;
- SplitPathToParts(fullPath, pathParts);
-
- if (pathParts.IsEmpty())
- return E_FAIL;
- int numRemovePathParts = 0;
- switch(_pathMode)
- {
- case NExtract::NPathMode::kFullPathnames:
- break;
- case NExtract::NPathMode::kCurrentPathnames:
- {
- numRemovePathParts = _removePathParts.Size();
- if (pathParts.Size() <= numRemovePathParts)
- return E_FAIL;
- for (int i = 0; i < numRemovePathParts; i++)
- if (_removePathParts[i].CompareNoCase(pathParts[i]) != 0)
- return E_FAIL;
- break;
- }
- case NExtract::NPathMode::kNoPathnames:
- {
- numRemovePathParts = pathParts.Size() - 1;
- break;
- }
- }
- pathParts.Delete(0, numRemovePathParts);
- MakeCorrectPath(pathParts);
+ bool replace = _isAltStream ?
+ _ntOptions.ReplaceColonForAltStream :
+ !_ntOptions.WriteToAltStreamIfColon;
+
+ if (_pathMode != NExtract::NPathMode::kAbsPaths)
+ MakeCorrectPath(_directoryPath.IsEmpty(), pathParts, replace);
+ Correct_IfEmptyLastPart(pathParts);
UString processedPath = MakePathNameFromParts(pathParts);
+
if (!isAnti)
{
if (!_fi.IsDir)
@@ -253,142 +714,273 @@ STDMETHODIMP CArchiveExtractCallback::GetStream(UInt32 index, ISequentialOutStre
if (!pathParts.IsEmpty())
pathParts.DeleteBack();
}
-
+
if (!pathParts.IsEmpty())
{
- UString fullPathNew;
+ FString fullPathNew;
CreateComplexDirectory(pathParts, fullPathNew);
if (_fi.IsDir)
- NFile::NDirectory::SetDirTime(fullPathNew,
+ {
+ _extractedFolderPaths.Add(fullPathNew);
+ _extractedFolderIndices.Add(index);
+ SetDirTime(fullPathNew,
(WriteCTime && _fi.CTimeDefined) ? &_fi.CTime : NULL,
(WriteATime && _fi.ATimeDefined) ? &_fi.ATime : NULL,
(WriteMTime && _fi.MTimeDefined) ? &_fi.MTime : (_arc->MTimeDefined ? &_arc->MTime : NULL));
+ }
}
}
- UString fullProcessedPath = _directoryPath + processedPath;
+ FString fullProcessedPath = us2fs(processedPath);
+ if (_pathMode != NExtract::NPathMode::kAbsPaths ||
+ !NName::IsAbsolutePath(processedPath))
+ fullProcessedPath = _directoryPath + fullProcessedPath;
if (_fi.IsDir)
{
_diskFilePath = fullProcessedPath;
if (isAnti)
- NFile::NDirectory::MyRemoveDirectory(_diskFilePath);
- return S_OK;
+ RemoveDir(_diskFilePath);
+ #ifdef SUPPORT_LINKS
+ if (linkPath.IsEmpty())
+ #endif
+ return S_OK;
}
-
- if (!_isSplit)
+ else if (!_isSplit)
{
- NFile::NFind::CFileInfoW fileInfo;
+ NFind::CFileInfo fileInfo;
if (fileInfo.Find(fullProcessedPath))
{
- switch(_overwriteMode)
+ switch (_overwriteMode)
{
- case NExtract::NOverwriteMode::kSkipExisting:
+ case NExtract::NOverwriteMode::kSkip:
return S_OK;
- case NExtract::NOverwriteMode::kAskBefore:
+ case NExtract::NOverwriteMode::kAsk:
{
+ int slashPos = fullProcessedPath.ReverseFind(FTEXT('/'));
+ #ifdef _WIN32
+ int slash1Pos = fullProcessedPath.ReverseFind(FTEXT('\\'));
+ slashPos = MyMax(slashPos, slash1Pos);
+ #endif
+ FString realFullProcessedPath = fullProcessedPath.Left(slashPos + 1) + fileInfo.Name;
+
Int32 overwiteResult;
RINOK(_extractCallback2->AskOverwrite(
- fullProcessedPath, &fileInfo.MTime, &fileInfo.Size, fullPath,
+ fs2us(realFullProcessedPath), &fileInfo.MTime, &fileInfo.Size, fullPath,
_fi.MTimeDefined ? &_fi.MTime : NULL,
_curSizeDefined ? &_curSize : NULL,
&overwiteResult))
- switch(overwiteResult)
+ switch (overwiteResult)
{
- case NOverwriteAnswer::kCancel:
- return E_ABORT;
- case NOverwriteAnswer::kNo:
- return S_OK;
- case NOverwriteAnswer::kNoToAll:
- _overwriteMode = NExtract::NOverwriteMode::kSkipExisting;
- return S_OK;
- case NOverwriteAnswer::kYesToAll:
- _overwriteMode = NExtract::NOverwriteMode::kWithoutPrompt;
- break;
- case NOverwriteAnswer::kYes:
- break;
- case NOverwriteAnswer::kAutoRename:
- _overwriteMode = NExtract::NOverwriteMode::kAutoRename;
- break;
+ case NOverwriteAnswer::kCancel: return E_ABORT;
+ case NOverwriteAnswer::kNo: return S_OK;
+ case NOverwriteAnswer::kNoToAll: _overwriteMode = NExtract::NOverwriteMode::kSkip; return S_OK;
+ case NOverwriteAnswer::kYes: break;
+ case NOverwriteAnswer::kYesToAll: _overwriteMode = NExtract::NOverwriteMode::kOverwrite; break;
+ case NOverwriteAnswer::kAutoRename: _overwriteMode = NExtract::NOverwriteMode::kRename; break;
default:
return E_FAIL;
}
}
}
- if (_overwriteMode == NExtract::NOverwriteMode::kAutoRename)
+ if (_overwriteMode == NExtract::NOverwriteMode::kRename)
{
if (!AutoRenamePath(fullProcessedPath))
{
- UString message = UString(kCantAutoRename) + fullProcessedPath;
- RINOK(_extractCallback2->MessageError(message));
+ RINOK(SendMessageError(kCantAutoRename, fullProcessedPath));
return E_FAIL;
}
}
- else if (_overwriteMode == NExtract::NOverwriteMode::kAutoRenameExisting)
+ else if (_overwriteMode == NExtract::NOverwriteMode::kRenameExisting)
{
- UString existPath = fullProcessedPath;
+ FString existPath = fullProcessedPath;
if (!AutoRenamePath(existPath))
{
- UString message = kCantAutoRename + fullProcessedPath;
- RINOK(_extractCallback2->MessageError(message));
+ RINOK(SendMessageError(kCantAutoRename, fullProcessedPath));
return E_FAIL;
}
- if (!NFile::NDirectory::MyMoveFile(fullProcessedPath, existPath))
+ // MyMoveFile can raname folders. So it's OK to use it folders too
+ if (!MyMoveFile(fullProcessedPath, existPath))
{
- UString message = UString(kCantRenameFile) + fullProcessedPath;
- RINOK(_extractCallback2->MessageError(message));
+ RINOK(SendMessageError(kCantRenameFile, fullProcessedPath));
return E_FAIL;
}
}
else
- if (!NFile::NDirectory::DeleteFileAlways(fullProcessedPath))
+ {
+ if (fileInfo.IsDir())
{
- UString message = UString(kCantDeleteOutputFile) + fullProcessedPath;
- RINOK(_extractCallback2->MessageError(message));
+ // do we need to delete all files in folder?
+ if (!RemoveDir(fullProcessedPath))
+ {
+ RINOK(SendMessageError(kCantDeleteOutputDir, fullProcessedPath));
+ return S_OK;
+ }
+ }
+ else if (!DeleteFileAlways(fullProcessedPath))
+ {
+ RINOK(SendMessageError(kCantDeleteOutputFile, fullProcessedPath));
return S_OK;
// return E_FAIL;
}
+ }
}
}
+ _diskFilePath = fullProcessedPath;
+
+
if (!isAnti)
{
- _outFileStreamSpec = new COutFileStream;
- CMyComPtr<ISequentialOutStream> outStreamLoc(_outFileStreamSpec);
- if (!_outFileStreamSpec->Open(fullProcessedPath, _isSplit ? OPEN_ALWAYS: CREATE_ALWAYS))
+ #ifdef SUPPORT_LINKS
+
+ if (!linkPath.IsEmpty())
{
- // if (::GetLastError() != ERROR_FILE_EXISTS || !isSplit)
+ #ifndef UNDER_CE
+
+ UString relatPath;
+ if (isRelative)
+ relatPath = GetDirPrefixOf(_filePath);
+ relatPath += linkPath;
+
+ if (!IsSafePath(relatPath))
{
- UString message = L"can not open output file " + fullProcessedPath;
- RINOK(_extractCallback2->MessageError(message));
- return S_OK;
+ RINOK(SendMessageError("Dangerous link path was ignored", us2fs(relatPath)));
}
+ else
+ {
+ FString existPath;
+ if (isHardLink || !isRelative)
+ {
+ if (!NName::GetFullPath(_directoryPathFull, us2fs(relatPath), existPath))
+ {
+ RINOK(SendMessageError("Incorrect path", us2fs(relatPath)));
+ }
+ }
+ else
+ {
+ existPath = us2fs(linkPath);
+ }
+
+ if (!existPath.IsEmpty())
+ {
+ if (isHardLink)
+ {
+ if (!MyCreateHardLink(fullProcessedPath, existPath))
+ {
+ RINOK(SendMessageError2("Can not create hard link", fullProcessedPath, existPath));
+ // return S_OK;
+ }
+ }
+ else if (_ntOptions.SymLinks.Val)
+ {
+ // bool isSymLink = true; // = false for junction
+ if (_fi.IsDir && !isRelative)
+ {
+ // if it's before Vista we use Junction Point
+ // isJunction = true;
+ // convertToAbs = true;
+ }
+
+ CByteBuffer data;
+ if (FillLinkData(data, fs2us(existPath), !isJunction))
+ {
+ CReparseAttr attr;
+ if (!attr.Parse(data, data.Size()))
+ {
+ return E_FAIL; // "Internal conversion error";
+ }
+
+ if (!NFile::NIO::SetReparseData(fullProcessedPath, _fi.IsDir, data, (DWORD)data.Size()))
+ {
+ RINOK(SendMessageError("Can not set reparse data", fullProcessedPath));
+ }
+ }
+ }
+ }
+ }
+
+ #endif
}
- if (_isSplit)
+ else
+ #endif // SUPPORT_LINKS
{
- RINOK(_outFileStreamSpec->Seek(_position, STREAM_SEEK_SET, NULL));
+ bool needWriteFile = true;
+
+ #ifdef SUPPORT_LINKS
+ if (!_hardLinks.IDs.IsEmpty())
+ {
+ CHardLinkNode h;
+ bool defined;
+ RINOK(Archive_Get_HardLinkNode(archive, index, h, defined));
+ if (defined)
+ {
+ {
+ int linkIndex = _hardLinks.IDs.FindInSorted2(h);
+ if (linkIndex >= 0)
+ {
+ FString &hl = _hardLinks.Links[linkIndex];
+ if (hl.IsEmpty())
+ hl = fullProcessedPath;
+ else
+ {
+ if (!MyCreateHardLink(fullProcessedPath, hl))
+ {
+ RINOK(SendMessageError2("Can not create hard link", fullProcessedPath, hl));
+ return S_OK;
+ }
+ needWriteFile = false;
+ }
+ }
+ }
+ }
+ }
+ #endif
+
+ if (needWriteFile)
+ {
+ _outFileStreamSpec = new COutFileStream;
+ CMyComPtr<ISequentialOutStream> outStreamLoc(_outFileStreamSpec);
+ if (!_outFileStreamSpec->Open(fullProcessedPath, _isSplit ? OPEN_ALWAYS: CREATE_ALWAYS))
+ {
+ // if (::GetLastError() != ERROR_FILE_EXISTS || !isSplit)
+ {
+ RINOK(SendMessageError("Can not open output file ", fullProcessedPath));
+ return S_OK;
+ }
+ }
+ if (_isSplit)
+ {
+ RINOK(_outFileStreamSpec->Seek(_position, STREAM_SEEK_SET, NULL));
+ }
+ _outFileStream = outStreamLoc;
+ }
}
- _outFileStream = outStreamLoc;
- *outStream = outStreamLoc.Detach();
}
- _diskFilePath = fullProcessedPath;
- }
- else
- {
- *outStream = NULL;
+
+ outStreamLoc = _outFileStream;
}
- if (_crcMode)
+}
+
+ #ifndef _SFX
+
+ if (_hashStream)
{
- _crcStreamSpec = new COutStreamWithCRC;
- _crcStream = _crcStreamSpec;
- CMyComPtr<ISequentialOutStream> crcStream = _crcStreamSpec;
- _crcStreamSpec->SetStream(*outStream);
- if (*outStream)
- (*outStream)->Release();
- *outStream = crcStream.Detach();
- _crcStreamSpec->Init(true);
+ if (askExtractMode == NArchive::NExtract::NAskMode::kExtract ||
+ askExtractMode == NArchive::NExtract::NAskMode::kTest)
+ {
+ _hashStreamSpec->SetStream(outStreamLoc);
+ outStreamLoc = _hashStream;
+ _hashStreamSpec->Init(true);
+ _hashStreamWasUsed = true;
+ }
}
+
+ #endif
+
+ if (outStreamLoc)
+ *outStream = outStreamLoc.Detach();
return S_OK;
COM_TRY_END
}
@@ -396,6 +988,12 @@ STDMETHODIMP CArchiveExtractCallback::GetStream(UInt32 index, ISequentialOutStre
STDMETHODIMP CArchiveExtractCallback::PrepareOperation(Int32 askExtractMode)
{
COM_TRY_BEGIN
+
+ #ifndef _SFX
+ if (ExtractToStreamCallback)
+ return ExtractToStreamCallback->PrepareOperation7(askExtractMode);
+ #endif
+
_extractMode = false;
switch (askExtractMode)
{
@@ -414,24 +1012,25 @@ STDMETHODIMP CArchiveExtractCallback::PrepareOperation(Int32 askExtractMode)
STDMETHODIMP CArchiveExtractCallback::SetOperationResult(Int32 operationResult)
{
COM_TRY_BEGIN
- switch(operationResult)
- {
- case NArchive::NExtract::NOperationResult::kOK:
- case NArchive::NExtract::NOperationResult::kUnSupportedMethod:
- case NArchive::NExtract::NOperationResult::kCRCError:
- case NArchive::NExtract::NOperationResult::kDataError:
- break;
- default:
- _outFileStream.Release();
- return E_FAIL;
- }
- if (_crcStream)
+
+ #ifndef _SFX
+ if (ExtractToStreamCallback)
+ return ExtractToStreamCallback->SetOperationResult7(operationResult, _encrypted);
+ #endif
+
+ #ifndef _SFX
+
+ if (_hashStreamWasUsed)
{
- CrcSum += _crcStreamSpec->GetCRC();
- _curSize = _crcStreamSpec->GetSize();
+ _hashStreamSpec->_hash->Final(_fi.IsDir, _isAltStream, _filePath);
+ _curSize = _hashStreamSpec->GetSize();
_curSizeDefined = true;
- _crcStream.Release();
+ _hashStreamSpec->ReleaseStream();
+ _hashStreamWasUsed = false;
}
+
+ #endif
+
if (_outFileStream)
{
_outFileStreamSpec->SetTime(
@@ -443,17 +1042,48 @@ STDMETHODIMP CArchiveExtractCallback::SetOperationResult(Int32 operationResult)
RINOK(_outFileStreamSpec->Close());
_outFileStream.Release();
}
+
+ #ifdef _USE_SECURITY_CODE
+ if (_ntOptions.NtSecurity.Val && _arc->GetRawProps)
+ {
+ const void *data;
+ UInt32 dataSize;
+ UInt32 propType;
+ _arc->GetRawProps->GetRawProp(_index, kpidNtSecure, &data, &dataSize, &propType);
+ if (dataSize != 0)
+ {
+ if (propType != NPropDataType::kRaw)
+ return E_FAIL;
+ if (CheckNtSecure((const Byte *)data, dataSize))
+ {
+ SECURITY_INFORMATION securInfo = DACL_SECURITY_INFORMATION | GROUP_SECURITY_INFORMATION | OWNER_SECURITY_INFORMATION;
+ if (_saclEnabled)
+ securInfo |= SACL_SECURITY_INFORMATION;
+ ::SetFileSecurityW(fs2us(_diskFilePath), securInfo, (PSECURITY_DESCRIPTOR)(void *)data);
+ }
+ }
+ }
+ #endif
+
if (!_curSizeDefined)
GetUnpackSize();
if (_curSizeDefined)
- UnpackSize += _curSize;
+ {
+ if (_isAltStream)
+ AltStreams_UnpackSize += _curSize;
+ else
+ UnpackSize += _curSize;
+ }
+
if (_fi.IsDir)
NumFolders++;
+ else if (_isAltStream)
+ NumAltStreams++;
else
NumFiles++;
if (_extractMode && _fi.AttribDefined)
- NFile::NDirectory::MySetFileAttributes(_diskFilePath, _fi.Attrib);
+ SetFileAttrib(_diskFilePath, _fi.Attrib);
RINOK(_extractCallback2->SetOperationResult(operationResult, _encrypted));
return S_OK;
COM_TRY_END
@@ -486,3 +1116,76 @@ STDMETHODIMP CArchiveExtractCallback::CryptoGetTextPassword(BSTR *password)
COM_TRY_END
}
+
+struct CExtrRefSortPair
+{
+ int Len;
+ int Index;
+
+ int Compare(const CExtrRefSortPair &a) const;
+};
+
+#define RINOZ(x) { int __tt = (x); if (__tt != 0) return __tt; }
+
+int CExtrRefSortPair::Compare(const CExtrRefSortPair &a) const
+{
+ RINOZ(-MyCompare(Len, a.Len));
+ return MyCompare(Index, a.Index);
+}
+
+static int GetNumSlashes(const FChar *s)
+{
+ for (int numSlashes = 0;;)
+ {
+ FChar c = *s++;
+ if (c == 0)
+ return numSlashes;
+ if (
+ #ifdef _WIN32
+ c == FTEXT('\\') ||
+ #endif
+ c == FTEXT('/'))
+ numSlashes++;
+ }
+}
+
+HRESULT CArchiveExtractCallback::SetDirsTimes()
+{
+ CRecordVector<CExtrRefSortPair> pairs;
+ pairs.ClearAndSetSize(_extractedFolderPaths.Size());
+ unsigned i;
+
+ for (i = 0; i < _extractedFolderPaths.Size(); i++)
+ {
+ CExtrRefSortPair &pair = pairs[i];
+ pair.Index = i;
+ pair.Len = GetNumSlashes(_extractedFolderPaths[i]);
+ }
+
+ pairs.Sort2();
+
+ for (i = 0; i < pairs.Size(); i++)
+ {
+ int pairIndex = pairs[i].Index;
+ int index = _extractedFolderIndices[pairIndex];
+
+ FILETIME CTime;
+ FILETIME ATime;
+ FILETIME MTime;
+
+ bool CTimeDefined;
+ bool ATimeDefined;
+ bool MTimeDefined;
+
+ RINOK(GetTime(index, kpidCTime, CTime, CTimeDefined));
+ RINOK(GetTime(index, kpidATime, ATime, ATimeDefined));
+ RINOK(GetTime(index, kpidMTime, MTime, MTimeDefined));
+
+ // printf("\n%S", _extractedFolderPaths[pairIndex]);
+ SetDirTime(_extractedFolderPaths[pairIndex],
+ (WriteCTime && CTimeDefined) ? &CTime : NULL,
+ (WriteATime && ATimeDefined) ? &ATime : NULL,
+ (WriteMTime && MTimeDefined) ? &MTime : (_arc->MTimeDefined ? &_arc->MTime : NULL));
+ }
+ return S_OK;
+}
diff --git a/src/libs/7zip/unix/CPP/7zip/UI/Common/ArchiveExtractCallback.h b/src/libs/7zip/unix/CPP/7zip/UI/Common/ArchiveExtractCallback.h
index 367e4b07d..374297651 100644
--- a/src/libs/7zip/unix/CPP/7zip/UI/Common/ArchiveExtractCallback.h
+++ b/src/libs/7zip/unix/CPP/7zip/UI/Common/ArchiveExtractCallback.h
@@ -3,8 +3,8 @@
#ifndef __ARCHIVE_EXTRACT_CALLBACK_H
#define __ARCHIVE_EXTRACT_CALLBACK_H
-#include "Common/MyCom.h"
-#include "Common/Wildcard.h"
+#include "../../../Common/MyCom.h"
+#include "../../../Common/Wildcard.h"
#include "../../IPassword.h"
@@ -13,12 +13,117 @@
#include "../../Archive/IArchive.h"
-#include "../../Archive/Common/OutStreamWithCRC.h"
-
#include "ExtractMode.h"
#include "IFileExtractCallback.h"
#include "OpenArchive.h"
+#include "HashCalc.h"
+
+#ifndef _SFX
+
+class COutStreamWithHash:
+ public ISequentialOutStream,
+ public CMyUnknownImp
+{
+ CMyComPtr<ISequentialOutStream> _stream;
+ UInt64 _size;
+ bool _calculate;
+public:
+ IHashCalc *_hash;
+
+ MY_UNKNOWN_IMP
+ STDMETHOD(Write)(const void *data, UInt32 size, UInt32 *processedSize);
+ void SetStream(ISequentialOutStream *stream) { _stream = stream; }
+ void ReleaseStream() { _stream.Release(); }
+ void Init(bool calculate = true)
+ {
+ InitCRC();
+ _size = 0;
+ _calculate = calculate;
+ }
+ void EnableCalc(bool calculate) { _calculate = calculate; }
+ void InitCRC() { _hash->InitForNewFile(); }
+ UInt64 GetSize() const { return _size; }
+};
+
+#endif
+
+struct CExtractNtOptions
+{
+ CBoolPair NtSecurity;
+ CBoolPair SymLinks;
+ CBoolPair HardLinks;
+ CBoolPair AltStreams;
+ bool ReplaceColonForAltStream;
+ bool WriteToAltStreamIfColon;
+
+ CExtractNtOptions():
+ ReplaceColonForAltStream(false),
+ WriteToAltStreamIfColon(false)
+ {
+ SymLinks.Val = true;
+ HardLinks.Val = true;
+ AltStreams.Val = true;
+ }
+};
+
+#ifndef _SFX
+
+class CGetProp:
+ public IGetProp,
+ public CMyUnknownImp
+{
+public:
+ const CArc *Arc;
+ UInt32 IndexInArc;
+ UString Name; // relative path
+
+ MY_UNKNOWN_IMP1(IGetProp)
+ INTERFACE_IGetProp(;)
+};
+
+#endif
+
+#ifndef _SFX
+#ifndef UNDER_CE
+
+// FIXME #define SUPPORT_LINKS
+
+#endif
+#endif
+
+
+#ifdef SUPPORT_LINKS
+
+struct CHardLinkNode
+{
+ UInt64 StreamId;
+ UInt64 INode;
+
+ int Compare(const CHardLinkNode &a) const;
+};
+
+class CHardLinks
+{
+public:
+ CRecordVector<CHardLinkNode> IDs;
+ CObjectVector<FString> Links;
+
+ void Clear()
+ {
+ IDs.Clear();
+ Links.Clear();
+ }
+
+ void PrepareLinks()
+ {
+ while (Links.Size() < IDs.Size())
+ Links.AddNew();
+ }
+};
+
+#endif
+
class CArchiveExtractCallback:
public IArchiveExtractCallback,
// public IArchiveVolumeExtractCallback,
@@ -27,18 +132,30 @@ class CArchiveExtractCallback:
public CMyUnknownImp
{
const CArc *_arc;
+ CExtractNtOptions _ntOptions;
+
const NWildcard::CCensorNode *_wildcardCensor;
CMyComPtr<IFolderArchiveExtractCallback> _extractCallback2;
CMyComPtr<ICompressProgressInfo> _compressProgress;
CMyComPtr<ICryptoGetTextPassword> _cryptoGetTextPassword;
- UString _directoryPath;
+ FString _directoryPath;
+ FString _directoryPathFull;
NExtract::NPathMode::EEnum _pathMode;
NExtract::NOverwriteMode::EEnum _overwriteMode;
- UString _diskFilePath;
+ #ifndef _SFX
+
+ CMyComPtr<IFolderExtractToStreamCallback> ExtractToStreamCallback;
+ CGetProp *GetProp_Spec;
+ CMyComPtr<IGetProp> GetProp;
+
+ #endif
+
+ FString _diskFilePath;
UString _filePath;
UInt64 _position;
bool _isSplit;
+ bool _isAltStream;
bool _extractMode;
@@ -54,7 +171,7 @@ class CArchiveExtractCallback:
FILETIME ATime;
FILETIME MTime;
UInt32 Attrib;
-
+
bool CTimeDefined;
bool ATimeDefined;
bool MTimeDefined;
@@ -69,33 +186,50 @@ class CArchiveExtractCallback:
COutFileStream *_outFileStreamSpec;
CMyComPtr<ISequentialOutStream> _outFileStream;
- COutStreamWithCRC *_crcStreamSpec;
- CMyComPtr<ISequentialOutStream> _crcStream;
+ #ifndef _SFX
+
+ COutStreamWithHash *_hashStreamSpec;
+ CMyComPtr<ISequentialOutStream> _hashStream;
+ bool _hashStreamWasUsed;
+
+ #endif
UStringVector _removePathParts;
+ bool _use_baseParentFolder_mode;
+ UInt32 _baseParentFolder;
bool _stdOutMode;
bool _testMode;
- bool _crcMode;
bool _multiArchives;
CMyComPtr<ICompressProgressInfo> _localProgress;
UInt64 _packTotal;
UInt64 _unpTotal;
- void CreateComplexDirectory(const UStringVector &dirPathParts, UString &fullPath);
+ FStringVector _extractedFolderPaths;
+ CRecordVector<UInt32> _extractedFolderIndices;
+
+ #if defined(_WIN32) && !defined(UNDER_CE) && !defined(_SFX)
+ bool _saclEnabled;
+ #endif
+
+ void CreateComplexDirectory(const UStringVector &dirPathParts, FString &fullPath);
HRESULT GetTime(int index, PROPID propID, FILETIME &filetime, bool &filetimeIsDefined);
HRESULT GetUnpackSize();
+ HRESULT SendMessageError(const char *message, const FString &path);
+ HRESULT SendMessageError2(const char *message, const FString &path1, const FString &path2);
+
public:
CLocalProgress *LocalProgressSpec;
UInt64 NumFolders;
UInt64 NumFiles;
+ UInt64 NumAltStreams;
UInt64 UnpackSize;
- UInt32 CrcSum;
-
+ UInt64 AltStreams_UnpackSize;
+
MY_UNKNOWN_IMP2(ICryptoGetTextPassword, ICompressProgressInfo)
// COM_INTERFACE_ENTRY(IArchiveVolumeExtractCallback)
@@ -108,15 +242,7 @@ public:
STDMETHOD(CryptoGetTextPassword)(BSTR *password);
- CArchiveExtractCallback():
- WriteCTime(true),
- WriteATime(true),
- WriteMTime(true),
- _multiArchives(false)
- {
- LocalProgressSpec = new CLocalProgress();
- _localProgress = LocalProgressSpec;
- }
+ CArchiveExtractCallback();
void InitForMulti(bool multiArchives,
NExtract::NPathMode::EEnum pathMode,
@@ -125,19 +251,49 @@ public:
_multiArchives = multiArchives;
_pathMode = pathMode;
_overwriteMode = overwriteMode;
- NumFolders = NumFiles = UnpackSize = 0;
- CrcSum = 0;
+ NumFolders = NumFiles = NumAltStreams = UnpackSize = AltStreams_UnpackSize = 0;
+ }
+
+ #ifndef _SFX
+
+ void SetHashMethods(IHashCalc *hash)
+ {
+ if (!hash)
+ return;
+ _hashStreamSpec = new COutStreamWithHash;
+ _hashStream = _hashStreamSpec;
+ _hashStreamSpec->_hash = hash;
}
+ #endif
+
void Init(
+ const CExtractNtOptions &ntOptions,
const NWildcard::CCensorNode *wildcardCensor,
const CArc *arc,
IFolderArchiveExtractCallback *extractCallback2,
- bool stdOutMode, bool testMode, bool crcMode,
- const UString &directoryPath,
+ bool stdOutMode, bool testMode,
+ const FString &directoryPath,
const UStringVector &removePathParts,
UInt64 packSize);
+ #ifdef SUPPORT_LINKS
+private:
+ CHardLinks _hardLinks;
+public:
+ // call PrepareHardLinks() after Init()
+ HRESULT PrepareHardLinks(const CRecordVector<UInt32> *realIndices); // NULL means all items
+ #endif
+
+ // call it after Init()
+
+ void SetBaseParentFolderIndex(UInt32 indexInArc)
+ {
+ _use_baseParentFolder_mode = true;
+ _baseParentFolder = indexInArc;
+ }
+
+ HRESULT SetDirsTimes();
};
#endif
diff --git a/src/libs/7zip/unix/CPP/7zip/UI/Common/ArchiveName.cpp b/src/libs/7zip/unix/CPP/7zip/UI/Common/ArchiveName.cpp
deleted file mode 100644
index c3684def8..000000000
--- a/src/libs/7zip/unix/CPP/7zip/UI/Common/ArchiveName.cpp
+++ /dev/null
@@ -1,54 +0,0 @@
-// ArchiveName.cpp
-
-#include "StdAfx.h"
-
-#include "Windows/FileDir.h"
-#include "Windows/FileFind.h"
-
-#include "ExtractingFilePath.h"
-
-using namespace NWindows;
-
-static UString CreateArchiveName2(const UString &srcName, bool fromPrev, bool keepName)
-{
- UString resultName = L"Archive";
- if (fromPrev)
- {
- UString dirPrefix;
- if (NFile::NDirectory::GetOnlyDirPrefix(srcName, dirPrefix))
- {
- if (dirPrefix.Length() > 0)
- if (dirPrefix[dirPrefix.Length() - 1] == WCHAR_PATH_SEPARATOR)
- {
- dirPrefix.Delete(dirPrefix.Length() - 1);
- NFile::NFind::CFileInfoW fileInfo;
- if (fileInfo.Find(dirPrefix))
- resultName = fileInfo.Name;
- }
- }
- }
- else
- {
- NFile::NFind::CFileInfoW fileInfo;
- if (!fileInfo.Find(srcName))
- // return resultName;
- return srcName;
- resultName = fileInfo.Name;
- if (!fileInfo.IsDir() && !keepName)
- {
- int dotPos = resultName.ReverseFind('.');
- if (dotPos > 0)
- {
- UString archiveName2 = resultName.Left(dotPos);
- if (archiveName2.ReverseFind('.') < 0)
- resultName = archiveName2;
- }
- }
- }
- return resultName;
-}
-
-UString CreateArchiveName(const UString &srcName, bool fromPrev, bool keepName)
-{
- return GetCorrectFsPath(CreateArchiveName2(srcName, fromPrev, keepName));
-}
diff --git a/src/libs/7zip/unix/CPP/7zip/UI/Common/ArchiveName.h b/src/libs/7zip/unix/CPP/7zip/UI/Common/ArchiveName.h
deleted file mode 100644
index 9513fb2ba..000000000
--- a/src/libs/7zip/unix/CPP/7zip/UI/Common/ArchiveName.h
+++ /dev/null
@@ -1,10 +0,0 @@
-// ArchiveName.h
-
-#ifndef __ARCHIVENAME_H
-#define __ARCHIVENAME_H
-
-#include "Common/MyString.h"
-
-UString CreateArchiveName(const UString &srcName, bool fromPrev, bool keepName);
-
-#endif
diff --git a/src/libs/7zip/unix/CPP/7zip/UI/Common/ArchiveOpenCallback.cpp b/src/libs/7zip/unix/CPP/7zip/UI/Common/ArchiveOpenCallback.cpp
index e7e617131..9eab39d31 100644
--- a/src/libs/7zip/unix/CPP/7zip/UI/Common/ArchiveOpenCallback.cpp
+++ b/src/libs/7zip/unix/CPP/7zip/UI/Common/ArchiveOpenCallback.cpp
@@ -2,10 +2,10 @@
#include "StdAfx.h"
-#include "Common/StringConvert.h"
-#include "Common/ComTry.h"
+#include "../../../Common/ComTry.h"
-#include "Windows/PropVariant.h"
+#include "../../../Windows/FileName.h"
+#include "../../../Windows/PropVariant.h"
#include "../../Common/FileStreams.h"
@@ -34,7 +34,7 @@ STDMETHODIMP COpenCallbackImp::SetCompleted(const UInt64 *files, const UInt64 *b
return Callback->Open_SetCompleted(files, bytes);
COM_TRY_END
}
-
+
STDMETHODIMP COpenCallbackImp::GetProperty(PROPID propID, PROPVARIANT *value)
{
COM_TRY_BEGIN
@@ -60,55 +60,48 @@ STDMETHODIMP COpenCallbackImp::GetProperty(PROPID propID, PROPVARIANT *value)
COM_TRY_END
}
-int COpenCallbackImp::FindName(const UString &name)
-{
- for (int i = 0; i < FileNames.Size(); i++)
- if (name.CompareNoCase(FileNames[i]) == 0)
- return i;
- return -1;
-}
-
struct CInFileStreamVol: public CInFileStream
{
- UString Name;
+ int FileNameIndex;
COpenCallbackImp *OpenCallbackImp;
CMyComPtr<IArchiveOpenCallback> OpenCallbackRef;
+ CInFileStreamVol(bool ignoreLink = false) : CInFileStream(ignoreLink) { }
~CInFileStreamVol()
{
if (OpenCallbackRef)
- {
- int index = OpenCallbackImp->FindName(Name);
- if (index >= 0)
- OpenCallbackImp->FileNames.Delete(index);
- }
+ OpenCallbackImp->FileNames_WasUsed[FileNameIndex] = false;
}
};
STDMETHODIMP COpenCallbackImp::GetStream(const wchar_t *name, IInStream **inStream)
{
COM_TRY_BEGIN
+ *inStream = NULL;
if (_subArchiveMode)
return S_FALSE;
if (Callback)
{
RINOK(Callback->Open_CheckBreak());
}
- *inStream = NULL;
- UString fullPath = _folderPrefix + name;
- if (!_fileInfo.Find(fullPath))
+ FString fullPath;
+ if (!NFile::NName::GetFullPath(_folderPrefix, us2fs(name), fullPath))
+ return S_FALSE;
+ if (!_fileInfo.Find(fullPath,true))
return S_FALSE;
if (_fileInfo.IsDir())
return S_FALSE;
- CInFileStreamVol *inFile = new CInFileStreamVol;
+ CInFileStreamVol *inFile = new CInFileStreamVol(true);
CMyComPtr<IInStream> inStreamTemp = inFile;
if (!inFile->Open(fullPath))
return ::GetLastError();
- *inStream = inStreamTemp.Detach();
- inFile->Name = name;
+
+ FileSizes.Add(_fileInfo.Size);
+ FileNames.Add(name);
+ inFile->FileNameIndex = FileNames_WasUsed.Add(true);
inFile->OpenCallbackImp = this;
inFile->OpenCallbackRef = this;
- FileNames.Add(name);
- TotalSize += _fileInfo.Size;
+ // TotalSize += _fileInfo.Size;
+ *inStream = inStreamTemp.Detach();
return S_OK;
COM_TRY_END
}
@@ -130,4 +123,3 @@ STDMETHODIMP COpenCallbackImp::CryptoGetTextPassword(BSTR *password)
COM_TRY_END
}
#endif
-
diff --git a/src/libs/7zip/unix/CPP/7zip/UI/Common/ArchiveOpenCallback.h b/src/libs/7zip/unix/CPP/7zip/UI/Common/ArchiveOpenCallback.h
index c6651e8f9..b72892c2f 100644
--- a/src/libs/7zip/unix/CPP/7zip/UI/Common/ArchiveOpenCallback.h
+++ b/src/libs/7zip/unix/CPP/7zip/UI/Common/ArchiveOpenCallback.h
@@ -3,10 +3,9 @@
#ifndef __ARCHIVE_OPEN_CALLBACK_H
#define __ARCHIVE_OPEN_CALLBACK_H
-#include "Common/MyCom.h"
-#include "Common/MyString.h"
+#include "../../../Common/MyCom.h"
-#include "Windows/FileFind.h"
+#include "../../../Windows/FileFind.h"
#ifndef _NO_CRYPTO
#include "../../IPassword.h"
@@ -21,10 +20,10 @@
#define INTERFACE_IOpenCallbackUI_Crypto(x) \
virtual HRESULT Open_CryptoGetTextPassword(BSTR *password) x; \
- virtual HRESULT Open_GetPasswordIfAny(UString &password) x; \
+ virtual HRESULT Open_GetPasswordIfAny(bool &passwordIsDefined, UString &password) x; \
virtual bool Open_WasPasswordAsked() x; \
virtual void Open_ClearPasswordWasAskedFlag() x; \
-
+
#endif
#define INTERFACE_IOpenCallbackUI(x) \
@@ -72,32 +71,41 @@ public:
{
_subArchiveMode = true;
_subArchiveName = name;
- TotalSize = 0;
- return S_OK;
+ // TotalSize = 0;
+ return S_OK;
}
private:
- UString _folderPrefix;
- NWindows::NFile::NFind::CFileInfoW _fileInfo;
+ FString _folderPrefix;
+ NWindows::NFile::NFind::CFileInfo _fileInfo;
bool _subArchiveMode;
UString _subArchiveName;
+
public:
UStringVector FileNames;
+ CBoolVector FileNames_WasUsed;
+ CRecordVector<UInt64> FileSizes;
+
IOpenCallbackUI *Callback;
CMyComPtr<IArchiveOpenCallback> ReOpenCallback;
- UInt64 TotalSize;
+ // UInt64 TotalSize;
COpenCallbackImp(): Callback(NULL) {}
- void Init(const UString &folderPrefix, const UString &fileName)
+ void Init(const FString &folderPrefix, const FString &fileName)
{
_folderPrefix = folderPrefix;
- if (!_fileInfo.Find(_folderPrefix + fileName))
- throw 1;
+ if (!_fileInfo.Find(_folderPrefix + fileName,true))
+ throw 20121118;
FileNames.Clear();
+ FileNames_WasUsed.Clear();
+ FileSizes.Clear();
_subArchiveMode = false;
- TotalSize = 0;
+ // TotalSize = 0;
+ }
+ bool SetSecondFileInfo(CFSTR newName)
+ {
+ return _fileInfo.Find(newName) && !_fileInfo.IsDir();
}
- int FindName(const UString &name);
};
#endif
diff --git a/src/libs/7zip/unix/CPP/7zip/UI/Common/Bench.cpp b/src/libs/7zip/unix/CPP/7zip/UI/Common/Bench.cpp
deleted file mode 100644
index 282f405f1..000000000
--- a/src/libs/7zip/unix/CPP/7zip/UI/Common/Bench.cpp
+++ /dev/null
@@ -1,1028 +0,0 @@
-// Bench.cpp
-
-#include "StdAfx.h"
-
-#include "Bench.h"
-
-#ifndef _WIN32
-#define USE_POSIX_TIME
-#define USE_POSIX_TIME2
-#endif
-
-#ifdef USE_POSIX_TIME
-#include <time.h>
-#ifdef USE_POSIX_TIME2
-#include <sys/time.h>
-#endif
-#endif
-
-#ifdef _WIN32
-#define USE_ALLOCA
-#endif
-
-#ifdef USE_ALLOCA
-#ifdef _WIN32
-#include <malloc.h>
-#else
-#include <stdlib.h>
-#endif
-#endif
-
-#include "../../../../C/7zCrc.h"
-#include "../../../../C/Alloc.h"
-
-#ifndef _7ZIP_ST
-#include "../../../Windows/Synchronization.h"
-#include "../../../Windows/Thread.h"
-#endif
-
-#include "../../../Windows/PropVariant.h"
-
-static const UInt32 kUncompressMinBlockSize =
-#ifdef UNDER_CE
-1 << 24;
-#else
-1 << 26;
-#endif
-
-static const UInt32 kCrcBlockSize =
-#ifdef UNDER_CE
-1 << 25;
-#else
-1 << 30;
-#endif
-
-static const UInt32 kAdditionalSize = (1 << 16);
-static const UInt32 kCompressedAdditionalSize = (1 << 10);
-static const UInt32 kMaxLzmaPropSize = 5;
-
-class CBaseRandomGenerator
-{
- UInt32 A1;
- UInt32 A2;
-public:
- CBaseRandomGenerator() { Init(); }
- void Init() { A1 = 362436069; A2 = 521288629;}
- UInt32 GetRnd()
- {
- return
- ((A1 = 36969 * (A1 & 0xffff) + (A1 >> 16)) << 16) +
- ((A2 = 18000 * (A2 & 0xffff) + (A2 >> 16)) );
- }
-};
-
-class CBenchBuffer
-{
-public:
- size_t BufferSize;
- Byte *Buffer;
- CBenchBuffer(): Buffer(0) {}
- virtual ~CBenchBuffer() { Free(); }
- void Free()
- {
- ::MidFree(Buffer);
- Buffer = 0;
- }
- bool Alloc(size_t bufferSize)
- {
- if (Buffer != 0 && BufferSize == bufferSize)
- return true;
- Free();
- Buffer = (Byte *)::MidAlloc(bufferSize);
- BufferSize = bufferSize;
- return (Buffer != 0);
- }
-};
-
-class CBenchRandomGenerator: public CBenchBuffer
-{
- CBaseRandomGenerator *RG;
-public:
- void Set(CBaseRandomGenerator *rg) { RG = rg; }
- UInt32 GetVal(UInt32 &res, int numBits)
- {
- UInt32 val = res & (((UInt32)1 << numBits) - 1);
- res >>= numBits;
- return val;
- }
- UInt32 GetLen(UInt32 &res)
- {
- UInt32 len = GetVal(res, 2);
- return GetVal(res, 1 + len);
- }
- void Generate()
- {
- UInt32 pos = 0;
- UInt32 rep0 = 1;
- while (pos < BufferSize)
- {
- UInt32 res = RG->GetRnd();
- res >>= 1;
- if (GetVal(res, 1) == 0 || pos < 1024)
- Buffer[pos++] = (Byte)(res & 0xFF);
- else
- {
- UInt32 len;
- len = 1 + GetLen(res);
- if (GetVal(res, 3) != 0)
- {
- len += GetLen(res);
- do
- {
- UInt32 ppp = GetVal(res, 5) + 6;
- res = RG->GetRnd();
- if (ppp > 30)
- continue;
- rep0 = /* (1 << ppp) +*/ GetVal(res, ppp);
- res = RG->GetRnd();
- }
- while (rep0 >= pos);
- rep0++;
- }
-
- for (UInt32 i = 0; i < len && pos < BufferSize; i++, pos++)
- Buffer[pos] = Buffer[pos - rep0];
- }
- }
- }
-};
-
-
-class CBenchmarkInStream:
- public ISequentialInStream,
- public CMyUnknownImp
-{
- const Byte *Data;
- size_t Pos;
- size_t Size;
-public:
- MY_UNKNOWN_IMP
- void Init(const Byte *data, size_t size)
- {
- Data = data;
- Size = size;
- Pos = 0;
- }
- STDMETHOD(Read)(void *data, UInt32 size, UInt32 *processedSize);
-};
-
-STDMETHODIMP CBenchmarkInStream::Read(void *data, UInt32 size, UInt32 *processedSize)
-{
- size_t remain = Size - Pos;
- UInt32 kMaxBlockSize = (1 << 20);
- if (size > kMaxBlockSize)
- size = kMaxBlockSize;
- if (size > remain)
- size = (UInt32)remain;
- for (UInt32 i = 0; i < size; i++)
- ((Byte *)data)[i] = Data[Pos + i];
- Pos += size;
- if(processedSize != NULL)
- *processedSize = size;
- return S_OK;
-}
-
-class CBenchmarkOutStream:
- public ISequentialOutStream,
- public CBenchBuffer,
- public CMyUnknownImp
-{
- // bool _overflow;
-public:
- UInt32 Pos;
- // CBenchmarkOutStream(): _overflow(false) {}
- void Init()
- {
- // _overflow = false;
- Pos = 0;
- }
- MY_UNKNOWN_IMP
- STDMETHOD(Write)(const void *data, UInt32 size, UInt32 *processedSize);
-};
-
-STDMETHODIMP CBenchmarkOutStream::Write(const void *data, UInt32 size, UInt32 *processedSize)
-{
- size_t curSize = BufferSize - Pos;
- if (curSize > size)
- curSize = size;
- memcpy(Buffer + Pos, data, curSize);
- Pos += (UInt32)curSize;
- if(processedSize != NULL)
- *processedSize = (UInt32)curSize;
- if (curSize != size)
- {
- // _overflow = true;
- return E_FAIL;
- }
- return S_OK;
-}
-
-class CCrcOutStream:
- public ISequentialOutStream,
- public CMyUnknownImp
-{
-public:
- UInt32 Crc;
- MY_UNKNOWN_IMP
- void Init() { Crc = CRC_INIT_VAL; }
- STDMETHOD(Write)(const void *data, UInt32 size, UInt32 *processedSize);
-};
-
-STDMETHODIMP CCrcOutStream::Write(const void *data, UInt32 size, UInt32 *processedSize)
-{
- Crc = CrcUpdate(Crc, data, size);
- if (processedSize != NULL)
- *processedSize = size;
- return S_OK;
-}
-
-static UInt64 GetTimeCount()
-{
- #ifdef USE_POSIX_TIME
- #ifdef USE_POSIX_TIME2
- timeval v;
- if (gettimeofday(&v, 0) == 0)
- return (UInt64)(v.tv_sec) * 1000000 + v.tv_usec;
- return (UInt64)time(NULL) * 1000000;
- #else
- return time(NULL);
- #endif
- #else
- /*
- LARGE_INTEGER value;
- if (::QueryPerformanceCounter(&value))
- return value.QuadPart;
- */
- return GetTickCount();
- #endif
-}
-
-static UInt64 GetFreq()
-{
- #ifdef USE_POSIX_TIME
- #ifdef USE_POSIX_TIME2
- return 1000000;
- #else
- return 1;
- #endif
- #else
- /*
- LARGE_INTEGER value;
- if (::QueryPerformanceFrequency(&value))
- return value.QuadPart;
- */
- return 1000;
- #endif
-}
-
-#ifndef USE_POSIX_TIME
-static inline UInt64 GetTime64(const FILETIME &t) { return ((UInt64)t.dwHighDateTime << 32) | t.dwLowDateTime; }
-#endif
-
-static UInt64 GetUserTime()
-{
- #ifdef USE_POSIX_TIME
- return clock();
- #else
- FILETIME creationTime, exitTime, kernelTime, userTime;
- if (
- #ifdef UNDER_CE
- ::GetThreadTimes(::GetCurrentThread()
- #else
- ::GetProcessTimes(::GetCurrentProcess()
- #endif
- , &creationTime, &exitTime, &kernelTime, &userTime) != 0)
- return GetTime64(userTime) + GetTime64(kernelTime);
- return (UInt64)GetTickCount() * 10000;
- #endif
-}
-
-static UInt64 GetUserFreq()
-{
- #ifdef USE_POSIX_TIME
- return CLOCKS_PER_SEC;
- #else
- return 10000000;
- #endif
-}
-
-class CBenchProgressStatus
-{
- #ifndef _7ZIP_ST
- NWindows::NSynchronization::CCriticalSection CS;
- #endif
-public:
- HRESULT Res;
- bool EncodeMode;
- void SetResult(HRESULT res)
- {
- #ifndef _7ZIP_ST
- NWindows::NSynchronization::CCriticalSectionLock lock(CS);
- #endif
- Res = res;
- }
- HRESULT GetResult()
- {
- #ifndef _7ZIP_ST
- NWindows::NSynchronization::CCriticalSectionLock lock(CS);
- #endif
- return Res;
- }
-};
-
-class CBenchProgressInfo:
- public ICompressProgressInfo,
- public CMyUnknownImp
-{
-public:
- CBenchProgressStatus *Status;
- CBenchInfo BenchInfo;
- HRESULT Res;
- IBenchCallback *callback;
- CBenchProgressInfo(): callback(0) {}
- MY_UNKNOWN_IMP
- STDMETHOD(SetRatioInfo)(const UInt64 *inSize, const UInt64 *outSize);
-};
-
-static void SetStartTime(CBenchInfo &bi)
-{
- bi.GlobalFreq = GetFreq();
- bi.UserFreq = GetUserFreq();
- bi.GlobalTime = ::GetTimeCount();
- bi.UserTime = ::GetUserTime();
-}
-
-static void SetFinishTime(const CBenchInfo &biStart, CBenchInfo &dest)
-{
- dest.GlobalFreq = GetFreq();
- dest.UserFreq = GetUserFreq();
- dest.GlobalTime = ::GetTimeCount() - biStart.GlobalTime;
- dest.UserTime = ::GetUserTime() - biStart.UserTime;
-}
-
-STDMETHODIMP CBenchProgressInfo::SetRatioInfo(const UInt64 *inSize, const UInt64 *outSize)
-{
- HRESULT res = Status->GetResult();
- if (res != S_OK)
- return res;
- if (!callback)
- return res;
- CBenchInfo info = BenchInfo;
- SetFinishTime(BenchInfo, info);
- if (Status->EncodeMode)
- {
- info.UnpackSize = *inSize;
- info.PackSize = *outSize;
- res = callback->SetEncodeResult(info, false);
- }
- else
- {
- info.PackSize = BenchInfo.PackSize + *inSize;
- info.UnpackSize = BenchInfo.UnpackSize + *outSize;
- res = callback->SetDecodeResult(info, false);
- }
- if (res != S_OK)
- Status->SetResult(res);
- return res;
-}
-
-static const int kSubBits = 8;
-
-static UInt32 GetLogSize(UInt32 size)
-{
- for (int i = kSubBits; i < 32; i++)
- for (UInt32 j = 0; j < (1 << kSubBits); j++)
- if (size <= (((UInt32)1) << i) + (j << (i - kSubBits)))
- return (i << kSubBits) + j;
- return (32 << kSubBits);
-}
-
-static void NormalizeVals(UInt64 &v1, UInt64 &v2)
-{
- while (v1 > 1000000)
- {
- v1 >>= 1;
- v2 >>= 1;
- }
-}
-
-UInt64 GetUsage(const CBenchInfo &info)
-{
- UInt64 userTime = info.UserTime;
- UInt64 userFreq = info.UserFreq;
- UInt64 globalTime = info.GlobalTime;
- UInt64 globalFreq = info.GlobalFreq;
- NormalizeVals(userTime, userFreq);
- NormalizeVals(globalFreq, globalTime);
- if (userFreq == 0)
- userFreq = 1;
- if (globalTime == 0)
- globalTime = 1;
- return userTime * globalFreq * 1000000 / userFreq / globalTime;
-}
-
-UInt64 GetRatingPerUsage(const CBenchInfo &info, UInt64 rating)
-{
- UInt64 userTime = info.UserTime;
- UInt64 userFreq = info.UserFreq;
- UInt64 globalTime = info.GlobalTime;
- UInt64 globalFreq = info.GlobalFreq;
- NormalizeVals(userFreq, userTime);
- NormalizeVals(globalTime, globalFreq);
- if (globalFreq == 0)
- globalFreq = 1;
- if (userTime == 0)
- userTime = 1;
- return userFreq * globalTime / globalFreq * rating / userTime;
-}
-
-static UInt64 MyMultDiv64(UInt64 value, UInt64 elapsedTime, UInt64 freq)
-{
- UInt64 elTime = elapsedTime;
- NormalizeVals(freq, elTime);
- if (elTime == 0)
- elTime = 1;
- return value * freq / elTime;
-}
-
-UInt64 GetCompressRating(UInt32 dictionarySize, UInt64 elapsedTime, UInt64 freq, UInt64 size)
-{
- UInt64 t = GetLogSize(dictionarySize) - (kBenchMinDicLogSize << kSubBits);
- UInt64 numCommandsForOne = 870 + ((t * t * 5) >> (2 * kSubBits));
- UInt64 numCommands = (UInt64)(size) * numCommandsForOne;
- return MyMultDiv64(numCommands, elapsedTime, freq);
-}
-
-UInt64 GetDecompressRating(UInt64 elapsedTime, UInt64 freq, UInt64 outSize, UInt64 inSize, UInt32 numIterations)
-{
- UInt64 numCommands = (inSize * 200 + outSize * 4) * numIterations;
- return MyMultDiv64(numCommands, elapsedTime, freq);
-}
-
-struct CEncoderInfo;
-
-struct CEncoderInfo
-{
- #ifndef _7ZIP_ST
- NWindows::CThread thread[2];
- #endif
- CMyComPtr<ICompressCoder> encoder;
- CBenchProgressInfo *progressInfoSpec[2];
- CMyComPtr<ICompressProgressInfo> progressInfo[2];
- UInt32 NumIterations;
- #ifdef USE_ALLOCA
- size_t AllocaSize;
- #endif
-
- struct CDecoderInfo
- {
- CEncoderInfo *Encoder;
- UInt32 DecoderIndex;
- #ifdef USE_ALLOCA
- size_t AllocaSize;
- #endif
- bool CallbackMode;
- };
- CDecoderInfo decodersInfo[2];
-
- CMyComPtr<ICompressCoder> decoders[2];
- HRESULT Results[2];
- CBenchmarkOutStream *outStreamSpec;
- CMyComPtr<ISequentialOutStream> outStream;
- IBenchCallback *callback;
- UInt32 crc;
- UInt32 kBufferSize;
- UInt32 compressedSize;
- CBenchRandomGenerator rg;
- CBenchmarkOutStream *propStreamSpec;
- CMyComPtr<ISequentialOutStream> propStream;
- HRESULT Init(UInt32 dictionarySize, UInt32 numThreads, CBaseRandomGenerator *rg);
- HRESULT Encode();
- HRESULT Decode(UInt32 decoderIndex);
-
- CEncoderInfo(): outStreamSpec(0), callback(0), propStreamSpec(0) {}
-
- #ifndef _7ZIP_ST
- static THREAD_FUNC_DECL EncodeThreadFunction(void *param)
- {
- CEncoderInfo *encoder = (CEncoderInfo *)param;
- #ifdef USE_ALLOCA
- alloca(encoder->AllocaSize);
- #endif
- HRESULT res = encoder->Encode();
- encoder->Results[0] = res;
- if (res != S_OK)
- encoder->progressInfoSpec[0]->Status->SetResult(res);
-
- return 0;
- }
- static THREAD_FUNC_DECL DecodeThreadFunction(void *param)
- {
- CDecoderInfo *decoder = (CDecoderInfo *)param;
- #ifdef USE_ALLOCA
- alloca(decoder->AllocaSize);
- #endif
- CEncoderInfo *encoder = decoder->Encoder;
- encoder->Results[decoder->DecoderIndex] = encoder->Decode(decoder->DecoderIndex);
- return 0;
- }
-
- HRESULT CreateEncoderThread()
- {
- return thread[0].Create(EncodeThreadFunction, this);
- }
-
- HRESULT CreateDecoderThread(int index, bool callbackMode
- #ifdef USE_ALLOCA
- , size_t allocaSize
- #endif
- )
- {
- CDecoderInfo &decoder = decodersInfo[index];
- decoder.DecoderIndex = index;
- decoder.Encoder = this;
- #ifdef USE_ALLOCA
- decoder.AllocaSize = allocaSize;
- #endif
- decoder.CallbackMode = callbackMode;
- return thread[index].Create(DecodeThreadFunction, &decoder);
- }
- #endif
-};
-
-HRESULT CEncoderInfo::Init(UInt32 dictionarySize, UInt32 numThreads, CBaseRandomGenerator *rgLoc)
-{
- rg.Set(rgLoc);
- kBufferSize = dictionarySize + kAdditionalSize;
- UInt32 kCompressedBufferSize = (kBufferSize / 2) + kCompressedAdditionalSize;
- if (!rg.Alloc(kBufferSize))
- return E_OUTOFMEMORY;
- rg.Generate();
- crc = CrcCalc(rg.Buffer, rg.BufferSize);
-
- outStreamSpec = new CBenchmarkOutStream;
- if (!outStreamSpec->Alloc(kCompressedBufferSize))
- return E_OUTOFMEMORY;
-
- outStream = outStreamSpec;
-
- propStreamSpec = 0;
- if (!propStream)
- {
- propStreamSpec = new CBenchmarkOutStream;
- propStream = propStreamSpec;
- }
- if (!propStreamSpec->Alloc(kMaxLzmaPropSize))
- return E_OUTOFMEMORY;
- propStreamSpec->Init();
-
- PROPID propIDs[] =
- {
- NCoderPropID::kDictionarySize,
- NCoderPropID::kNumThreads
- };
- const int kNumProps = sizeof(propIDs) / sizeof(propIDs[0]);
- PROPVARIANT props[kNumProps];
- props[0].vt = VT_UI4;
- props[0].ulVal = dictionarySize;
-
- props[1].vt = VT_UI4;
- props[1].ulVal = numThreads;
-
- {
- CMyComPtr<ICompressSetCoderProperties> setCoderProperties;
- RINOK(encoder.QueryInterface(IID_ICompressSetCoderProperties, &setCoderProperties));
- if (!setCoderProperties)
- return E_FAIL;
- RINOK(setCoderProperties->SetCoderProperties(propIDs, props, kNumProps));
-
- CMyComPtr<ICompressWriteCoderProperties> writeCoderProperties;
- encoder.QueryInterface(IID_ICompressWriteCoderProperties, &writeCoderProperties);
- if (writeCoderProperties)
- {
- RINOK(writeCoderProperties->WriteCoderProperties(propStream));
- }
- }
- return S_OK;
-}
-
-HRESULT CEncoderInfo::Encode()
-{
- CBenchmarkInStream *inStreamSpec = new CBenchmarkInStream;
- CMyComPtr<ISequentialInStream> inStream = inStreamSpec;
- inStreamSpec->Init(rg.Buffer, rg.BufferSize);
- outStreamSpec->Init();
-
- RINOK(encoder->Code(inStream, outStream, 0, 0, progressInfo[0]));
- compressedSize = outStreamSpec->Pos;
- encoder.Release();
- return S_OK;
-}
-
-HRESULT CEncoderInfo::Decode(UInt32 decoderIndex)
-{
- CBenchmarkInStream *inStreamSpec = new CBenchmarkInStream;
- CMyComPtr<ISequentialInStream> inStream = inStreamSpec;
- CMyComPtr<ICompressCoder> &decoder = decoders[decoderIndex];
-
- CMyComPtr<ICompressSetDecoderProperties2> compressSetDecoderProperties;
- decoder.QueryInterface(IID_ICompressSetDecoderProperties2, &compressSetDecoderProperties);
- if (!compressSetDecoderProperties)
- return E_FAIL;
-
- CCrcOutStream *crcOutStreamSpec = new CCrcOutStream;
- CMyComPtr<ISequentialOutStream> crcOutStream = crcOutStreamSpec;
-
- CBenchProgressInfo *pi = progressInfoSpec[decoderIndex];
- pi->BenchInfo.UnpackSize = 0;
- pi->BenchInfo.PackSize = 0;
-
- for (UInt32 j = 0; j < NumIterations; j++)
- {
- inStreamSpec->Init(outStreamSpec->Buffer, compressedSize);
- crcOutStreamSpec->Init();
-
- RINOK(compressSetDecoderProperties->SetDecoderProperties2(propStreamSpec->Buffer, propStreamSpec->Pos));
- UInt64 outSize = kBufferSize;
- RINOK(decoder->Code(inStream, crcOutStream, 0, &outSize, progressInfo[decoderIndex]));
- if (CRC_GET_DIGEST(crcOutStreamSpec->Crc) != crc)
- return S_FALSE;
- pi->BenchInfo.UnpackSize += kBufferSize;
- pi->BenchInfo.PackSize += compressedSize;
- }
- decoder.Release();
- return S_OK;
-}
-
-static const UInt32 kNumThreadsMax = (1 << 16);
-
-struct CBenchEncoders
-{
- CEncoderInfo *encoders;
- CBenchEncoders(UInt32 num): encoders(0) { encoders = new CEncoderInfo[num]; }
- ~CBenchEncoders() { delete []encoders; }
-};
-
-HRESULT LzmaBench(
- DECL_EXTERNAL_CODECS_LOC_VARS
- UInt32 numThreads, UInt32 dictionarySize, IBenchCallback *callback)
-{
- UInt32 numEncoderThreads =
- #ifndef _7ZIP_ST
- (numThreads > 1 ? numThreads / 2 : 1);
- #else
- 1;
- #endif
- UInt32 numSubDecoderThreads =
- #ifndef _7ZIP_ST
- (numThreads > 1 ? 2 : 1);
- #else
- 1;
- #endif
- if (dictionarySize < (1 << kBenchMinDicLogSize) || numThreads < 1 || numEncoderThreads > kNumThreadsMax)
- {
- return E_INVALIDARG;
- }
-
- CBenchEncoders encodersSpec(numEncoderThreads);
- CEncoderInfo *encoders = encodersSpec.encoders;
-
-
- UInt32 i;
- for (i = 0; i < numEncoderThreads; i++)
- {
- CEncoderInfo &encoder = encoders[i];
- encoder.callback = (i == 0) ? callback : 0;
-
- const UInt32 kLzmaId = 0x030101;
- RINOK(CreateCoder(EXTERNAL_CODECS_LOC_VARS kLzmaId, encoder.encoder, true));
- if (!encoder.encoder)
- return E_NOTIMPL;
- for (UInt32 j = 0; j < numSubDecoderThreads; j++)
- {
- RINOK(CreateCoder(EXTERNAL_CODECS_LOC_VARS kLzmaId, encoder.decoders[j], false));
- if (!encoder.decoders[j])
- return E_NOTIMPL;
- }
- }
-
- CBaseRandomGenerator rg;
- rg.Init();
- for (i = 0; i < numEncoderThreads; i++)
- {
- RINOK(encoders[i].Init(dictionarySize, numThreads, &rg));
- }
-
- CBenchProgressStatus status;
- status.Res = S_OK;
- status.EncodeMode = true;
-
- for (i = 0; i < numEncoderThreads; i++)
- {
- CEncoderInfo &encoder = encoders[i];
- for (int j = 0; j < 2; j++)
- {
- encoder.progressInfo[j] = encoder.progressInfoSpec[j] = new CBenchProgressInfo;
- encoder.progressInfoSpec[j]->Status = &status;
- }
- if (i == 0)
- {
- encoder.progressInfoSpec[0]->callback = callback;
- encoder.progressInfoSpec[0]->BenchInfo.NumIterations = numEncoderThreads;
- SetStartTime(encoder.progressInfoSpec[0]->BenchInfo);
- }
-
- #ifndef _7ZIP_ST
- if (numEncoderThreads > 1)
- {
- #ifdef USE_ALLOCA
- encoder.AllocaSize = (i * 16 * 21) & 0x7FF;
- #endif
- RINOK(encoder.CreateEncoderThread())
- }
- else
- #endif
- {
- RINOK(encoder.Encode());
- }
- }
- #ifndef _7ZIP_ST
- if (numEncoderThreads > 1)
- for (i = 0; i < numEncoderThreads; i++)
- encoders[i].thread[0].Wait();
- #endif
-
- RINOK(status.Res);
-
- CBenchInfo info;
-
- SetFinishTime(encoders[0].progressInfoSpec[0]->BenchInfo, info);
- info.UnpackSize = 0;
- info.PackSize = 0;
- info.NumIterations = 1; // progressInfoSpec->NumIterations;
- for (i = 0; i < numEncoderThreads; i++)
- {
- CEncoderInfo &encoder = encoders[i];
- info.UnpackSize += encoder.kBufferSize;
- info.PackSize += encoder.compressedSize;
- }
- RINOK(callback->SetEncodeResult(info, true));
-
-
- status.Res = S_OK;
- status.EncodeMode = false;
-
- UInt32 numDecoderThreads = numEncoderThreads * numSubDecoderThreads;
- for (i = 0; i < numEncoderThreads; i++)
- {
- CEncoderInfo &encoder = encoders[i];
- encoder.NumIterations = 2 + kUncompressMinBlockSize / encoder.kBufferSize;
-
- if (i == 0)
- {
- encoder.progressInfoSpec[0]->callback = callback;
- encoder.progressInfoSpec[0]->BenchInfo.NumIterations = numDecoderThreads;
- SetStartTime(encoder.progressInfoSpec[0]->BenchInfo);
- }
-
- #ifndef _7ZIP_ST
- if (numDecoderThreads > 1)
- {
- for (UInt32 j = 0; j < numSubDecoderThreads; j++)
- {
- HRESULT res = encoder.CreateDecoderThread(j, (i == 0 && j == 0)
- #ifdef USE_ALLOCA
- , ((i * numSubDecoderThreads + j) * 16 * 21) & 0x7FF
- #endif
- );
- RINOK(res);
- }
- }
- else
- #endif
- {
- RINOK(encoder.Decode(0));
- }
- }
- #ifndef _7ZIP_ST
- HRESULT res = S_OK;
- if (numDecoderThreads > 1)
- for (i = 0; i < numEncoderThreads; i++)
- for (UInt32 j = 0; j < numSubDecoderThreads; j++)
- {
- CEncoderInfo &encoder = encoders[i];
- encoder.thread[j].Wait();
- if (encoder.Results[j] != S_OK)
- res = encoder.Results[j];
- }
- RINOK(res);
- #endif
- RINOK(status.Res);
- SetFinishTime(encoders[0].progressInfoSpec[0]->BenchInfo, info);
- #ifndef _7ZIP_ST
- #ifdef UNDER_CE
- if (numDecoderThreads > 1)
- for (i = 0; i < numEncoderThreads; i++)
- for (UInt32 j = 0; j < numSubDecoderThreads; j++)
- {
- FILETIME creationTime, exitTime, kernelTime, userTime;
- if (::GetThreadTimes(encoders[i].thread[j], &creationTime, &exitTime, &kernelTime, &userTime) != 0)
- info.UserTime += GetTime64(userTime) + GetTime64(kernelTime);
- }
- #endif
- #endif
- info.UnpackSize = 0;
- info.PackSize = 0;
- info.NumIterations = numSubDecoderThreads * encoders[0].NumIterations;
- for (i = 0; i < numEncoderThreads; i++)
- {
- CEncoderInfo &encoder = encoders[i];
- info.UnpackSize += encoder.kBufferSize;
- info.PackSize += encoder.compressedSize;
- }
- RINOK(callback->SetDecodeResult(info, false));
- RINOK(callback->SetDecodeResult(info, true));
- return S_OK;
-}
-
-
-inline UInt64 GetLZMAUsage(bool multiThread, UInt32 dictionary)
-{
- UInt32 hs = dictionary - 1;
- hs |= (hs >> 1);
- hs |= (hs >> 2);
- hs |= (hs >> 4);
- hs |= (hs >> 8);
- hs >>= 1;
- hs |= 0xFFFF;
- if (hs > (1 << 24))
- hs >>= 1;
- hs++;
- return ((hs + (1 << 16)) + (UInt64)dictionary * 2) * 4 + (UInt64)dictionary * 3 / 2 +
- (1 << 20) + (multiThread ? (6 << 20) : 0);
-}
-
-UInt64 GetBenchMemoryUsage(UInt32 numThreads, UInt32 dictionary)
-{
- const UInt32 kBufferSize = dictionary;
- const UInt32 kCompressedBufferSize = (kBufferSize / 2);
- UInt32 numSubThreads = (numThreads > 1) ? 2 : 1;
- UInt32 numBigThreads = numThreads / numSubThreads;
- return (kBufferSize + kCompressedBufferSize +
- GetLZMAUsage((numThreads > 1), dictionary) + (2 << 20)) * numBigThreads;
-}
-
-static bool CrcBig(const void *data, UInt32 size, UInt32 numCycles, UInt32 crcBase)
-{
- for (UInt32 i = 0; i < numCycles; i++)
- if (CrcCalc(data, size) != crcBase)
- return false;
- return true;
-}
-
-#ifndef _7ZIP_ST
-struct CCrcInfo
-{
- NWindows::CThread Thread;
- const Byte *Data;
- UInt32 Size;
- UInt32 NumCycles;
- UInt32 Crc;
- bool Res;
- void Wait()
- {
- Thread.Wait();
- Thread.Close();
- }
-};
-
-static THREAD_FUNC_DECL CrcThreadFunction(void *param)
-{
- CCrcInfo *p = (CCrcInfo *)param;
- p->Res = CrcBig(p->Data, p->Size, p->NumCycles, p->Crc);
- return 0;
-}
-
-struct CCrcThreads
-{
- UInt32 NumThreads;
- CCrcInfo *Items;
- CCrcThreads(): Items(0), NumThreads(0) {}
- void WaitAll()
- {
- for (UInt32 i = 0; i < NumThreads; i++)
- Items[i].Wait();
- NumThreads = 0;
- }
- ~CCrcThreads()
- {
- WaitAll();
- delete []Items;
- }
-};
-#endif
-
-static UInt32 CrcCalc1(const Byte *buf, UInt32 size)
-{
- UInt32 crc = CRC_INIT_VAL;;
- for (UInt32 i = 0; i < size; i++)
- crc = CRC_UPDATE_BYTE(crc, buf[i]);
- return CRC_GET_DIGEST(crc);
-}
-
-static void RandGen(Byte *buf, UInt32 size, CBaseRandomGenerator &RG)
-{
- for (UInt32 i = 0; i < size; i++)
- buf[i] = (Byte)RG.GetRnd();
-}
-
-static UInt32 RandGenCrc(Byte *buf, UInt32 size, CBaseRandomGenerator &RG)
-{
- RandGen(buf, size, RG);
- return CrcCalc1(buf, size);
-}
-
-bool CrcInternalTest()
-{
- CBenchBuffer buffer;
- const UInt32 kBufferSize0 = (1 << 8);
- const UInt32 kBufferSize1 = (1 << 10);
- const UInt32 kCheckSize = (1 << 5);
- if (!buffer.Alloc(kBufferSize0 + kBufferSize1))
- return false;
- Byte *buf = buffer.Buffer;
- UInt32 i;
- for (i = 0; i < kBufferSize0; i++)
- buf[i] = (Byte)i;
- UInt32 crc1 = CrcCalc1(buf, kBufferSize0);
- if (crc1 != 0x29058C73)
- return false;
- CBaseRandomGenerator RG;
- RandGen(buf + kBufferSize0, kBufferSize1, RG);
- for (i = 0; i < kBufferSize0 + kBufferSize1 - kCheckSize; i++)
- for (UInt32 j = 0; j < kCheckSize; j++)
- if (CrcCalc1(buf + i, j) != CrcCalc(buf + i, j))
- return false;
- return true;
-}
-
-HRESULT CrcBench(UInt32 numThreads, UInt32 bufferSize, UInt64 &speed)
-{
- if (numThreads == 0)
- numThreads = 1;
-
- CBenchBuffer buffer;
- size_t totalSize = (size_t)bufferSize * numThreads;
- if (totalSize / numThreads != bufferSize)
- return E_OUTOFMEMORY;
- if (!buffer.Alloc(totalSize))
- return E_OUTOFMEMORY;
-
- Byte *buf = buffer.Buffer;
- CBaseRandomGenerator RG;
- UInt32 numCycles = (kCrcBlockSize) / ((bufferSize >> 2) + 1) + 1;
-
- UInt64 timeVal;
- #ifndef _7ZIP_ST
- CCrcThreads threads;
- if (numThreads > 1)
- {
- threads.Items = new CCrcInfo[numThreads];
- UInt32 i;
- for (i = 0; i < numThreads; i++)
- {
- CCrcInfo &info = threads.Items[i];
- Byte *data = buf + (size_t)bufferSize * i;
- info.Data = data;
- info.NumCycles = numCycles;
- info.Size = bufferSize;
- info.Crc = RandGenCrc(data, bufferSize, RG);
- }
- timeVal = GetTimeCount();
- for (i = 0; i < numThreads; i++)
- {
- CCrcInfo &info = threads.Items[i];
- RINOK(info.Thread.Create(CrcThreadFunction, &info));
- threads.NumThreads++;
- }
- threads.WaitAll();
- for (i = 0; i < numThreads; i++)
- if (!threads.Items[i].Res)
- return S_FALSE;
- }
- else
- #endif
- {
- UInt32 crc = RandGenCrc(buf, bufferSize, RG);
- timeVal = GetTimeCount();
- if (!CrcBig(buf, bufferSize, numCycles, crc))
- return S_FALSE;
- }
- timeVal = GetTimeCount() - timeVal;
- if (timeVal == 0)
- timeVal = 1;
-
- UInt64 size = (UInt64)numCycles * totalSize;
- speed = MyMultDiv64(size, timeVal, GetFreq());
- return S_OK;
-}
diff --git a/src/libs/7zip/unix/CPP/7zip/UI/Common/Bench.h b/src/libs/7zip/unix/CPP/7zip/UI/Common/Bench.h
deleted file mode 100644
index a8d02a19b..000000000
--- a/src/libs/7zip/unix/CPP/7zip/UI/Common/Bench.h
+++ /dev/null
@@ -1,42 +0,0 @@
-// Bench.h
-
-#ifndef __7ZIP_BENCH_H
-#define __7ZIP_BENCH_H
-
-#include "../../Common/CreateCoder.h"
-
-struct CBenchInfo
-{
- UInt64 GlobalTime;
- UInt64 GlobalFreq;
- UInt64 UserTime;
- UInt64 UserFreq;
- UInt64 UnpackSize;
- UInt64 PackSize;
- UInt32 NumIterations;
- CBenchInfo(): NumIterations(0) {}
-};
-
-struct IBenchCallback
-{
- virtual HRESULT SetEncodeResult(const CBenchInfo &info, bool final) = 0;
- virtual HRESULT SetDecodeResult(const CBenchInfo &info, bool final) = 0;
-};
-
-UInt64 GetUsage(const CBenchInfo &benchOnfo);
-UInt64 GetRatingPerUsage(const CBenchInfo &info, UInt64 rating);
-UInt64 GetCompressRating(UInt32 dictionarySize, UInt64 elapsedTime, UInt64 freq, UInt64 size);
-UInt64 GetDecompressRating(UInt64 elapsedTime, UInt64 freq, UInt64 outSize, UInt64 inSize, UInt32 numIterations);
-
-HRESULT LzmaBench(
- DECL_EXTERNAL_CODECS_LOC_VARS
- UInt32 numThreads, UInt32 dictionarySize, IBenchCallback *callback);
-
-const int kBenchMinDicLogSize = 18;
-
-UInt64 GetBenchMemoryUsage(UInt32 numThreads, UInt32 dictionary);
-
-bool CrcInternalTest();
-HRESULT CrcBench(UInt32 numThreads, UInt32 bufferSize, UInt64 &speed);
-
-#endif
diff --git a/src/libs/7zip/unix/CPP/7zip/UI/Common/Common.pri b/src/libs/7zip/unix/CPP/7zip/UI/Common/Common.pri
new file mode 100644
index 000000000..a1d75b674
--- /dev/null
+++ b/src/libs/7zip/unix/CPP/7zip/UI/Common/Common.pri
@@ -0,0 +1,43 @@
+HEADERS += $$7ZIP_BASE/CPP/7zip/UI/Common/ArchiveOpenCallback.h \
+ $$7ZIP_BASE/CPP/7zip/UI/Common/ArchiveExtractCallback.h \
+ $$7ZIP_BASE/CPP/7zip/UI/Common/ArchiveCommandLine.h \
+ $$7ZIP_BASE/CPP/7zip/UI/Common/DefaultName.h \
+ $$7ZIP_BASE/CPP/7zip/UI/Common/DirItem.h \
+ $$7ZIP_BASE/CPP/7zip/UI/Common/EnumDirItems.h \
+ $$7ZIP_BASE/CPP/7zip/UI/Common/Extract.h \
+ $$7ZIP_BASE/CPP/7zip/UI/Common/ExtractMode.h \
+ $$7ZIP_BASE/CPP/7zip/UI/Common/ExtractingFilePath.h \
+ $$7ZIP_BASE/CPP/7zip/UI/Common/HashCalc.h \
+ $$7ZIP_BASE/CPP/7zip/UI/Common/IFileExtractCallback.h \
+ $$7ZIP_BASE/CPP/7zip/UI/Common/LoadCodecs.h \
+ $$7ZIP_BASE/CPP/7zip/UI/Common/OpenArchive.h \
+ $$7ZIP_BASE/CPP/7zip/UI/Common/Property.h \
+ $$7ZIP_BASE/CPP/7zip/UI/Common/PropIDUtils.h \
+ $$7ZIP_BASE/CPP/7zip/UI/Common/SetProperties.h \
+ $$7ZIP_BASE/CPP/7zip/UI/Common/SortUtils.h \
+ $$7ZIP_BASE/CPP/7zip/UI/Common/TempFiles.h \
+ $$7ZIP_BASE/CPP/7zip/UI/Common/Update.h \
+ $$7ZIP_BASE/CPP/7zip/UI/Common/UpdateAction.h \
+ $$7ZIP_BASE/CPP/7zip/UI/Common/UpdateCallback.h \
+ $$7ZIP_BASE/CPP/7zip/UI/Common/UpdatePair.h \
+ $$7ZIP_BASE/CPP/7zip/UI/Common/UpdateProduce.h
+
+SOURCES += $$7ZIP_BASE/CPP/7zip/UI/Common/ArchiveOpenCallback.cpp \
+ $$7ZIP_BASE/CPP/7zip/UI/Common/ArchiveExtractCallback.cpp \
+ $$7ZIP_BASE/CPP/7zip/UI/Common/ArchiveCommandLine.cpp \
+ $$7ZIP_BASE/CPP/7zip/UI/Common/DefaultName.cpp \
+ $$7ZIP_BASE/CPP/7zip/UI/Common/EnumDirItems.cpp \
+ $$7ZIP_BASE/CPP/7zip/UI/Common/Extract.cpp \
+ $$7ZIP_BASE/CPP/7zip/UI/Common/ExtractingFilePath.cpp \
+ $$7ZIP_BASE/CPP/7zip/UI/Common/HashCalc.cpp \
+ $$7ZIP_BASE/CPP/7zip/UI/Common/LoadCodecs.cpp \
+ $$7ZIP_BASE/CPP/7zip/UI/Common/OpenArchive.cpp \
+ $$7ZIP_BASE/CPP/7zip/UI/Common/PropIDUtils.cpp \
+ $$7ZIP_BASE/CPP/7zip/UI/Common/SetProperties.cpp \
+ $$7ZIP_BASE/CPP/7zip/UI/Common/SortUtils.cpp \
+ $$7ZIP_BASE/CPP/7zip/UI/Common/TempFiles.cpp \
+ $$7ZIP_BASE/CPP/7zip/UI/Common/Update.cpp \
+ $$7ZIP_BASE/CPP/7zip/UI/Common/UpdateAction.cpp \
+ $$7ZIP_BASE/CPP/7zip/UI/Common/UpdateCallback.cpp \
+ $$7ZIP_BASE/CPP/7zip/UI/Common/UpdatePair.cpp \
+ $$7ZIP_BASE/CPP/7zip/UI/Common/UpdateProduce.cpp
diff --git a/src/libs/7zip/unix/CPP/7zip/UI/Common/DefaultName.cpp b/src/libs/7zip/unix/CPP/7zip/UI/Common/DefaultName.cpp
index 4335e2731..ce0b327b5 100644
--- a/src/libs/7zip/unix/CPP/7zip/UI/Common/DefaultName.cpp
+++ b/src/libs/7zip/unix/CPP/7zip/UI/Common/DefaultName.cpp
@@ -7,13 +7,13 @@
static UString GetDefaultName3(const UString &fileName,
const UString &extension, const UString &addSubExtension)
{
- int extLength = extension.Length();
- int fileNameLength = fileName.Length();
+ int extLength = extension.Len();
+ int fileNameLength = fileName.Len();
if (fileNameLength > extLength + 1)
{
int dotPos = fileNameLength - (extLength + 1);
if (fileName[dotPos] == '.')
- if (extension.CompareNoCase(fileName.Mid(dotPos + 1)) == 0)
+ if (extension.IsEqualToNoCase(fileName.Ptr(dotPos + 1)))
return fileName.Left(dotPos) + addSubExtension;
}
int dotPos = fileName.ReverseFind(L'.');
diff --git a/src/libs/7zip/unix/CPP/7zip/UI/Common/DefaultName.h b/src/libs/7zip/unix/CPP/7zip/UI/Common/DefaultName.h
index 9764ff871..df1645602 100644
--- a/src/libs/7zip/unix/CPP/7zip/UI/Common/DefaultName.h
+++ b/src/libs/7zip/unix/CPP/7zip/UI/Common/DefaultName.h
@@ -1,9 +1,9 @@
// DefaultName.h
-#ifndef __DEFAULTNAME_H
-#define __DEFAULTNAME_H
+#ifndef __DEFAULT_NAME_H
+#define __DEFAULT_NAME_H
-#include "Common/MyString.h"
+#include "../../../Common/MyString.h"
UString GetDefaultName2(const UString &fileName,
const UString &extension, const UString &addSubExtension);
diff --git a/src/libs/7zip/unix/CPP/7zip/UI/Common/DirItem.h b/src/libs/7zip/unix/CPP/7zip/UI/Common/DirItem.h
index 29cc60d93..82203c03a 100644
--- a/src/libs/7zip/unix/CPP/7zip/UI/Common/DirItem.h
+++ b/src/libs/7zip/unix/CPP/7zip/UI/Common/DirItem.h
@@ -3,8 +3,12 @@
#ifndef __DIR_ITEM_H
#define __DIR_ITEM_H
-#include "Common/MyString.h"
-#include "Common/Types.h"
+#include "../../../Common/MyString.h"
+
+#include "../../../Windows/FileFind.h"
+
+#include "../../Common/UniqBlocks.h"
+
#include "../../Archive/IArchive.h"
struct CDirItem
@@ -14,11 +18,23 @@ struct CDirItem
FILETIME ATime;
FILETIME MTime;
UString Name;
+
+ #if defined(_WIN32) && !defined(UNDER_CE)
+ // UString ShortName;
+ CByteBuffer ReparseData;
+ CByteBuffer ReparseData2; // fixed (reduced) absolute links
+
+ bool AreReparseData() const { return ReparseData.Size() != 0 || ReparseData2.Size() != 0; }
+ #endif
+
UInt32 Attrib;
int PhyParent;
int LogParent;
-
- CDirItem(): PhyParent(-1), LogParent(-1) {}
+ int SecureIndex;
+
+ bool IsAltStream;
+
+ CDirItem(): PhyParent(-1), LogParent(-1), SecureIndex(-1), IsAltStream(false) {}
bool IsDir() const { return (Attrib & FILE_ATTRIBUTE_DIRECTORY) != 0 ; }
};
@@ -29,24 +45,64 @@ class CDirItems
CIntVector LogParents;
UString GetPrefixesPath(const CIntVector &parents, int index, const UString &name) const;
+
+ void EnumerateDir(int phyParent, int logParent, const FString &phyPrefix);
+
public:
CObjectVector<CDirItem> Items;
- int GetNumFolders() const { return Prefixes.Size(); }
- UString GetPhyPath(int index) const;
- UString GetLogPath(int index) const;
+ bool SymLinks;
+
+ bool ScanAltStreams;
+ FStringVector ErrorPaths;
+ CRecordVector<DWORD> ErrorCodes;
+ UInt64 TotalSize;
- int AddPrefix(int phyParent, int logParent, const UString &prefix);
- void DeleteLastPrefix();
- void EnumerateDirectory(int phyParent, int logParent, const UString &phyPrefix,
- UStringVector &errorPaths, CRecordVector<DWORD> &errorCodes);
+ #ifndef UNDER_CE
+ void SetLinkInfo(CDirItem &dirItem, const NWindows::NFile::NFind::CFileInfo &fi,
+ const FString &phyPrefix);
+ #endif
- void EnumerateDirItems2(
- const UString &phyPrefix,
+ void AddError(const FString &path, DWORD errorCode)
+ {
+ ErrorCodes.Add(errorCode);
+ ErrorPaths.Add(path);
+ }
+
+ void AddError(const FString &path)
+ {
+ AddError(path, ::GetLastError());
+ }
+
+ #if defined(_WIN32) && !defined(UNDER_CE)
+
+ CUniqBlocks SecureBlocks;
+ CByteBuffer TempSecureBuf;
+ bool _saclEnabled;
+ bool ReadSecure;
+
+ void AddSecurityItem(const FString &path, int &secureIndex);
+
+ #endif
+
+ CDirItems();
+
+ int GetNumFolders() const { return Prefixes.Size(); }
+ UString GetPhyPath(unsigned index) const;
+ UString GetLogPath(unsigned index) const;
+
+ unsigned AddPrefix(int phyParent, int logParent, const UString &prefix);
+ void DeleteLastPrefix();
+ void EnumerateItems2(
+ const FString &phyPrefix,
const UString &logPrefix,
- const UStringVector &filePaths,
- UStringVector &errorPaths, CRecordVector<DWORD> &errorCodes);
+ const FStringVector &filePaths,
+ FStringVector *requestedPaths);
+
+ #if defined(_WIN32) && !defined(UNDER_CE)
+ void FillFixedReparse();
+ #endif
void ReserveDown();
};
@@ -57,13 +113,14 @@ struct CArcItem
FILETIME MTime;
UString Name;
bool IsDir;
+ bool IsAltStream;
bool SizeDefined;
bool MTimeDefined;
bool Censored;
UInt32 IndexInServer;
int TimeType;
-
- CArcItem(): IsDir(false), SizeDefined(false), MTimeDefined(false), Censored(false), TimeType(-1) {}
+
+ CArcItem(): IsDir(false), IsAltStream(false), SizeDefined(false), MTimeDefined(false), Censored(false), TimeType(-1) {}
};
#endif
diff --git a/src/libs/7zip/unix/CPP/7zip/UI/Common/EnumDirItems.cpp b/src/libs/7zip/unix/CPP/7zip/UI/Common/EnumDirItems.cpp
index ba03ea35c..b94e6274c 100644
--- a/src/libs/7zip/unix/CPP/7zip/UI/Common/EnumDirItems.cpp
+++ b/src/libs/7zip/unix/CPP/7zip/UI/Common/EnumDirItems.cpp
@@ -2,14 +2,25 @@
#include "StdAfx.h"
+#include "../../../Common/Wildcard.h"
+
+#include "../../../Windows/FileDir.h"
+#include "../../../Windows/FileIO.h"
+#include "../../../Windows/FileName.h"
+
+#if defined(_WIN32) && !defined(UNDER_CE)
+#define _USE_SECURITY_CODE
+#include "../../../Windows/SecurityUtils.h"
+#endif
+
#include "EnumDirItems.h"
using namespace NWindows;
using namespace NFile;
using namespace NName;
-void AddDirFileInfo(int phyParent, int logParent,
- const NFind::CFileInfoW &fi, CObjectVector<CDirItem> &dirItems)
+void AddDirFileInfo(int phyParent, int logParent, int secureIndex,
+ const NFind::CFileInfo &fi, CObjectVector<CDirItem> &dirItems)
{
CDirItem di;
di.Size = fi.Size;
@@ -17,41 +28,46 @@ void AddDirFileInfo(int phyParent, int logParent,
di.ATime = fi.ATime;
di.MTime = fi.MTime;
di.Attrib = fi.Attrib;
+ // FIXME di.IsAltStream = fi.IsAltStream;
di.PhyParent = phyParent;
di.LogParent = logParent;
- di.Name = fi.Name;
+ di.SecureIndex = secureIndex;
+ di.Name = fs2us(fi.Name);
+ #if defined(_WIN32) && !defined(UNDER_CE)
+ // di.ShortName = fs2us(fi.ShortName);
+ #endif
dirItems.Add(di);
}
UString CDirItems::GetPrefixesPath(const CIntVector &parents, int index, const UString &name) const
{
UString path;
- int len = name.Length();
+ unsigned len = name.Len();
int i;
for (i = index; i >= 0; i = parents[i])
- len += Prefixes[i].Length();
- int totalLen = len;
+ len += Prefixes[i].Len();
+ unsigned totalLen = len;
wchar_t *p = path.GetBuffer(len);
p[len] = 0;
- len -= name.Length();
- memcpy(p + len, (const wchar_t *)name, name.Length() * sizeof(wchar_t));
+ len -= name.Len();
+ memcpy(p + len, (const wchar_t *)name, name.Len() * sizeof(wchar_t));
for (i = index; i >= 0; i = parents[i])
{
const UString &s = Prefixes[i];
- len -= s.Length();
- memcpy(p + len, (const wchar_t *)s, s.Length() * sizeof(wchar_t));
+ len -= s.Len();
+ memcpy(p + len, (const wchar_t *)s, s.Len() * sizeof(wchar_t));
}
path.ReleaseBuffer(totalLen);
return path;
}
-UString CDirItems::GetPhyPath(int index) const
+UString CDirItems::GetPhyPath(unsigned index) const
{
const CDirItem &di = Items[index];
return GetPrefixesPath(PhyParents, di.PhyParent, di.Name);
}
-UString CDirItems::GetLogPath(int index) const
+UString CDirItems::GetLogPath(unsigned index) const
{
const CDirItem &di = Items[index];
return GetPrefixesPath(LogParents, di.LogParent, di.Name);
@@ -65,7 +81,7 @@ void CDirItems::ReserveDown()
Items.ReserveDown();
}
-int CDirItems::AddPrefix(int phyParent, int logParent, const UString &prefix)
+unsigned CDirItems::AddPrefix(int phyParent, int logParent, const UString &prefix)
{
PhyParents.Add(phyParent);
LogParents.Add(logParent);
@@ -79,162 +95,440 @@ void CDirItems::DeleteLastPrefix()
Prefixes.DeleteBack();
}
-void CDirItems::EnumerateDirectory(int phyParent, int logParent, const UString &phyPrefix,
- UStringVector &errorPaths, CRecordVector<DWORD> &errorCodes)
+bool InitLocalPrivileges();
+
+CDirItems::CDirItems():
+ SymLinks(false),
+ TotalSize(0)
+ #ifdef _USE_SECURITY_CODE
+ , ReadSecure(false)
+ #endif
+{
+ #ifdef _USE_SECURITY_CODE
+ _saclEnabled = InitLocalPrivileges();
+ #endif
+}
+
+#ifdef _USE_SECURITY_CODE
+
+void CDirItems::AddSecurityItem(const FString &path, int &secureIndex)
+{
+ secureIndex = -1;
+
+ SECURITY_INFORMATION securInfo =
+ DACL_SECURITY_INFORMATION |
+ GROUP_SECURITY_INFORMATION |
+ OWNER_SECURITY_INFORMATION;
+ if (_saclEnabled)
+ securInfo |= SACL_SECURITY_INFORMATION;
+
+ DWORD errorCode = 0;
+ DWORD secureSize;
+ BOOL res = ::GetFileSecurityW(fs2us(path), securInfo, TempSecureBuf, (DWORD)TempSecureBuf.Size(), &secureSize);
+ if (res)
+ {
+ if (secureSize == 0)
+ return;
+ if (secureSize > TempSecureBuf.Size())
+ errorCode = ERROR_INVALID_FUNCTION;
+ }
+ else
+ {
+ errorCode = GetLastError();
+ if (errorCode == ERROR_INSUFFICIENT_BUFFER)
+ {
+ if (secureSize <= TempSecureBuf.Size())
+ errorCode = ERROR_INVALID_FUNCTION;
+ else
+ {
+ TempSecureBuf.Alloc(secureSize);
+ res = ::GetFileSecurityW(fs2us(path), securInfo, TempSecureBuf, (DWORD)TempSecureBuf.Size(), &secureSize);
+ if (res)
+ {
+ if (secureSize != TempSecureBuf.Size())
+ errorCode = ERROR_INVALID_FUNCTION;;
+ }
+ else
+ errorCode = GetLastError();
+ }
+ }
+ }
+ if (res)
+ {
+ secureIndex = SecureBlocks.AddUniq(TempSecureBuf, secureSize);
+ return;
+ }
+ if (errorCode == 0)
+ errorCode = ERROR_INVALID_FUNCTION;
+ AddError(path, errorCode);
+}
+
+#endif
+
+void CDirItems::EnumerateDir(int phyParent, int logParent, const FString &phyPrefix)
{
- NFind::CEnumeratorW enumerator(phyPrefix + (wchar_t)kAnyStringWildcard);
+ NFind::CEnumerator enumerator(phyPrefix + FCHAR_ANY_MASK);
for (;;)
{
- NFind::CFileInfoW fi;
+ NFind::CFileInfo fi;
bool found;
if (!enumerator.Next(fi, found))
{
- errorCodes.Add(::GetLastError());
- errorPaths.Add(phyPrefix);
+ AddError(phyPrefix);
return;
}
if (!found)
break;
- AddDirFileInfo(phyParent, logParent, fi, Items);
+
+ int secureIndex = -1;
+ #ifdef _USE_SECURITY_CODE
+ if (ReadSecure)
+ AddSecurityItem(phyPrefix + fi.Name, secureIndex);
+ #endif
+
+ AddDirFileInfo(phyParent, logParent, secureIndex, fi, Items);
+
if (fi.IsDir())
{
- const UString name2 = fi.Name + (wchar_t)kDirDelimiter;
- int parent = AddPrefix(phyParent, logParent, name2);
- EnumerateDirectory(parent, parent, phyPrefix + name2, errorPaths, errorCodes);
+ const FString name2 = fi.Name + FCHAR_PATH_SEPARATOR;
+ unsigned parent = AddPrefix(phyParent, logParent, fs2us(name2));
+ EnumerateDir(parent, parent, phyPrefix + name2);
}
}
}
-void CDirItems::EnumerateDirItems2(const UString &phyPrefix, const UString &logPrefix,
- const UStringVector &filePaths, UStringVector &errorPaths, CRecordVector<DWORD> &errorCodes)
+void CDirItems::EnumerateItems2(
+ const FString &phyPrefix,
+ const UString &logPrefix,
+ const FStringVector &filePaths,
+ FStringVector *requestedPaths)
{
- int phyParent = phyPrefix.IsEmpty() ? -1 : AddPrefix(-1, -1, phyPrefix);
+ int phyParent = phyPrefix.IsEmpty() ? -1 : AddPrefix(-1, -1, fs2us(phyPrefix));
int logParent = logPrefix.IsEmpty() ? -1 : AddPrefix(-1, -1, logPrefix);
- for (int i = 0; i < filePaths.Size(); i++)
+ FOR_VECTOR (i, filePaths)
{
- const UString &filePath = filePaths[i];
- NFind::CFileInfoW fi;
- const UString phyPath = phyPrefix + filePath;
+ const FString &filePath = filePaths[i];
+ NFind::CFileInfo fi;
+ const FString phyPath = phyPrefix + filePath;
if (!fi.Find(phyPath))
{
- errorCodes.Add(::GetLastError());
- errorPaths.Add(phyPath);
+ AddError(phyPath);
continue;
}
- int delimiter = filePath.ReverseFind((wchar_t)kDirDelimiter);
- UString phyPrefixCur;
+ if (requestedPaths)
+ requestedPaths->Add(phyPath);
+
+ int delimiter = filePath.ReverseFind(FCHAR_PATH_SEPARATOR);
+ FString phyPrefixCur;
int phyParentCur = phyParent;
if (delimiter >= 0)
{
- phyPrefixCur = filePath.Left(delimiter + 1);
- phyParentCur = AddPrefix(phyParent, logParent, phyPrefixCur);
+ phyPrefixCur.SetFrom(filePath, delimiter + 1);
+ phyParentCur = AddPrefix(phyParent, logParent, fs2us(phyPrefixCur));
}
- AddDirFileInfo(phyParentCur, logParent, fi, Items);
+
+ int secureIndex = -1;
+ #ifdef _USE_SECURITY_CODE
+ if (ReadSecure)
+ AddSecurityItem(phyPath, secureIndex);
+ #endif
+
+ AddDirFileInfo(phyParentCur, logParent, secureIndex, fi, Items);
+
if (fi.IsDir())
{
- const UString name2 = fi.Name + (wchar_t)kDirDelimiter;
- int parent = AddPrefix(phyParentCur, logParent, name2);
- EnumerateDirectory(parent, parent, phyPrefix + phyPrefixCur + name2, errorPaths, errorCodes);
+ const FString name2 = fi.Name + FCHAR_PATH_SEPARATOR;
+ unsigned parent = AddPrefix(phyParentCur, logParent, fs2us(name2));
+ EnumerateDir(parent, parent, phyPrefix + phyPrefixCur + name2);
}
}
ReserveDown();
}
-static HRESULT EnumerateDirItems(const NWildcard::CCensorNode &curNode,
- int phyParent, int logParent, const UString &phyPrefix,
+
+
+
+
+
+static HRESULT EnumerateDirItems(
+ const NWildcard::CCensorNode &curNode,
+ int phyParent, int logParent, const FString &phyPrefix,
const UStringVector &addArchivePrefix,
CDirItems &dirItems,
bool enterToSubFolders,
- IEnumDirItemCallback *callback,
- UStringVector &errorPaths,
- CRecordVector<DWORD> &errorCodes);
+ IEnumDirItemCallback *callback);
-static HRESULT EnumerateDirItems_Spec(const NWildcard::CCensorNode &curNode,
- int phyParent, int logParent, const UString &curFolderName,
- const UString &phyPrefix,
+static HRESULT EnumerateDirItems_Spec(
+ const NWildcard::CCensorNode &curNode,
+ int phyParent, int logParent, const FString &curFolderName,
+ const FString &phyPrefix,
const UStringVector &addArchivePrefix,
CDirItems &dirItems,
bool enterToSubFolders,
- IEnumDirItemCallback *callback,
- UStringVector &errorPaths,
- CRecordVector<DWORD> &errorCodes)
-
+ IEnumDirItemCallback *callback)
{
- const UString name2 = curFolderName + (wchar_t)kDirDelimiter;
- int parent = dirItems.AddPrefix(phyParent, logParent, name2);
- int numItems = dirItems.Items.Size();
- HRESULT res = EnumerateDirItems(curNode, parent, parent, phyPrefix + name2,
- addArchivePrefix, dirItems, enterToSubFolders, callback, errorPaths, errorCodes);
+ const FString name2 = curFolderName + FCHAR_PATH_SEPARATOR;
+ unsigned parent = dirItems.AddPrefix(phyParent, logParent, fs2us(name2));
+ unsigned numItems = dirItems.Items.Size();
+ HRESULT res = EnumerateDirItems(
+ curNode, parent, parent, phyPrefix + name2,
+ addArchivePrefix, dirItems, enterToSubFolders, callback);
if (numItems == dirItems.Items.Size())
dirItems.DeleteLastPrefix();
return res;
}
+#if 0 // #ifndef UNDER_CE
-static HRESULT EnumerateDirItems(const NWildcard::CCensorNode &curNode,
- int phyParent, int logParent, const UString &phyPrefix,
+static void EnumerateAltStreams(
+ const NFind::CFileInfo &fi,
+ const NWildcard::CCensorNode &curNode,
+ int phyParent, int logParent, const FString &phyPrefix,
+ const UStringVector &addArchivePrefix, // prefix from curNode
+ CDirItems &dirItems)
+{
+ const FString fullPath = phyPrefix + fi.Name;
+ NFind::CStreamEnumerator enumerator(fullPath);
+ for (;;)
+ {
+ NFind::CStreamInfo si;
+ bool found;
+ if (!enumerator.Next(si, found))
+ {
+ dirItems.AddError(fullPath + FTEXT(":*"), (DWORD)E_FAIL);
+ break;
+ }
+ if (!found)
+ break;
+ if (si.IsMainStream())
+ continue;
+ UStringVector addArchivePrefixNew = addArchivePrefix;
+ UString reducedName = si.GetReducedName();
+ addArchivePrefixNew.Back() += reducedName;
+ if (curNode.CheckPathToRoot(false, addArchivePrefixNew, true))
+ continue;
+ NFind::CFileInfo fi2 = fi;
+ fi2.Name += us2fs(reducedName);
+ fi2.Size = si.Size;
+ fi2.Attrib &= ~FILE_ATTRIBUTE_DIRECTORY;
+ fi2.IsAltStream = true;
+ AddDirFileInfo(phyParent, logParent, -1, fi2, dirItems.Items);
+ dirItems.TotalSize += fi2.Size;
+ }
+}
+
+void CDirItems::SetLinkInfo(CDirItem &dirItem, const NFind::CFileInfo &fi,
+ const FString &phyPrefix)
+{
+ if (!SymLinks || !fi.HasReparsePoint())
+ return;
+ const FString path = phyPrefix + fi.Name;
+ CByteBuffer &buf = dirItem.ReparseData;
+ if (NIO::GetReparseData(path, buf))
+ {
+ CReparseAttr attr;
+ if (attr.Parse(buf, buf.Size()))
+ return;
+ }
+ AddError(path);
+ buf.Free();
+}
+
+#endif
+
+static HRESULT EnumerateForItem(
+ NFind::CFileInfo &fi,
+ const NWildcard::CCensorNode &curNode,
+ int phyParent, int logParent, const FString &phyPrefix,
const UStringVector &addArchivePrefix, // prefix from curNode
CDirItems &dirItems,
bool enterToSubFolders,
- IEnumDirItemCallback *callback,
- UStringVector &errorPaths,
- CRecordVector<DWORD> &errorCodes)
+ IEnumDirItemCallback *callback)
+{
+ const UString name = fs2us(fi.Name);
+ bool enterToSubFolders2 = enterToSubFolders;
+ UStringVector addArchivePrefixNew = addArchivePrefix;
+ addArchivePrefixNew.Add(name);
+ {
+ UStringVector addArchivePrefixNewTemp(addArchivePrefixNew);
+ if (curNode.CheckPathToRoot(false, addArchivePrefixNewTemp, !fi.IsDir()))
+ return S_OK;
+ }
+ int dirItemIndex = -1;
+
+ if (curNode.CheckPathToRoot(true, addArchivePrefixNew, !fi.IsDir()))
+ {
+ int secureIndex = -1;
+ #ifdef _USE_SECURITY_CODE
+ if (dirItems.ReadSecure)
+ dirItems.AddSecurityItem(phyPrefix + fi.Name, secureIndex);
+ #endif
+
+ dirItemIndex = dirItems.Items.Size();
+ AddDirFileInfo(phyParent, logParent, secureIndex, fi, dirItems.Items);
+ dirItems.TotalSize += fi.Size;
+ if (fi.IsDir())
+ enterToSubFolders2 = true;
+ }
+
+ #if 0 // #ifndef UNDER_CE
+ if (dirItems.ScanAltStreams)
+ {
+ EnumerateAltStreams(fi, curNode, phyParent, logParent, phyPrefix,
+ addArchivePrefixNew, dirItems);
+ }
+
+ if (dirItemIndex >= 0)
+ {
+ CDirItem &dirItem = dirItems.Items[dirItemIndex];
+ dirItems.SetLinkInfo(dirItem, fi, phyPrefix);
+ if (dirItem.ReparseData.Size() != 0)
+ return S_OK;
+ }
+ #endif
+
+ if (!fi.IsDir())
+ return S_OK;
+
+ const NWildcard::CCensorNode *nextNode = 0;
+ if (addArchivePrefix.IsEmpty())
+ {
+ int index = curNode.FindSubNode(name);
+ if (index >= 0)
+ nextNode = &curNode.SubNodes[index];
+ }
+ if (!enterToSubFolders2 && nextNode == 0)
+ return S_OK;
+
+ addArchivePrefixNew = addArchivePrefix;
+ if (nextNode == 0)
+ {
+ nextNode = &curNode;
+ addArchivePrefixNew.Add(name);
+ }
+
+ return EnumerateDirItems_Spec(
+ *nextNode, phyParent, logParent, fi.Name, phyPrefix,
+ addArchivePrefixNew,
+ dirItems,
+ enterToSubFolders2, callback);
+}
+
+
+static bool CanUseFsDirect(const NWildcard::CCensorNode &curNode)
+{
+ FOR_VECTOR (i, curNode.IncludeItems)
+ {
+ const NWildcard::CItem &item = curNode.IncludeItems[i];
+ if (item.Recursive || item.PathParts.Size() != 1)
+ return false;
+ const UString &name = item.PathParts.Front();
+ if (name.IsEmpty())
+ return false;
+
+ /* Windows doesn't support file name with wildcard.
+ but if another system supports file name with wildcard,
+ and wildcard mode is disabled, we can ignore wildcard in name */
+ /*
+ if (!item.WildcardParsing)
+ continue;
+ */
+ if (DoesNameContainWildcard(name))
+ return false;
+ }
+ return true;
+}
+
+
+static HRESULT EnumerateDirItems(
+ const NWildcard::CCensorNode &curNode,
+ int phyParent, int logParent, const FString &phyPrefix,
+ const UStringVector &addArchivePrefix, // prefix from curNode
+ CDirItems &dirItems,
+ bool enterToSubFolders,
+ IEnumDirItemCallback *callback)
{
if (!enterToSubFolders)
if (curNode.NeedCheckSubDirs())
enterToSubFolders = true;
if (callback)
- RINOK(callback->ScanProgress(dirItems.GetNumFolders(), dirItems.Items.Size(), phyPrefix));
+ RINOK(callback->ScanProgress(dirItems.GetNumFolders(), dirItems.Items.Size(), dirItems.TotalSize, fs2us(phyPrefix), true));
// try direct_names case at first
if (addArchivePrefix.IsEmpty() && !enterToSubFolders)
{
- // check that all names are direct
- int i;
- for (i = 0; i < curNode.IncludeItems.Size(); i++)
- {
- const NWildcard::CItem &item = curNode.IncludeItems[i];
- if (item.Recursive || item.PathParts.Size() != 1)
- break;
- const UString &name = item.PathParts.Front();
- if (name.IsEmpty() || DoesNameContainWildCard(name))
- break;
- }
- if (i == curNode.IncludeItems.Size())
+ if (CanUseFsDirect(curNode))
{
// all names are direct (no wildcards)
// so we don't need file_system's dir enumerator
CRecordVector<bool> needEnterVector;
+ unsigned i;
+
for (i = 0; i < curNode.IncludeItems.Size(); i++)
{
const NWildcard::CItem &item = curNode.IncludeItems[i];
const UString &name = item.PathParts.Front();
- const UString fullPath = phyPrefix + name;
- NFind::CFileInfoW fi;
+ const FString fullPath = phyPrefix + us2fs(name);
+ NFind::CFileInfo fi;
+ #ifdef _WIN32
+ if (phyPrefix.IsEmpty() && item.IsDriveItem())
+ {
+ fi.SetAsDir();
+ fi.Name = fullPath;
+ }
+ else
+ #endif
if (!fi.Find(fullPath))
{
- errorCodes.Add(::GetLastError());
- errorPaths.Add(fullPath);
+ dirItems.AddError(fullPath);
continue;
}
bool isDir = fi.IsDir();
if (isDir && !item.ForDir || !isDir && !item.ForFile)
{
- errorCodes.Add((DWORD)E_FAIL);
- errorPaths.Add(fullPath);
+ dirItems.AddError(fullPath, (DWORD)E_FAIL);
continue;
}
{
UStringVector pathParts;
- pathParts.Add(fi.Name);
+ pathParts.Add(fs2us(fi.Name));
if (curNode.CheckPathToRoot(false, pathParts, !isDir))
continue;
}
- AddDirFileInfo(phyParent, logParent, fi, dirItems.Items);
+
+ int secureIndex = -1;
+ #ifdef _USE_SECURITY_CODE
+ if (dirItems.ReadSecure)
+ dirItems.AddSecurityItem(fullPath, secureIndex);
+ #endif
+
+ AddDirFileInfo(phyParent, logParent, secureIndex, fi, dirItems.Items);
+
+ #if 0 // #ifndef UNDER_CE
+ {
+ CDirItem &dirItem = dirItems.Items.Back();
+ dirItems.SetLinkInfo(dirItem, fi, phyPrefix);
+ if (dirItem.ReparseData.Size() != 0)
+ continue;
+ }
+ #endif
+
+ dirItems.TotalSize += fi.Size;
+
+ #if 0 // #ifndef UNDER_CE
+ if (dirItems.ScanAltStreams)
+ {
+ UStringVector pathParts;
+ pathParts.Add(fs2us(fi.Name));
+ EnumerateAltStreams(fi, curNode, phyParent, logParent, phyPrefix,
+ pathParts, dirItems);
+ }
+ #endif
+
if (!isDir)
continue;
-
+
UStringVector addArchivePrefixNew;
const NWildcard::CCensorNode *nextNode = 0;
int index = curNode.FindSubNode(name);
@@ -252,110 +546,212 @@ static HRESULT EnumerateDirItems(const NWildcard::CCensorNode &curNode,
}
RINOK(EnumerateDirItems_Spec(*nextNode, phyParent, logParent, fi.Name, phyPrefix,
- addArchivePrefixNew, dirItems, true, callback, errorPaths, errorCodes));
+ addArchivePrefixNew, dirItems, true, callback));
}
+
for (i = 0; i < curNode.SubNodes.Size(); i++)
{
if (i < needEnterVector.Size())
if (!needEnterVector[i])
continue;
const NWildcard::CCensorNode &nextNode = curNode.SubNodes[i];
- const UString fullPath = phyPrefix + nextNode.Name;
- NFind::CFileInfoW fi;
- if (!fi.Find(fullPath))
+ const FString fullPath = phyPrefix + us2fs(nextNode.Name);
+ NFind::CFileInfo fi;
+ #ifdef _WIN32
+ if (phyPrefix.IsEmpty() && NWildcard::IsDriveColonName(nextNode.Name))
+ {
+ fi.SetAsDir();
+ fi.Name = fullPath;
+ }
+ else
+ #endif
+ if (!fi.Find(fullPath,true))
{
if (!nextNode.AreThereIncludeItems())
continue;
- errorCodes.Add(::GetLastError());
- errorPaths.Add(fullPath);
+ dirItems.AddError(fullPath);
continue;
}
if (!fi.IsDir())
{
- errorCodes.Add((DWORD)E_FAIL);
- errorPaths.Add(fullPath);
+ dirItems.AddError(fullPath, (DWORD)E_FAIL);
continue;
}
RINOK(EnumerateDirItems_Spec(nextNode, phyParent, logParent, fi.Name, phyPrefix,
- UStringVector(), dirItems, false, callback, errorPaths, errorCodes));
+ UStringVector(), dirItems, false, callback));
}
+
return S_OK;
}
}
+ #ifdef _WIN32
+ #ifndef UNDER_CE
- NFind::CEnumeratorW enumerator(phyPrefix + wchar_t(kAnyStringWildcard));
- for (int ttt = 0; ; ttt++)
- {
- NFind::CFileInfoW fi;
- bool found;
- if (!enumerator.Next(fi, found))
- {
- errorCodes.Add(::GetLastError());
- errorPaths.Add(phyPrefix);
- break;
- }
- if (!found)
- break;
+ // scan drives, if wildcard is "*:\"
- if (callback && (ttt & 0xFF) == 0xFF)
- RINOK(callback->ScanProgress(dirItems.GetNumFolders(), dirItems.Items.Size(), phyPrefix));
- const UString &name = fi.Name;
- bool enterToSubFolders2 = enterToSubFolders;
- UStringVector addArchivePrefixNew = addArchivePrefix;
- addArchivePrefixNew.Add(name);
+ if (phyPrefix.IsEmpty() && curNode.IncludeItems.Size() > 0)
+ {
+ unsigned i;
+ for (i = 0; i < curNode.IncludeItems.Size(); i++)
{
- UStringVector addArchivePrefixNewTemp(addArchivePrefixNew);
- if (curNode.CheckPathToRoot(false, addArchivePrefixNewTemp, !fi.IsDir()))
+ const NWildcard::CItem &item = curNode.IncludeItems[i];
+ if (item.PathParts.Size() < 1)
+ break;
+ const UString &name = item.PathParts.Front();
+ if (name.Len() != 2 || name[1] != ':')
+ break;
+ if (item.PathParts.Size() == 1)
+ if (item.ForFile || !item.ForDir)
+ break;
+ if (NWildcard::IsDriveColonName(name))
continue;
+ if (name[0] != '*' && name[0] != '?')
+ break;
}
- if (curNode.CheckPathToRoot(true, addArchivePrefixNew, !fi.IsDir()))
+ if (i == curNode.IncludeItems.Size())
{
- AddDirFileInfo(phyParent, logParent, fi, dirItems.Items);
- if (fi.IsDir())
- enterToSubFolders2 = true;
- }
- if (!fi.IsDir())
- continue;
+ FStringVector driveStrings;
+ NFind::MyGetLogicalDriveStrings(driveStrings);
+ for (i = 0; i < driveStrings.Size(); i++)
+ {
+ FString driveName = driveStrings[i];
+ if (driveName.Len() < 3 || driveName.Back() != '\\')
+ return E_FAIL;
+ driveName.DeleteBack();
+ NFind::CFileInfo fi;
+ fi.SetAsDir();
+ fi.Name = driveName;
- const NWildcard::CCensorNode *nextNode = 0;
- if (addArchivePrefix.IsEmpty())
- {
- int index = curNode.FindSubNode(name);
- if (index >= 0)
- nextNode = &curNode.SubNodes[index];
+ RINOK(EnumerateForItem(fi, curNode, phyParent, logParent, phyPrefix,
+ addArchivePrefix, dirItems, enterToSubFolders, callback));
+ }
+ return S_OK;
}
- if (!enterToSubFolders2 && nextNode == 0)
- continue;
+ }
+
+ #endif
+ #endif
- addArchivePrefixNew = addArchivePrefix;
- if (nextNode == 0)
+ NFind::CEnumerator enumerator(phyPrefix + FCHAR_ANY_MASK);
+ for (unsigned ttt = 0; ; ttt++)
+ {
+ NFind::CFileInfo fi;
+ bool found;
+ if (!enumerator.Next(fi, found))
{
- nextNode = &curNode;
- addArchivePrefixNew.Add(name);
+ dirItems.AddError(phyPrefix);
+ break;
}
+ if (!found)
+ break;
- RINOK(EnumerateDirItems_Spec(*nextNode, phyParent, logParent, name, phyPrefix,
- addArchivePrefixNew, dirItems, enterToSubFolders2, callback, errorPaths, errorCodes));
+ if (callback && (ttt & 0xFF) == 0xFF)
+ RINOK(callback->ScanProgress(dirItems.GetNumFolders(), dirItems.Items.Size(), dirItems.TotalSize, fs2us(phyPrefix), true));
+
+ RINOK(EnumerateForItem(fi, curNode, phyParent, logParent, phyPrefix,
+ addArchivePrefix, dirItems, enterToSubFolders, callback));
}
return S_OK;
}
HRESULT EnumerateItems(
const NWildcard::CCensor &censor,
+ const NWildcard::ECensorPathMode pathMode,
+ const UString &addPathPrefix,
CDirItems &dirItems,
- IEnumDirItemCallback *callback,
- UStringVector &errorPaths,
- CRecordVector<DWORD> &errorCodes)
+ IEnumDirItemCallback *callback)
{
- for (int i = 0; i < censor.Pairs.Size(); i++)
+ FOR_VECTOR (i, censor.Pairs)
{
const NWildcard::CPair &pair = censor.Pairs[i];
int phyParent = pair.Prefix.IsEmpty() ? -1 : dirItems.AddPrefix(-1, -1, pair.Prefix);
- RINOK(EnumerateDirItems(pair.Head, phyParent, -1, pair.Prefix, UStringVector(), dirItems, false,
- callback, errorPaths, errorCodes));
+ int logParent = -1;
+
+ if (pathMode == NWildcard::k_AbsPath)
+ logParent = phyParent;
+ else
+ {
+ if (!addPathPrefix.IsEmpty())
+ logParent = dirItems.AddPrefix(-1, -1, addPathPrefix);
+ }
+
+ RINOK(EnumerateDirItems(pair.Head, phyParent, logParent, us2fs(pair.Prefix), UStringVector(),
+ dirItems,
+ false, // enterToSubFolders
+ callback));
}
dirItems.ReserveDown();
+
+ #if defined(_WIN32) && !defined(UNDER_CE)
+ dirItems.FillFixedReparse();
+ #endif
+
return S_OK;
}
+
+#if defined(_WIN32) && !defined(UNDER_CE)
+
+void CDirItems::FillFixedReparse()
+{
+ /* imagex/WIM reduces absolute pathes in links (raparse data),
+ if we archive non root folder. We do same thing here */
+
+ if (!SymLinks)
+ return;
+
+ FOR_VECTOR(i, Items)
+ {
+ CDirItem &item = Items[i];
+ if (item.ReparseData.Size() == 0)
+ continue;
+
+ CReparseAttr attr;
+ if (!attr.Parse(item.ReparseData, item.ReparseData.Size()))
+ continue;
+ if (attr.IsRelative())
+ continue;
+
+ const UString &link = attr.GetPath();
+ if (!IsDrivePath(link))
+ continue;
+ // maybe we need to support networks paths also ?
+
+ FString fullPathF;
+ if (!NDir::MyGetFullPathName(us2fs(GetPhyPath(i)), fullPathF))
+ continue;
+ UString fullPath = fs2us(fullPathF);
+ const UString logPath = GetLogPath(i);
+ if (logPath.Len() >= fullPath.Len())
+ continue;
+ if (CompareFileNames(logPath, fullPath.RightPtr(logPath.Len())) != 0)
+ continue;
+
+ const UString prefix = fullPath.Left(fullPath.Len() - logPath.Len());
+ if (prefix.Back() != WCHAR_PATH_SEPARATOR)
+ continue;
+
+ unsigned rootPrefixSize = GetRootPrefixSize(prefix);
+ if (rootPrefixSize == 0)
+ continue;
+ if (rootPrefixSize == prefix.Len())
+ continue; // simple case: paths are from root
+
+ if (link.Len() <= prefix.Len())
+ continue;
+
+ if (CompareFileNames(link.Left(prefix.Len()), prefix) != 0)
+ continue;
+
+ UString newLink = prefix.Left(rootPrefixSize);
+ newLink += link.Ptr(prefix.Len());
+
+ CByteBuffer data;
+ if (!FillLinkData(data, newLink, attr.IsSymLink()))
+ continue;
+ item.ReparseData2 = data;
+ }
+}
+
+#endif
diff --git a/src/libs/7zip/unix/CPP/7zip/UI/Common/EnumDirItems.h b/src/libs/7zip/unix/CPP/7zip/UI/Common/EnumDirItems.h
index d0ce950e3..803a64e7d 100644
--- a/src/libs/7zip/unix/CPP/7zip/UI/Common/EnumDirItems.h
+++ b/src/libs/7zip/unix/CPP/7zip/UI/Common/EnumDirItems.h
@@ -3,23 +3,25 @@
#ifndef __ENUM_DIR_ITEMS_H
#define __ENUM_DIR_ITEMS_H
-#include "Common/Wildcard.h"
-#include "Windows/FileFind.h"
+#include "../../../Common/Wildcard.h"
+
+#include "../../../Windows/FileFind.h"
+
#include "DirItem.h"
-void AddDirFileInfo(int phyParent, int logParent,
- const NWindows::NFile::NFind::CFileInfoW &fi, CObjectVector<CDirItem> &dirItems);
+void AddDirFileInfo(int phyParent, int logParent, int secureIndex,
+ const NWindows::NFile::NFind::CFileInfo &fi, CObjectVector<CDirItem> &dirItems);
struct IEnumDirItemCallback
{
- virtual HRESULT ScanProgress(UInt64 numFolders, UInt64 numFiles, const wchar_t *path) = 0;
+ virtual HRESULT ScanProgress(UInt64 numFolders, UInt64 numFiles, UInt64 totalSize, const wchar_t *path, bool isDir) = 0;
};
HRESULT EnumerateItems(
const NWildcard::CCensor &censor,
+ NWildcard::ECensorPathMode pathMode,
+ const UString &addPathPrefix,
CDirItems &dirItems,
- IEnumDirItemCallback *callback,
- UStringVector &errorPaths,
- CRecordVector<DWORD> &errorCodes);
+ IEnumDirItemCallback *callback);
#endif
diff --git a/src/libs/7zip/unix/CPP/7zip/UI/Common/ExitCode.h b/src/libs/7zip/unix/CPP/7zip/UI/Common/ExitCode.h
deleted file mode 100644
index b6d7d4dfc..000000000
--- a/src/libs/7zip/unix/CPP/7zip/UI/Common/ExitCode.h
+++ /dev/null
@@ -1,27 +0,0 @@
-// ExitCode.h
-
-#ifndef __EXIT_CODE_H
-#define __EXIT_CODE_H
-
-namespace NExitCode {
-
-enum EEnum {
-
- kSuccess = 0, // Successful operation
- kWarning = 1, // Non fatal error(s) occurred
- kFatalError = 2, // A fatal error occurred
- // kCRCError = 3, // A CRC error occurred when unpacking
- // kLockedArchive = 4, // Attempt to modify an archive previously locked
- // kWriteError = 5, // Write to disk error
- // kOpenError = 6, // Open file error
- kUserError = 7, // Command line option error
- kMemoryError = 8, // Not enough memory for operation
- // kCreateFileError = 9, // Create file error
-
- kUserBreak = 255 // User stopped the process
-
-};
-
-}
-
-#endif
diff --git a/src/libs/7zip/unix/CPP/7zip/UI/Common/Extract.cpp b/src/libs/7zip/unix/CPP/7zip/UI/Common/Extract.cpp
index ca2c8c73d..5f94254ef 100644
--- a/src/libs/7zip/unix/CPP/7zip/UI/Common/Extract.cpp
+++ b/src/libs/7zip/unix/CPP/7zip/UI/Common/Extract.cpp
@@ -2,11 +2,11 @@
#include "StdAfx.h"
-#include <stdio.h>
+#include "../../../Common/StringConvert.h"
-#include "Windows/FileDir.h"
-#include "Windows/PropVariant.h"
-#include "Windows/PropVariantConversions.h"
+#include "../../../Windows/FileDir.h"
+#include "../../../Windows/PropVariant.h"
+#include "../../../Windows/PropVariantConv.h"
#include "../Common/ExtractingFilePath.h"
@@ -14,135 +14,251 @@
#include "SetProperties.h"
using namespace NWindows;
+using namespace NFile;
+using namespace NDir;
static HRESULT DecompressArchive(
- const CArc &arc,
+ CCodecs *codecs,
+ const CArchiveLink &arcLink,
UInt64 packSize,
const NWildcard::CCensorNode &wildcardCensor,
const CExtractOptions &options,
+ bool calcCrc,
IExtractCallbackUI *callback,
- CArchiveExtractCallback *extractCallbackSpec,
+ CArchiveExtractCallback *ecs,
UString &errorMessage,
UInt64 &stdInProcessed)
{
+ const CArc &arc = arcLink.Arcs.Back();
stdInProcessed = 0;
IInArchive *archive = arc.Archive;
CRecordVector<UInt32> realIndices;
+
+ UStringVector removePathParts;
+
+ FString outDir = options.OutputDir;
+ UString replaceName = arc.DefaultName;
+
+ if (arcLink.Arcs.Size() > 1)
+ {
+ // Most "pe" archives have same name of archive subfile "[0]" or ".rsrc_1".
+ // So it extracts different archives to one folder.
+ // We will use top level archive name
+ const CArc &arc0 = arcLink.Arcs[0];
+ if (StringsAreEqualNoCase_Ascii(codecs->Formats[arc0.FormatIndex].Name, "pe"))
+ replaceName = arc0.DefaultName;
+ }
+
+ outDir.Replace(FSTRING_ANY_MASK, us2fs(GetCorrectFsPath(replaceName)));
+
+ bool elimIsPossible = false;
+ UString elimPrefix; // only pure name without dir delimiter
+ FString outDirReduced = outDir;
+
+ if (options.ElimDup.Val)
+ {
+ UString dirPrefix;
+ SplitPathToParts_Smart(fs2us(outDir), dirPrefix, elimPrefix);
+ if (!elimPrefix.IsEmpty())
+ {
+ if (IsCharDirLimiter(elimPrefix.Back()))
+ elimPrefix.DeleteBack();
+ if (!elimPrefix.IsEmpty())
+ {
+ outDirReduced = us2fs(dirPrefix);
+ elimIsPossible = true;
+ }
+ }
+ }
+
if (!options.StdInMode)
{
UInt32 numItems;
RINOK(archive->GetNumberOfItems(&numItems));
-
+
+ UString filePath;
+
for (UInt32 i = 0; i < numItems; i++)
{
- UString filePath;
RINOK(arc.GetItemPath(i, filePath));
+
+ if (elimIsPossible && options.ElimDup.Val)
+ {
+ if (!IsPath1PrefixedByPath2(filePath, elimPrefix))
+ elimIsPossible = false;
+ else
+ {
+ wchar_t c = filePath[elimPrefix.Len()];
+ if (c != 0 && !IsCharDirLimiter(c))
+ elimIsPossible = false;
+ }
+ }
+
bool isFolder;
- RINOK(IsArchiveItemFolder(archive, i, isFolder));
- if (!wildcardCensor.CheckPath(filePath, !isFolder))
+ RINOK(Archive_IsItem_Folder(archive, i, isFolder));
+ bool isAltStream;
+ RINOK(Archive_IsItem_AltStream(archive, i, isAltStream));
+ if (!options.NtOptions.AltStreams.Val && isAltStream)
+ continue;
+ if (!wildcardCensor.CheckPath(isAltStream, filePath, !isFolder))
continue;
realIndices.Add(i);
}
+
if (realIndices.Size() == 0)
{
callback->ThereAreNoFiles();
- return S_OK;
+ return callback->ExtractResult(S_OK);
}
}
- UStringVector removePathParts;
+ if (elimIsPossible)
+ outDir = outDirReduced;
- UString outDir = options.OutputDir;
- outDir.Replace(L"*", GetCorrectFsPath(arc.DefaultName));
#ifdef _WIN32
// GetCorrectFullFsPath doesn't like "..".
// outDir.TrimRight();
// outDir = GetCorrectFullFsPath(outDir);
#endif
- if (!outDir.IsEmpty())
- if (!NFile::NDirectory::CreateComplexDirectory(outDir))
+ if (outDir.IsEmpty())
+ outDir = FString(FTEXT(".")) + FString(FSTRING_PATH_SEPARATOR);
+ else
+ if (!CreateComplexDir(outDir))
{
HRESULT res = ::GetLastError();
if (res == S_OK)
res = E_FAIL;
- errorMessage = ((UString)L"Can not create output directory ") + outDir;
+ errorMessage = ((UString)L"Can not create output directory ") + fs2us(outDir);
return res;
}
- extractCallbackSpec->Init(
+ ecs->Init(
+ options.NtOptions,
options.StdInMode ? &wildcardCensor : NULL,
&arc,
callback,
- options.StdOutMode, options.TestMode, options.CalcCrc,
+ options.StdOutMode, options.TestMode,
outDir,
removePathParts,
packSize);
- #if !defined(_7ZIP_ST) && !defined(_SFX)
- RINOK(SetProperties(archive, options.Properties));
+
+ #ifdef SUPPORT_LINKS
+
+ if (!options.StdInMode &&
+ !options.TestMode &&
+ options.NtOptions.HardLinks.Val)
+ {
+ RINOK(ecs->PrepareHardLinks(&realIndices));
+ }
+
#endif
+
HRESULT result;
- Int32 testMode = (options.TestMode && !options.CalcCrc) ? 1: 0;
+ Int32 testMode = (options.TestMode && !calcCrc) ? 1: 0;
if (options.StdInMode)
{
- result = archive->Extract(NULL, (UInt32)(Int32)-1, testMode, extractCallbackSpec);
+ result = archive->Extract(NULL, (UInt32)(Int32)-1, testMode, ecs);
NCOM::CPropVariant prop;
if (archive->GetArchiveProperty(kpidPhySize, &prop) == S_OK)
- if (prop.vt == VT_UI8 || prop.vt == VT_UI4)
- stdInProcessed = ConvertPropVariantToUInt64(prop);
+ ConvertPropVariantToUInt64(prop, stdInProcessed);
}
else
- result = archive->Extract(&realIndices.Front(), realIndices.Size(), testMode, extractCallbackSpec);
-
+ result = archive->Extract(&realIndices.Front(), realIndices.Size(), testMode, ecs);
+ if (result == S_OK && !options.StdInMode)
+ result = ecs->SetDirsTimes();
return callback->ExtractResult(result);
}
-HRESULT DecompressArchives(
- CCodecs *codecs, const CIntVector &formatIndices,
+/* v9.31: BUG was fixed:
+ Sorted list for file paths was sorted with case insensitive compare function.
+ But FindInSorted function did binary search via case sensitive compare function */
+
+int Find_FileName_InSortedVector(const UStringVector &fileName, const UString &name)
+{
+ unsigned left = 0, right = fileName.Size();
+ while (left != right)
+ {
+ unsigned mid = (left + right) / 2;
+ const UString &midValue = fileName[mid];
+ int compare = CompareFileNames(name, midValue);
+ if (compare == 0)
+ return mid;
+ if (compare < 0)
+ right = mid;
+ else
+ left = mid + 1;
+ }
+ return -1;
+}
+
+HRESULT Extract(
+ CCodecs *codecs,
+ const CObjectVector<COpenType> &types,
+ const CIntVector &excludedFormats,
UStringVector &arcPaths, UStringVector &arcPathsFull,
const NWildcard::CCensorNode &wildcardCensor,
const CExtractOptions &options,
IOpenCallbackUI *openCallback,
IExtractCallbackUI *extractCallback,
+ #ifndef _SFX
+ IHashCalc *hash,
+ #endif
UString &errorMessage,
CDecompressStat &stat)
{
stat.Clear();
- int i;
UInt64 totalPackSize = 0;
- CRecordVector<UInt64> archiveSizes;
+ CRecordVector<UInt64> arcSizes;
- int numArcs = options.StdInMode ? 1 : arcPaths.Size();
+ unsigned numArcs = options.StdInMode ? 1 : arcPaths.Size();
+ unsigned i;
for (i = 0; i < numArcs; i++)
{
- NFile::NFind::CFileInfoW fi;
+ NFind::CFileInfo fi;
fi.Size = 0;
if (!options.StdInMode)
{
- const UString &arcPath = arcPaths[i];
- if (!fi.Find(arcPath))
+ const FString &arcPath = us2fs(arcPaths[i]);
+ if (!fi.Find(arcPath,true))
throw "there is no such archive";
if (fi.IsDir())
throw "can't decompress folder";
}
- archiveSizes.Add(fi.Size);
+ arcSizes.Add(fi.Size);
totalPackSize += fi.Size;
}
- CArchiveExtractCallback *extractCallbackSpec = new CArchiveExtractCallback;
- CMyComPtr<IArchiveExtractCallback> ec(extractCallbackSpec);
+
+ CBoolArr skipArcs(numArcs);
+ for (i = 0; i < numArcs; i++)
+ skipArcs[i] = false;
+
+ CArchiveExtractCallback *ecs = new CArchiveExtractCallback;
+ CMyComPtr<IArchiveExtractCallback> ec(ecs);
bool multi = (numArcs > 1);
- extractCallbackSpec->InitForMulti(multi, options.PathMode, options.OverwriteMode);
+ ecs->InitForMulti(multi, options.PathMode, options.OverwriteMode);
+ #ifndef _SFX
+ ecs->SetHashMethods(hash);
+ #endif
+
if (multi)
{
RINOK(extractCallback->SetTotal(totalPackSize));
}
+
+ UInt64 totalPackProcessed = 0;
+ bool thereAreNotOpenArcs = false;
+
for (i = 0; i < numArcs; i++)
{
+ if (skipArcs[i])
+ continue;
+
const UString &arcPath = arcPaths[i];
- NFile::NFind::CFileInfoW fi;
+ NFind::CFileInfo fi;
if (options.StdInMode)
{
fi.Size = 0;
@@ -150,7 +266,7 @@ HRESULT DecompressArchives(
}
else
{
- if (!fi.Find(arcPath) || fi.IsDir())
+ if (!fi.Find(us2fs(arcPath),true) || fi.IsDir())
throw "there is no such archive";
}
@@ -159,16 +275,17 @@ HRESULT DecompressArchives(
#endif
RINOK(extractCallback->BeforeOpen(arcPath));
- CArchiveLink archiveLink;
+ CArchiveLink arcLink;
- CIntVector formatIndices2 = formatIndices;
+ CObjectVector<COpenType> types2 = types;
+ /*
#ifndef _SFX
- if (formatIndices.IsEmpty())
+ if (types.IsEmpty())
{
int pos = arcPath.ReverseFind(L'.');
if (pos >= 0)
{
- UString s = arcPath.Mid(pos + 1);
+ UString s = arcPath.Ptr(pos + 1);
int index = codecs->FindFormatForExtension(s);
if (index >= 0 && s == L"001")
{
@@ -176,18 +293,31 @@ HRESULT DecompressArchives(
pos = s.ReverseFind(L'.');
if (pos >= 0)
{
- int index2 = codecs->FindFormatForExtension(s.Mid(pos + 1));
- if (index2 >= 0 && s.CompareNoCase(L"rar") != 0)
+ int index2 = codecs->FindFormatForExtension(s.Ptr(pos + 1));
+ if (index2 >= 0) // && s.CompareNoCase(L"rar") != 0
{
- formatIndices2.Add(index2);
- formatIndices2.Add(index);
+ types2.Add(index2);
+ types2.Add(index);
}
}
}
}
}
#endif
- HRESULT result = archiveLink.Open2(codecs, formatIndices2, options.StdInMode, NULL, arcPath, openCallback);
+ */
+
+ COpenOptions op;
+ #ifndef _SFX
+ op.props = &options.Properties;
+ #endif
+ op.codecs = codecs;
+ op.types = &types2;
+ op.excludedFormats = &excludedFormats;
+ op.stdInMode = options.StdInMode;
+ op.stream = NULL;
+ op.filePath = arcPath;
+ HRESULT result = arcLink.Open2(op, openCallback);
+
if (result == E_ABORT)
return result;
@@ -196,68 +326,148 @@ HRESULT DecompressArchives(
crypted = openCallback->Open_WasPasswordAsked();
#endif
+ if (arcLink.NonOpen_ErrorInfo.ErrorFormatIndex >= 0)
+ result = S_FALSE;
+
+ // arcLink.Set_ErrorsText();
RINOK(extractCallback->OpenResult(arcPath, result, crypted));
+
+
+ {
+ FOR_VECTOR (r, arcLink.Arcs)
+ {
+ const CArc &arc = arcLink.Arcs[r];
+ const CArcErrorInfo &er = arc.ErrorInfo;
+ if (er.IsThereErrorOrWarning())
+ {
+ RINOK(extractCallback->SetError(r, arc.Path,
+ er.GetErrorFlags(), er.ErrorMessage,
+ er.GetWarningFlags(), er.WarningMessage));
+ }
+ }
+ }
+
if (result != S_OK)
+ {
+ thereAreNotOpenArcs = true;
+ if (!options.StdInMode)
+ {
+ NFind::CFileInfo fi;
+ if (fi.Find(us2fs(arcPath)))
+ if (!fi.IsDir())
+ totalPackProcessed += fi.Size;
+ }
continue;
+ }
if (!options.StdInMode)
- for (int v = 0; v < archiveLink.VolumePaths.Size(); v++)
{
- int index = arcPathsFull.FindInSorted(archiveLink.VolumePaths[v]);
- if (index >= 0 && index > i)
+ // numVolumes += arcLink.VolumePaths.Size();
+ // arcLink.VolumesSize;
+
+ // totalPackSize -= DeleteUsedFileNamesFromList(arcLink, i + 1, arcPaths, arcPathsFull, &arcSizes);
+ // numArcs = arcPaths.Size();
+ if (arcLink.VolumePaths.Size() != 0)
{
- arcPaths.Delete(index);
- arcPathsFull.Delete(index);
- totalPackSize -= archiveSizes[index];
- archiveSizes.Delete(index);
- numArcs = arcPaths.Size();
+ Int64 correctionSize = arcLink.VolumesSize;
+ FOR_VECTOR (v, arcLink.VolumePaths)
+ {
+ int index = Find_FileName_InSortedVector(arcPathsFull, arcLink.VolumePaths[v]);
+ if (index >= 0)
+ {
+ if ((unsigned)index > i)
+ {
+ skipArcs[index] = true;
+ correctionSize -= arcSizes[index];
+ }
+ }
+ }
+ if (correctionSize != 0)
+ {
+ Int64 newPackSize = (Int64)totalPackSize + correctionSize;
+ if (newPackSize < 0)
+ newPackSize = 0;
+ totalPackSize = newPackSize;
+ RINOK(extractCallback->SetTotal(totalPackSize));
+ }
}
}
- if (archiveLink.VolumePaths.Size() != 0)
- {
- totalPackSize += archiveLink.VolumesSize;
- RINOK(extractCallback->SetTotal(totalPackSize));
- }
#ifndef _NO_CRYPTO
+ bool passwordIsDefined;
UString password;
- RINOK(openCallback->Open_GetPasswordIfAny(password));
- if (!password.IsEmpty())
+ RINOK(openCallback->Open_GetPasswordIfAny(passwordIsDefined, password));
+ if (passwordIsDefined)
{
RINOK(extractCallback->SetPassword(password));
}
#endif
- for (int v = 0; v < archiveLink.Arcs.Size(); v++)
+ FOR_VECTOR (k, arcLink.Arcs)
{
- const UString &s = archiveLink.Arcs[v].ErrorMessage;
- if (!s.IsEmpty())
+ const CArc &arc = arcLink.Arcs[k];
+ const CArcErrorInfo &er = arc.ErrorInfo;
+
+ if (er.ErrorFormatIndex >= 0)
{
+ RINOK(extractCallback->OpenTypeWarning(arc.Path,
+ codecs->GetFormatNamePtr(arc.FormatIndex),
+ codecs->GetFormatNamePtr(er.ErrorFormatIndex)))
+ /*
+ UString s = L"Can not open the file as [" + codecs->Formats[arc.ErrorFormatIndex].Name + L"] archive\n";
+ s += L"The file is open as [" + codecs->Formats[arc.FormatIndex].Name + L"] archive";
RINOK(extractCallback->MessageError(s));
+ */
+ }
+ {
+ const UString &s = er.ErrorMessage;
+ if (!s.IsEmpty())
+ {
+ RINOK(extractCallback->MessageError(s));
+ }
}
}
- CArc &arc = archiveLink.Arcs.Back();
+ CArc &arc = arcLink.Arcs.Back();
arc.MTimeDefined = (!options.StdInMode && !fi.IsDevice);
arc.MTime = fi.MTime;
UInt64 packProcessed;
- RINOK(DecompressArchive(arc,
- fi.Size + archiveLink.VolumesSize,
- wildcardCensor, options, extractCallback, extractCallbackSpec, errorMessage, packProcessed));
+ bool calcCrc =
+ #ifndef _SFX
+ (hash != NULL);
+ #else
+ false;
+ #endif
+
+ RINOK(DecompressArchive(
+ codecs,
+ arcLink,
+ fi.Size + arcLink.VolumesSize,
+ wildcardCensor,
+ options,
+ calcCrc,
+ extractCallback, ecs, errorMessage, packProcessed));
if (!options.StdInMode)
- packProcessed = fi.Size + archiveLink.VolumesSize;
- extractCallbackSpec->LocalProgressSpec->InSize += packProcessed;
- extractCallbackSpec->LocalProgressSpec->OutSize = extractCallbackSpec->UnpackSize;
+ packProcessed = fi.Size + arcLink.VolumesSize;
+ totalPackProcessed += packProcessed;
+ ecs->LocalProgressSpec->InSize += packProcessed;
+ ecs->LocalProgressSpec->OutSize = ecs->UnpackSize;
if (!errorMessage.IsEmpty())
return E_FAIL;
}
- stat.NumFolders = extractCallbackSpec->NumFolders;
- stat.NumFiles = extractCallbackSpec->NumFiles;
- stat.UnpackSize = extractCallbackSpec->UnpackSize;
- stat.CrcSum = extractCallbackSpec->CrcSum;
+ if (multi || thereAreNotOpenArcs)
+ {
+ RINOK(extractCallback->SetTotal(totalPackSize));
+ RINOK(extractCallback->SetCompleted(&totalPackProcessed));
+ }
+ stat.NumFolders = ecs->NumFolders;
+ stat.NumFiles = ecs->NumFiles;
+ stat.NumAltStreams = ecs->NumAltStreams;
+ stat.UnpackSize = ecs->UnpackSize;
+ stat.AltStreams_UnpackSize = ecs->AltStreams_UnpackSize;
stat.NumArchives = arcPaths.Size();
- stat.PackSize = extractCallbackSpec->LocalProgressSpec->InSize;
+ stat.PackSize = ecs->LocalProgressSpec->InSize;
return S_OK;
}
diff --git a/src/libs/7zip/unix/CPP/7zip/UI/Common/Extract.h b/src/libs/7zip/unix/CPP/7zip/UI/Common/Extract.h
index 5a939ed23..052b2f7d3 100644
--- a/src/libs/7zip/unix/CPP/7zip/UI/Common/Extract.h
+++ b/src/libs/7zip/unix/CPP/7zip/UI/Common/Extract.h
@@ -3,7 +3,7 @@
#ifndef __EXTRACT_H
#define __EXTRACT_H
-#include "Windows/FileFind.h"
+#include "../../../Windows/FileFind.h"
#include "../../Archive/IArchive.h"
@@ -14,21 +14,37 @@
#include "../Common/LoadCodecs.h"
-struct CExtractOptions
+struct CExtractOptionsBase
+{
+ CBoolPair ElimDup;
+
+ bool PathMode_Force;
+ bool OverwriteMode_Force;
+ NExtract::NPathMode::EEnum PathMode;
+ NExtract::NOverwriteMode::EEnum OverwriteMode;
+
+ FString OutputDir;
+ CExtractNtOptions NtOptions;
+
+ CExtractOptionsBase():
+ PathMode_Force(false),
+ OverwriteMode_Force(false),
+ PathMode(NExtract::NPathMode::kFullPaths),
+ OverwriteMode(NExtract::NOverwriteMode::kAsk)
+ {}
+};
+
+struct CExtractOptions: public CExtractOptionsBase
{
bool StdInMode;
bool StdOutMode;
bool YesToAll;
bool TestMode;
- bool CalcCrc;
- NExtract::NPathMode::EEnum PathMode;
- NExtract::NOverwriteMode::EEnum OverwriteMode;
- UString OutputDir;
-
+
// bool ShowDialog;
// bool PasswordEnabled;
// UString Password;
- #if !defined(_7ZIP_ST) && !defined(_SFX)
+ #ifndef _SFX
CObjectVector<CProperty> Properties;
#endif
@@ -37,13 +53,10 @@ struct CExtractOptions
#endif
CExtractOptions():
+ TestMode(false),
StdInMode(false),
StdOutMode(false),
- YesToAll(false),
- TestMode(false),
- CalcCrc(false),
- PathMode(NExtract::NPathMode::kFullPathnames),
- OverwriteMode(NExtract::NOverwriteMode::kAskBefore)
+ YesToAll(false)
{}
};
@@ -51,25 +64,30 @@ struct CDecompressStat
{
UInt64 NumArchives;
UInt64 UnpackSize;
+ UInt64 AltStreams_UnpackSize;
UInt64 PackSize;
UInt64 NumFolders;
UInt64 NumFiles;
- UInt32 CrcSum;
+ UInt64 NumAltStreams;
void Clear()
{
- NumArchives = UnpackSize = PackSize = NumFolders = NumFiles = 0;
- CrcSum = 0;
+ NumArchives = UnpackSize = AltStreams_UnpackSize = PackSize = NumFolders = NumFiles = NumAltStreams = 0;
}
};
-HRESULT DecompressArchives(
- CCodecs *codecs, const CIntVector &formatIndices,
+HRESULT Extract(
+ CCodecs *codecs,
+ const CObjectVector<COpenType> &types,
+ const CIntVector &excludedFormats,
UStringVector &archivePaths, UStringVector &archivePathsFull,
const NWildcard::CCensorNode &wildcardCensor,
const CExtractOptions &options,
IOpenCallbackUI *openCallback,
IExtractCallbackUI *extractCallback,
+ #ifndef _SFX
+ IHashCalc *hash,
+ #endif
UString &errorMessage,
CDecompressStat &stat);
diff --git a/src/libs/7zip/unix/CPP/7zip/UI/Common/ExtractMode.h b/src/libs/7zip/unix/CPP/7zip/UI/Common/ExtractMode.h
index b448fb30a..a54376705 100644
--- a/src/libs/7zip/unix/CPP/7zip/UI/Common/ExtractMode.h
+++ b/src/libs/7zip/unix/CPP/7zip/UI/Common/ExtractMode.h
@@ -4,28 +4,30 @@
#define __EXTRACT_MODE_H
namespace NExtract {
-
- namespace NPathMode
+
+namespace NPathMode
+{
+ enum EEnum
{
- enum EEnum
- {
- kFullPathnames,
- kCurrentPathnames,
- kNoPathnames
- };
- }
-
- namespace NOverwriteMode
+ kFullPaths,
+ kCurPaths,
+ kNoPaths,
+ kAbsPaths
+ };
+}
+
+namespace NOverwriteMode
+{
+ enum EEnum
{
- enum EEnum
- {
- kAskBefore,
- kWithoutPrompt,
- kSkipExisting,
- kAutoRename,
- kAutoRenameExisting
- };
- }
+ kAsk,
+ kOverwrite,
+ kSkip,
+ kRename,
+ kRenameExisting
+ };
+}
+
}
#endif
diff --git a/src/libs/7zip/unix/CPP/7zip/UI/Common/ExtractingFilePath.cpp b/src/libs/7zip/unix/CPP/7zip/UI/Common/ExtractingFilePath.cpp
index 8f31708b6..852fd5adb 100644
--- a/src/libs/7zip/unix/CPP/7zip/UI/Common/ExtractingFilePath.cpp
+++ b/src/libs/7zip/unix/CPP/7zip/UI/Common/ExtractingFilePath.cpp
@@ -2,26 +2,44 @@
#include "StdAfx.h"
-#include "../../../../C/Types.h"
+#include "../../../Common/Wildcard.h"
-#include "Common/Wildcard.h"
+#include "../../../Windows/FileName.h"
#include "ExtractingFilePath.h"
-static UString ReplaceIncorrectChars(const UString &s)
+static UString ReplaceIncorrectChars(const UString &s, bool repaceColon)
{
#ifdef _WIN32
UString res;
- for (int i = 0; i < s.Length(); i++)
+ bool beforeColon = true;
{
- wchar_t c = s[i];
- if (c < 0x20 || c == '*' || c == '?' || c == '<' || c == '>' || c == '|' || c == ':' || c == '"')
- c = '_';
- res += c;
+ for (unsigned i = 0; i < s.Len(); i++)
+ {
+ wchar_t c = s[i];
+ if (beforeColon)
+ if (c == '*' || c == '?' || c < 0x20 || c == '<' || c == '>' || c == '|' || c == '"')
+ c = '_';
+ if (c == ':')
+ {
+ if (repaceColon)
+ c = '_';
+ else
+ beforeColon = false;
+ }
+ res += c;
+ }
+ }
+ if (beforeColon)
+ {
+ for (int i = res.Len() - 1; i >= 0; i--)
+ {
+ wchar_t c = res[i];
+ if (c != '.' && c != ' ')
+ break;
+ res.ReplaceOneCharAtPos(i, '_');
+ }
}
- res.TrimRight();
- while (!res.IsEmpty() && res[res.Length() - 1] == '.')
- res.Delete(res.Length() - 1);
return res;
#else
return s;
@@ -29,27 +47,28 @@ static UString ReplaceIncorrectChars(const UString &s)
}
#ifdef _WIN32
+
static const wchar_t *g_ReservedNames[] =
{
L"CON", L"PRN", L"AUX", L"NUL"
};
-static bool CheckTail(const UString &name, int len)
+static bool CheckTail(const UString &name, unsigned len)
{
int dotPos = name.Find(L'.');
if (dotPos < 0)
- dotPos = name.Length();
+ dotPos = name.Len();
UString s = name.Left(dotPos);
s.TrimRight();
- return (s.Length() != len);
+ return s.Len() != len;
}
static bool CheckNameNum(const UString &name, const wchar_t *reservedName)
{
- int len = MyStringLen(reservedName);
- if (name.Length() <= len)
+ unsigned len = MyStringLen(reservedName);
+ if (name.Len() <= len)
return true;
- if (name.Left(len).CompareNoCase(reservedName) != 0)
+ if (MyStringCompareNoCase_N(name, reservedName, len) != 0)
return true;
wchar_t c = name[len];
if (c < L'0' || c > L'9')
@@ -59,13 +78,13 @@ static bool CheckNameNum(const UString &name, const wchar_t *reservedName)
static bool IsSupportedName(const UString &name)
{
- for (int i = 0; i < sizeof(g_ReservedNames) / sizeof(g_ReservedNames[0]); i++)
+ for (unsigned i = 0; i < ARRAY_SIZE(g_ReservedNames); i++)
{
const wchar_t *reservedName = g_ReservedNames[i];
- int len = MyStringLen(reservedName);
- if (name.Length() < len)
+ unsigned len = MyStringLen(reservedName);
+ if (name.Len() < len)
continue;
- if (name.Left(len).CompareNoCase(reservedName) != 0)
+ if (MyStringCompareNoCase_N(name, reservedName, len) != 0)
continue;
if (!CheckTail(name, len))
return false;
@@ -74,21 +93,34 @@ static bool IsSupportedName(const UString &name)
return false;
return CheckNameNum(name, L"LPT");
}
+
#endif
-static UString GetCorrectFileName(const UString &path)
+static UString GetCorrectFileName(const UString &path, bool repaceColon)
{
if (path == L".." || path == L".")
return UString();
- return ReplaceIncorrectChars(path);
+ return ReplaceIncorrectChars(path, repaceColon);
}
-void MakeCorrectPath(UStringVector &pathParts)
+void MakeCorrectPath(bool isPathFromRoot, UStringVector &pathParts, bool replaceAltStreamColon)
{
- for (int i = 0; i < pathParts.Size();)
+ for (unsigned i = 0; i < pathParts.Size();)
{
UString &s = pathParts[i];
- s = GetCorrectFileName(s);
+ #ifdef _WIN32
+ bool needReplaceColon = (replaceAltStreamColon || i != pathParts.Size() - 1);
+ if (i == 0 && isPathFromRoot && NWindows::NFile::NName::IsDrivePath(s))
+ {
+ UString s2 = s[0];
+ s2 += L'_';
+ s2 += GetCorrectFileName(s.Ptr(2), needReplaceColon);
+ s = s2;
+ }
+ else
+ s = GetCorrectFileName(s, needReplaceColon);
+ #endif
+
if (s.IsEmpty())
pathParts.Delete(i);
else
@@ -105,7 +137,7 @@ void MakeCorrectPath(UStringVector &pathParts)
UString MakePathNameFromParts(const UStringVector &parts)
{
UString result;
- for (int i = 0; i < parts.Size(); i++)
+ FOR_VECTOR (i, parts)
{
if (i != 0)
result += WCHAR_PATH_SEPARATOR;
@@ -114,28 +146,44 @@ UString MakePathNameFromParts(const UStringVector &parts)
return result;
}
+static const wchar_t *k_EmptyReplaceName = L"[]";
+
+void Correct_IfEmptyLastPart(UStringVector &parts)
+{
+ if (parts.IsEmpty())
+ parts.Add(k_EmptyReplaceName);
+ else
+ {
+ UString &s = parts.Back();
+ if (s.IsEmpty())
+ s = k_EmptyReplaceName;
+ }
+}
+
UString GetCorrectFsPath(const UString &path)
{
- UString res = GetCorrectFileName(path);
+ UString res = GetCorrectFileName(path, true);
#ifdef _WIN32
if (!IsSupportedName(res))
res = (UString)L"_" + res;
#endif
+ if (res.IsEmpty())
+ res = k_EmptyReplaceName;
return res;
}
-
+
UString GetCorrectFullFsPath(const UString &path)
{
UStringVector parts;
SplitPathToParts(path, parts);
- for (int i = 0; i < parts.Size(); i++)
+ FOR_VECTOR (i, parts)
{
UString &s = parts[i];
#ifdef _WIN32
- while (!s.IsEmpty() && s[s.Length() - 1] == '.')
- s.Delete(s.Length() - 1);
+ while (!s.IsEmpty() && (s.Back() == '.' || s.Back() == ' '))
+ s.DeleteBack();
if (!IsSupportedName(s))
- s = (UString)L"_" + s;
+ s.InsertAtFront(L'_');
#endif
}
return MakePathNameFromParts(parts);
diff --git a/src/libs/7zip/unix/CPP/7zip/UI/Common/ExtractingFilePath.h b/src/libs/7zip/unix/CPP/7zip/UI/Common/ExtractingFilePath.h
index da28bfc23..751248a97 100644
--- a/src/libs/7zip/unix/CPP/7zip/UI/Common/ExtractingFilePath.h
+++ b/src/libs/7zip/unix/CPP/7zip/UI/Common/ExtractingFilePath.h
@@ -3,11 +3,19 @@
#ifndef __EXTRACTING_FILE_PATH_H
#define __EXTRACTING_FILE_PATH_H
-#include "Common/MyString.h"
+#include "../../../Common/MyString.h"
UString MakePathNameFromParts(const UStringVector &parts);
-void MakeCorrectPath(UStringVector &pathParts);
+
+/* for WIN32:
+ if (isRoot == true), and pathParts[0] contains path like "c:name",
+ it thinks that "c:" is drive prefix (it's not ":name alt stream) and
+ the function changes part to c_name */
+void MakeCorrectPath(bool isPathFromRoot, UStringVector &pathParts, bool replaceAltStreamColon);
+
UString GetCorrectFsPath(const UString &path);
UString GetCorrectFullFsPath(const UString &path);
+void Correct_IfEmptyLastPart(UStringVector &parts);
+
#endif
diff --git a/src/libs/7zip/unix/CPP/7zip/UI/Common/HashCalc.cpp b/src/libs/7zip/unix/CPP/7zip/UI/Common/HashCalc.cpp
new file mode 100644
index 000000000..2d13a2af1
--- /dev/null
+++ b/src/libs/7zip/unix/CPP/7zip/UI/Common/HashCalc.cpp
@@ -0,0 +1,361 @@
+// HashCalc.cpp
+
+#include "StdAfx.h"
+
+#include "../../../../C/Alloc.h"
+
+#include "../../../Common/StringToInt.h"
+
+#include "../../Common/FileStreams.h"
+#include "../../Common/StreamUtils.h"
+
+#include "EnumDirItems.h"
+#include "HashCalc.h"
+
+using namespace NWindows;
+
+class CHashMidBuf
+{
+ void *_data;
+public:
+ CHashMidBuf(): _data(0) {}
+ operator void *() { return _data; }
+ bool Alloc(size_t size)
+ {
+ if (_data != 0)
+ return false;
+ _data = ::MidAlloc(size);
+ return _data != 0;
+ }
+ ~CHashMidBuf() { ::MidFree(_data); }
+};
+
+struct CEnumDirItemCallback_Hash: public IEnumDirItemCallback
+{
+ IHashCallbackUI *Callback;
+
+ HRESULT ScanProgress(UInt64 numFolders, UInt64 numFiles, UInt64 totalSize, const wchar_t *path, bool isDir)
+ {
+ return Callback->ScanProgress(numFolders, numFiles, totalSize, path, isDir);
+ }
+};
+
+static const wchar_t *k_DefaultHashMethod = L"CRC32";
+
+HRESULT CHashBundle::SetMethods(DECL_EXTERNAL_CODECS_LOC_VARS const UStringVector &hashMethods)
+{
+ UStringVector names = hashMethods;
+ if (names.IsEmpty())
+ names.Add(k_DefaultHashMethod);
+
+ CRecordVector<CMethodId> ids;
+ CObjectVector<COneMethodInfo> methods;
+
+ unsigned i;
+ for (i = 0; i < names.Size(); i++)
+ {
+ COneMethodInfo m;
+ RINOK(m.ParseMethodFromString(names[i]));
+
+ if (m.MethodName.IsEmpty())
+ m.MethodName = k_DefaultHashMethod;
+
+ if (m.MethodName == L"*")
+ {
+ CRecordVector<CMethodId> tempMethods;
+ GetHashMethods(EXTERNAL_CODECS_LOC_VARS tempMethods);
+ methods.Clear();
+ ids.Clear();
+ FOR_VECTOR (t, tempMethods)
+ {
+ int index = ids.AddToUniqueSorted(tempMethods[t]);
+ if (ids.Size() != methods.Size())
+ methods.Insert(index, m);
+ }
+ break;
+ }
+ else
+ {
+ // m.MethodName.RemoveChar(L'-');
+ CMethodId id;
+ if (!FindHashMethod(EXTERNAL_CODECS_LOC_VARS m.MethodName, id))
+ return E_NOTIMPL;
+ int index = ids.AddToUniqueSorted(id);
+ if (ids.Size() != methods.Size())
+ methods.Insert(index, m);
+ }
+ }
+
+ for (i = 0; i < ids.Size(); i++)
+ {
+ CMyComPtr<IHasher> hasher;
+ UString name;
+ RINOK(CreateHasher(EXTERNAL_CODECS_LOC_VARS ids[i], name, hasher));
+ if (!hasher)
+ throw "Can't create hasher";
+ const COneMethodInfo &m = methods[i];
+ {
+ CMyComPtr<ICompressSetCoderProperties> scp;
+ hasher.QueryInterface(IID_ICompressSetCoderProperties, &scp);
+ if (scp)
+ {
+ RINOK(m.SetCoderProps(scp, NULL));
+ }
+ }
+ UInt32 digestSize = hasher->GetDigestSize();
+ if (digestSize > k_HashCalc_DigestSize_Max)
+ return E_NOTIMPL;
+ CHasherState &h = Hashers.AddNew();
+ h.Hasher = hasher;
+ h.Name = name;
+ h.DigestSize = digestSize;
+ for (int i = 0; i < k_HashCalc_NumGroups; i++)
+ memset(h.Digests[i], 0, digestSize);
+ }
+ return S_OK;
+}
+
+void CHashBundle::InitForNewFile()
+{
+ CurSize = 0;
+ FOR_VECTOR (i, Hashers)
+ {
+ CHasherState &h = Hashers[i];
+ h.Hasher->Init();
+ memset(h.Digests[k_HashCalc_Index_Current], 0, h.DigestSize);
+ }
+}
+
+void CHashBundle::Update(const void *data, UInt32 size)
+{
+ CurSize += size;
+ FOR_VECTOR (i, Hashers)
+ Hashers[i].Hasher->Update(data, size);
+}
+
+void CHashBundle::SetSize(UInt64 size)
+{
+ CurSize = size;
+}
+
+static void AddDigests(Byte *dest, const Byte *src, UInt32 size)
+{
+ unsigned next = 0;
+ for (UInt32 i = 0; i < size; i++)
+ {
+ next += (unsigned)dest[i] + (unsigned)src[i];
+ dest[i] = (Byte)next;
+ next >>= 8;
+ }
+}
+
+void CHashBundle::Final(bool isDir, bool isAltStream, const UString &path)
+{
+ if (isDir)
+ NumDirs++;
+ else if (isAltStream)
+ {
+ NumAltStreams++;
+ AltStreamsSize += CurSize;
+ }
+ else
+ {
+ NumFiles++;
+ FilesSize += CurSize;
+ }
+
+ Byte pre[16];
+ memset(pre, 0, sizeof(pre));
+ if (isDir)
+ pre[0] = 1;
+
+ FOR_VECTOR (i, Hashers)
+ {
+ CHasherState &h = Hashers[i];
+ if (!isDir)
+ {
+ h.Hasher->Final(h.Digests[0]);
+ if (!isAltStream)
+ AddDigests(h.Digests[k_HashCalc_Index_DataSum], h.Digests[0], h.DigestSize);
+ }
+
+ h.Hasher->Init();
+ h.Hasher->Update(pre, sizeof(pre));
+ h.Hasher->Update(h.Digests[0], h.DigestSize);
+
+ for (unsigned k = 0; k < path.Len(); k++)
+ {
+ wchar_t c = path[k];
+ Byte temp[2] = { (Byte)(c & 0xFF), (Byte)((c >> 8) & 0xFF) };
+ h.Hasher->Update(temp, 2);
+ }
+
+ Byte tempDigest[k_HashCalc_DigestSize_Max];
+ h.Hasher->Final(tempDigest);
+ if (!isAltStream)
+ AddDigests(h.Digests[k_HashCalc_Index_NamesSum], tempDigest, h.DigestSize);
+ AddDigests(h.Digests[k_HashCalc_Index_StreamsSum], tempDigest, h.DigestSize);
+ }
+}
+
+
+HRESULT HashCalc(
+ DECL_EXTERNAL_CODECS_LOC_VARS
+ const NWildcard::CCensor &censor,
+ const CHashOptions &options,
+ UString &errorInfo,
+ IHashCallbackUI *callback)
+{
+ CDirItems dirItems;
+
+ UInt64 numErrors = 0;
+ UInt64 totalBytes = 0;
+ if (options.StdInMode)
+ {
+ CDirItem di;
+ di.Size = (UInt64)(Int64)-1;
+ di.Attrib = 0;
+ di.MTime.dwLowDateTime = 0;
+ di.MTime.dwHighDateTime = 0;
+ di.CTime = di.ATime = di.MTime;
+ dirItems.Items.Add(di);
+ }
+ else
+ {
+ CEnumDirItemCallback_Hash enumCallback;
+ enumCallback.Callback = callback;
+ RINOK(callback->StartScanning());
+ dirItems.ScanAltStreams = options.AltStreamsMode;
+ HRESULT res = EnumerateItems(censor,
+ options.PathMode,
+ UString(),
+ dirItems, &enumCallback);
+ totalBytes = dirItems.TotalSize;
+ FOR_VECTOR (i, dirItems.ErrorPaths)
+ {
+ RINOK(callback->CanNotFindError(fs2us(dirItems.ErrorPaths[i]), dirItems.ErrorCodes[i]));
+ }
+ numErrors = dirItems.ErrorPaths.Size();
+ if (res != S_OK)
+ {
+ if (res != E_ABORT)
+ errorInfo = L"Scanning error";
+ return res;
+ }
+ RINOK(callback->FinishScanning());
+ }
+
+ unsigned i;
+ CHashBundle hb;
+ RINOK(hb.SetMethods(EXTERNAL_CODECS_LOC_VARS options.Methods));
+ hb.Init();
+ hb.NumErrors = numErrors;
+
+ if (options.StdInMode)
+ {
+ RINOK(callback->SetNumFiles(1));
+ }
+ else
+ {
+ RINOK(callback->SetTotal(totalBytes));
+ }
+
+ const UInt32 kBufSize = 1 << 15;
+ CHashMidBuf buf;
+ if (!buf.Alloc(kBufSize))
+ return E_OUTOFMEMORY;
+
+ UInt64 completeValue = 0;
+
+ RINOK(callback->BeforeFirstFile(hb));
+
+ for (i = 0; i < dirItems.Items.Size(); i++)
+ {
+ CMyComPtr<ISequentialInStream> inStream;
+ UString path;
+ bool isDir = false;
+ bool isAltStream = false;
+ if (options.StdInMode)
+ {
+ inStream = new CStdInFileStream;
+ }
+ else
+ {
+ CInFileStream *inStreamSpec = new CInFileStream;
+ inStream = inStreamSpec;
+ const CDirItem &dirItem = dirItems.Items[i];
+ isDir = dirItem.IsDir();
+ isAltStream = dirItem.IsAltStream;
+ path = dirItems.GetLogPath(i);
+ if (!isDir)
+ {
+ UString phyPath = dirItems.GetPhyPath(i);
+ if (!inStreamSpec->OpenShared(us2fs(phyPath), options.OpenShareForWrite))
+ {
+ HRESULT res = callback->OpenFileError(phyPath, ::GetLastError());
+ hb.NumErrors++;
+ if (res != S_FALSE)
+ return res;
+ continue;
+ }
+ }
+ }
+ RINOK(callback->GetStream(path, isDir));
+ UInt64 fileSize = 0;
+
+ hb.InitForNewFile();
+ if (!isDir)
+ {
+ for (UInt32 step = 0;; step++)
+ {
+ if ((step & 0xFF) == 0)
+ RINOK(callback->SetCompleted(&completeValue));
+ UInt32 size;
+ RINOK(inStream->Read(buf, kBufSize, &size));
+ if (size == 0)
+ break;
+ hb.Update(buf, size);
+ fileSize += size;
+ completeValue += size;
+ }
+ }
+ hb.Final(isDir, isAltStream, path);
+ RINOK(callback->SetOperationResult(fileSize, hb, !isDir));
+ RINOK(callback->SetCompleted(&completeValue));
+ }
+ return callback->AfterLastFile(hb);
+}
+
+
+static inline char GetHex(Byte value)
+{
+ return (char)((value < 10) ? ('0' + value) : ('A' + (value - 10)));
+}
+
+void AddHashHexToString(char *dest, const Byte *data, UInt32 size)
+{
+ dest[size * 2] = 0;
+ if (!data)
+ {
+ for (UInt32 i = 0; i < size; i++)
+ {
+ dest[0] = ' ';
+ dest[1] = ' ';
+ dest += 2;
+ }
+ return;
+ }
+ int step = 2;
+ if (size <= 8)
+ {
+ step = -2;
+ dest += size * 2 - 2;
+ }
+ for (UInt32 i = 0; i < size; i++)
+ {
+ Byte b = data[i];
+ dest[0] = GetHex((Byte)((b >> 4) & 0xF));
+ dest[1] = GetHex((Byte)(b & 0xF));
+ dest += step;
+ }
+}
diff --git a/src/libs/7zip/unix/CPP/7zip/UI/Common/HashCalc.h b/src/libs/7zip/unix/CPP/7zip/UI/Common/HashCalc.h
new file mode 100644
index 000000000..68e2404cc
--- /dev/null
+++ b/src/libs/7zip/unix/CPP/7zip/UI/Common/HashCalc.h
@@ -0,0 +1,107 @@
+// HashCalc.h
+
+#ifndef __HASH_CALC_H
+#define __HASH_CALC_H
+
+#include "../../../Common/Wildcard.h"
+
+#include "../../Common/CreateCoder.h"
+#include "../../Common/MethodProps.h"
+
+#include "Property.h"
+
+const unsigned k_HashCalc_DigestSize_Max = 64;
+
+const unsigned k_HashCalc_NumGroups = 4;
+
+enum
+{
+ k_HashCalc_Index_Current,
+ k_HashCalc_Index_DataSum,
+ k_HashCalc_Index_NamesSum,
+ k_HashCalc_Index_StreamsSum
+};
+
+struct CHasherState
+{
+ CMyComPtr<IHasher> Hasher;
+ UString Name;
+ UInt32 DigestSize;
+ Byte Digests[k_HashCalc_NumGroups][k_HashCalc_DigestSize_Max];
+};
+
+struct IHashCalc
+{
+ virtual void InitForNewFile() = 0;
+ virtual void Update(const void *data, UInt32 size) = 0;
+ virtual void SetSize(UInt64 size) = 0;
+ virtual void Final(bool isDir, bool isAltStream, const UString &path) = 0;
+};
+
+struct CHashBundle: public IHashCalc
+{
+ CObjectVector<CHasherState> Hashers;
+
+ UInt64 NumFiles;
+ UInt64 NumDirs;
+ UInt64 NumAltStreams;
+ UInt64 FilesSize;
+ UInt64 AltStreamsSize;
+ UInt64 NumErrors;
+
+ UInt64 CurSize;
+
+ HRESULT SetMethods(DECL_EXTERNAL_CODECS_LOC_VARS const UStringVector &methods);
+
+ void Init()
+ {
+ NumFiles = NumDirs = NumAltStreams = FilesSize = AltStreamsSize = NumErrors = 0;
+ }
+
+ void InitForNewFile();
+ void Update(const void *data, UInt32 size);
+ void SetSize(UInt64 size);
+ void Final(bool isDir, bool isAltStream, const UString &path);
+};
+
+#define INTERFACE_IHashCallbackUI(x) \
+ virtual HRESULT StartScanning() x; \
+ virtual HRESULT ScanProgress(UInt64 numFolders, UInt64 numFiles, UInt64 totalSize, const wchar_t *path, bool isDir) x; \
+ virtual HRESULT CanNotFindError(const wchar_t *name, DWORD systemError) x; \
+ virtual HRESULT FinishScanning() x; \
+ virtual HRESULT SetNumFiles(UInt64 numFiles) x; \
+ virtual HRESULT SetTotal(UInt64 size) x; \
+ virtual HRESULT SetCompleted(const UInt64 *completeValue) x; \
+ virtual HRESULT CheckBreak() x; \
+ virtual HRESULT BeforeFirstFile(const CHashBundle &hb) x; \
+ virtual HRESULT GetStream(const wchar_t *name, bool isFolder) x; \
+ virtual HRESULT OpenFileError(const wchar_t *name, DWORD systemError) x; \
+ virtual HRESULT SetOperationResult(UInt64 fileSize, const CHashBundle &hb, bool showHash) x; \
+ virtual HRESULT AfterLastFile(const CHashBundle &hb) x; \
+
+struct IHashCallbackUI
+{
+ INTERFACE_IHashCallbackUI(=0)
+};
+
+struct CHashOptions
+{
+ UStringVector Methods;
+ bool OpenShareForWrite;
+ bool StdInMode;
+ bool AltStreamsMode;
+ NWildcard::ECensorPathMode PathMode;
+
+ CHashOptions(): StdInMode(false), OpenShareForWrite(false), AltStreamsMode(false), PathMode(NWildcard::k_RelatPath) {};
+};
+
+HRESULT HashCalc(
+ DECL_EXTERNAL_CODECS_LOC_VARS
+ const NWildcard::CCensor &censor,
+ const CHashOptions &options,
+ UString &errorInfo,
+ IHashCallbackUI *callback);
+
+void AddHashHexToString(char *dest, const Byte *data, UInt32 size);
+
+#endif
diff --git a/src/libs/7zip/unix/CPP/7zip/UI/Common/IFileExtractCallback.h b/src/libs/7zip/unix/CPP/7zip/UI/Common/IFileExtractCallback.h
index e8dcdce5f..7bb852795 100644
--- a/src/libs/7zip/unix/CPP/7zip/UI/Common/IFileExtractCallback.h
+++ b/src/libs/7zip/unix/CPP/7zip/UI/Common/IFileExtractCallback.h
@@ -1,9 +1,10 @@
// IFileExtractCallback.h
-#ifndef __IFILEEXTRACTCALLBACK_H
-#define __IFILEEXTRACTCALLBACK_H
+#ifndef __I_FILE_EXTRACT_CALLBACK_H
+#define __I_FILE_EXTRACT_CALLBACK_H
+
+#include "../../../Common/MyString.h"
-#include "Common/MyString.h"
#include "../../IDecl.h"
namespace NOverwriteAnswer
@@ -35,12 +36,37 @@ struct IExtractCallbackUI: IFolderArchiveExtractCallback
{
virtual HRESULT BeforeOpen(const wchar_t *name) = 0;
virtual HRESULT OpenResult(const wchar_t *name, HRESULT result, bool encrypted) = 0;
+ virtual HRESULT SetError(int level, const wchar_t *name,
+ UInt32 errorFlags, const wchar_t *errors,
+ UInt32 warningFlags, const wchar_t *warnings) = 0;
virtual HRESULT ThereAreNoFiles() = 0;
virtual HRESULT ExtractResult(HRESULT result) = 0;
+ virtual HRESULT OpenTypeWarning(const wchar_t *name, const wchar_t *okType, const wchar_t *errorType) = 0;
#ifndef _NO_CRYPTO
virtual HRESULT SetPassword(const UString &password) = 0;
#endif
};
+
+#define INTERFACE_IGetProp(x) \
+ STDMETHOD(GetProp)(PROPID propID, PROPVARIANT *value) x; \
+
+DECL_INTERFACE_SUB(IGetProp, IUnknown, 0x01, 0x20)
+{
+ INTERFACE_IGetProp(PURE)
+};
+
+#define INTERFACE_IFolderExtractToStreamCallback(x) \
+ STDMETHOD(UseExtractToStream)(Int32 *res) x; \
+ STDMETHOD(GetStream7)(const wchar_t *name, Int32 isDir, ISequentialOutStream **outStream, Int32 askExtractMode, IGetProp *getProp) x; \
+ STDMETHOD(PrepareOperation7)(Int32 askExtractMode) x; \
+ STDMETHOD(SetOperationResult7)(Int32 resultEOperationResult, bool encrypted) x; \
+
+DECL_INTERFACE_SUB(IFolderExtractToStreamCallback, IUnknown, 0x01, 0x30)
+{
+ INTERFACE_IFolderExtractToStreamCallback(PURE)
+};
+
+
#endif
diff --git a/src/libs/7zip/unix/CPP/7zip/UI/Common/LoadCodecs.cpp b/src/libs/7zip/unix/CPP/7zip/UI/Common/LoadCodecs.cpp
index 171b7c104..09c79147d 100644
--- a/src/libs/7zip/unix/CPP/7zip/UI/Common/LoadCodecs.cpp
+++ b/src/libs/7zip/unix/CPP/7zip/UI/Common/LoadCodecs.cpp
@@ -2,18 +2,27 @@
#include "StdAfx.h"
-#include "LoadCodecs.h"
+#include "../../../../C/7zVersion.h"
#include "../../../Common/MyCom.h"
+#include "../../../Common/StringToInt.h"
+#include "../../../Common/StringConvert.h"
+
+#include "../../../Windows/PropVariant.h"
+
+#include "LoadCodecs.h"
+
+using namespace NWindows;
+
#ifdef NEW_FOLDER_INTERFACE
#include "../../../Common/StringToInt.h"
#endif
-#include "../../../Windows/PropVariant.h"
#include "../../ICoder.h"
#include "../../Common/RegisterArc.h"
#ifdef EXTERNAL_CODECS
+
#include "../../../Windows/FileFind.h"
#include "../../../Windows/DLL.h"
#ifdef NEW_FOLDER_INTERFACE
@@ -22,106 +31,169 @@ static const UINT kIconTypesResId = 100;
#endif
#ifdef _WIN32
-#include "Windows/Registry.h"
+#include "../../../Windows/FileName.h"
+#include "../../../Windows/Registry.h"
#else
-#include "Common/StringConvert.h"
+#include "../../../Common/StringConvert.h"
#endif
-using namespace NWindows;
using namespace NFile;
#ifdef _WIN32
extern HINSTANCE g_hInstance;
#endif
-static CSysString GetLibraryFolderPrefix()
-{
- #ifdef _WIN32
- TCHAR fullPath[MAX_PATH + 1];
- ::GetModuleFileName(g_hInstance, fullPath, MAX_PATH);
- CSysString path = fullPath;
- int pos = path.ReverseFind(TEXT(CHAR_PATH_SEPARATOR));
- return path.Left(pos + 1);
- #else
- const char *p7zip_home_dir = getenv("P7ZIP_HOME_DIR");
- if (p7zip_home_dir == 0) p7zip_home_dir="./";
-#ifdef _UNICODE
- return MultiByteToUnicodeString(p7zip_home_dir);
-#else
- return p7zip_home_dir;
-#endif
- #endif
-}
-
-#define kCodecsFolderName TEXT("Codecs")
-#define kFormatsFolderName TEXT("Formats")
-static const TCHAR *kMainDll = TEXT("7z.dll");
+#define kCodecsFolderName FTEXT("Codecs")
+#define kFormatsFolderName FTEXT("Formats")
+static CFSTR kMainDll = FTEXT("7z.dll");
#ifdef _WIN32
+
static LPCTSTR kRegistryPath = TEXT("Software") TEXT(STRING_PATH_SEPARATOR) TEXT("7-zip");
-static LPCTSTR kProgramPathValue = TEXT("Path");
-static bool ReadPathFromRegistry(HKEY baseKey, CSysString &path)
+static LPCWSTR kProgramPathValue = L"Path";
+static LPCWSTR kProgramPath2Value = L"Path"
+ #ifdef _WIN64
+ L"64";
+ #else
+ L"32";
+ #endif
+
+static bool ReadPathFromRegistry(HKEY baseKey, LPCWSTR value, FString &path)
{
NRegistry::CKey key;
- if(key.Open(baseKey, kRegistryPath, KEY_READ) == ERROR_SUCCESS)
- if (key.QueryValue(kProgramPathValue, path) == ERROR_SUCCESS)
+ if (key.Open(baseKey, kRegistryPath, KEY_READ) == ERROR_SUCCESS)
+ {
+ UString pathU;
+ if (key.QueryValue(value, pathU) == ERROR_SUCCESS)
{
+ path = us2fs(pathU);
NName::NormalizeDirPathPrefix(path);
- return true;
+ return NFind::DoesFileExist(path + kMainDll);
}
+ }
return false;
}
-#endif
+#endif // _WIN32
+
+#endif // EXTERNAL_CODECS
+
-CSysString GetBaseFolderPrefixFromRegistry()
+static const unsigned kNumArcsMax = 48;
+static unsigned g_NumArcs = 0;
+static const CArcInfo *g_Arcs[kNumArcsMax];
+
+void RegisterArc(const CArcInfo *arcInfo) throw()
{
- CSysString moduleFolderPrefix = GetLibraryFolderPrefix();
-#ifdef _UNICODE
- NFind::CFileInfoW fi;
-#else
- NFind::CFileInfo fi;
-#endif
- if (NFind::FindFile(moduleFolderPrefix + kMainDll, fi))
- if (!fi.IsDir())
- return moduleFolderPrefix;
- if (NFind::FindFile(moduleFolderPrefix + kCodecsFolderName, fi))
- if (fi.IsDir())
- return moduleFolderPrefix;
- if (NFind::FindFile(moduleFolderPrefix + kFormatsFolderName, fi))
- if (fi.IsDir())
- return moduleFolderPrefix;
+ if (g_NumArcs < kNumArcsMax)
+ {
+ g_Arcs[g_NumArcs] = arcInfo;
+ g_NumArcs++;
+ }
+}
+
+static void SplitString(const UString &srcString, UStringVector &destStrings)
+{
+ destStrings.Clear();
+ UString s;
+ unsigned len = srcString.Len();
+ if (len == 0)
+ return;
+ for (unsigned i = 0; i < len; i++)
+ {
+ wchar_t c = srcString[i];
+ if (c == L' ')
+ {
+ if (!s.IsEmpty())
+ {
+ destStrings.Add(s);
+ s.Empty();
+ }
+ }
+ else
+ s += c;
+ }
+ if (!s.IsEmpty())
+ destStrings.Add(s);
+}
+
+int CArcInfoEx::FindExtension(const UString &ext) const
+{
+ FOR_VECTOR (i, Exts)
+ if (ext.IsEqualToNoCase(Exts[i].Ext))
+ return i;
+ return -1;
+}
+
+void CArcInfoEx::AddExts(const UString &ext, const UString &addExt)
+{
+ UStringVector exts, addExts;
+ SplitString(ext, exts);
+ SplitString(addExt, addExts);
+ FOR_VECTOR (i, exts)
+ {
+ CArcExtInfo extInfo;
+ extInfo.Ext = exts[i];
+ if (i < addExts.Size())
+ {
+ extInfo.AddExt = addExts[i];
+ if (extInfo.AddExt == L"*")
+ extInfo.AddExt.Empty();
+ }
+ Exts.Add(extInfo);
+ }
+}
+
+#ifndef _SFX
+
+static bool ParseSignatures(const Byte *data, unsigned size, CObjectVector<CByteBuffer> &signatures)
+{
+ signatures.Clear();
+ while (size > 0)
+ {
+ unsigned len = *data++;
+ size--;
+ if (len > size)
+ return false;
+ signatures.AddNew().CopyFrom(data, len);
+ data += len;
+ size -= len;
+ }
+ return true;
+}
+
+#endif // _SFX
+
+#ifdef EXTERNAL_CODECS
+
+static FString GetBaseFolderPrefixFromRegistry()
+{
+ FString moduleFolderPrefix = NDLL::GetModuleDirPrefix();
#ifdef _WIN32
if (!NFind::DoesFileExist(moduleFolderPrefix + kMainDll) &&
!NFind::DoesDirExist(moduleFolderPrefix + kCodecsFolderName) &&
!NFind::DoesDirExist(moduleFolderPrefix + kFormatsFolderName))
{
- CSysString path;
- if (ReadPathFromRegistry(HKEY_CURRENT_USER, path))
- return path;
- if (ReadPathFromRegistry(HKEY_LOCAL_MACHINE, path))
- return path;
+ FString path;
+ if (ReadPathFromRegistry(HKEY_CURRENT_USER, kProgramPath2Value, path)) return path;
+ if (ReadPathFromRegistry(HKEY_LOCAL_MACHINE, kProgramPath2Value, path)) return path;
+ if (ReadPathFromRegistry(HKEY_CURRENT_USER, kProgramPathValue, path)) return path;
+ if (ReadPathFromRegistry(HKEY_LOCAL_MACHINE, kProgramPathValue, path)) return path;
}
#endif
return moduleFolderPrefix;
}
-typedef UInt32 (WINAPI *GetNumberOfMethodsFunc)(UInt32 *numMethods);
-typedef UInt32 (WINAPI *GetNumberOfFormatsFunc)(UInt32 *numFormats);
-typedef UInt32 (WINAPI *GetHandlerPropertyFunc)(PROPID propID, PROPVARIANT *value);
-typedef UInt32 (WINAPI *GetHandlerPropertyFunc2)(UInt32 index, PROPID propID, PROPVARIANT *value);
-typedef UInt32 (WINAPI *CreateObjectFunc)(const GUID *clsID, const GUID *iid, void **outObject);
-typedef UInt32 (WINAPI *SetLargePageModeFunc)();
-
-
-static HRESULT GetCoderClass(GetMethodPropertyFunc getMethodProperty, UInt32 index,
+static HRESULT GetCoderClass(Func_GetMethodProperty getMethodProperty, UInt32 index,
PROPID propId, CLSID &clsId, bool &isAssigned)
{
- NWindows::NCOM::CPropVariant prop;
+ NCOM::CPropVariant prop;
isAssigned = false;
RINOK(getMethodProperty(index, propId, &prop));
if (prop.vt == VT_BSTR)
{
+ if (::SysStringByteLen(prop.bstrVal) != sizeof(GUID))
+ return E_FAIL;
isAssigned = true;
clsId = *(const GUID *)prop.bstrVal;
}
@@ -133,34 +205,48 @@ static HRESULT GetCoderClass(GetMethodPropertyFunc getMethodProperty, UInt32 ind
HRESULT CCodecs::LoadCodecs()
{
CCodecLib &lib = Libs.Back();
- lib.GetMethodProperty = (GetMethodPropertyFunc)lib.Lib.GetProc("GetMethodProperty");
- if (lib.GetMethodProperty == NULL)
- return S_OK;
-
- UInt32 numMethods = 1;
- GetNumberOfMethodsFunc getNumberOfMethodsFunc = (GetNumberOfMethodsFunc)lib.Lib.GetProc("GetNumberOfMethods");
- if (getNumberOfMethodsFunc != NULL)
+ lib.GetMethodProperty = (Func_GetMethodProperty)lib.Lib.GetProc("GetMethodProperty");
+ if (lib.GetMethodProperty)
{
- RINOK(getNumberOfMethodsFunc(&numMethods));
+ UInt32 numMethods = 1;
+ Func_GetNumberOfMethods getNumberOfMethodsFunc = (Func_GetNumberOfMethods)lib.Lib.GetProc("GetNumberOfMethods");
+ if (getNumberOfMethodsFunc)
+ {
+ RINOK(getNumberOfMethodsFunc(&numMethods));
+ }
+ for (UInt32 i = 0; i < numMethods; i++)
+ {
+ CDllCodecInfo info;
+ info.LibIndex = Libs.Size() - 1;
+ info.CodecIndex = i;
+ RINOK(GetCoderClass(lib.GetMethodProperty, i, NMethodPropID::kEncoder, info.Encoder, info.EncoderIsAssigned));
+ RINOK(GetCoderClass(lib.GetMethodProperty, i, NMethodPropID::kDecoder, info.Decoder, info.DecoderIsAssigned));
+ Codecs.Add(info);
+ }
}
- for(UInt32 i = 0; i < numMethods; i++)
+ Func_GetHashers getHashers = (Func_GetHashers)lib.Lib.GetProc("GetHashers");
+ if (getHashers)
{
- CDllCodecInfo info;
- info.LibIndex = Libs.Size() - 1;
- info.CodecIndex = i;
-
- RINOK(GetCoderClass(lib.GetMethodProperty, i, NMethodPropID::kEncoder, info.Encoder, info.EncoderIsAssigned));
- RINOK(GetCoderClass(lib.GetMethodProperty, i, NMethodPropID::kDecoder, info.Decoder, info.DecoderIsAssigned));
-
- Codecs.Add(info);
+ RINOK(getHashers(&lib.Hashers));
+ if (lib.Hashers)
+ {
+ UInt32 numMethods = lib.Hashers->GetNumHashers();
+ for (UInt32 i = 0; i < numMethods; i++)
+ {
+ CDllHasherInfo info;
+ info.LibIndex = Libs.Size() - 1;
+ info.HasherIndex = i;
+ Hashers.Add(info);
+ }
+ }
}
return S_OK;
}
-static HRESULT ReadProp(
- GetHandlerPropertyFunc getProp,
- GetHandlerPropertyFunc2 getProp2,
+static HRESULT GetProp(
+ Func_GetHandlerProperty getProp,
+ Func_GetHandlerProperty2 getProp2,
UInt32 index, PROPID propID, NCOM::CPropVariant &prop)
{
if (getProp2)
@@ -168,13 +254,14 @@ static HRESULT ReadProp(
return getProp(propID, &prop);
}
-static HRESULT ReadBoolProp(
- GetHandlerPropertyFunc getProp,
- GetHandlerPropertyFunc2 getProp2,
+static HRESULT GetProp_Bool(
+ Func_GetHandlerProperty getProp,
+ Func_GetHandlerProperty2 getProp2,
UInt32 index, PROPID propID, bool &res)
{
+ res = false;
NCOM::CPropVariant prop;
- RINOK(ReadProp(getProp, getProp2, index, propID, prop));
+ RINOK(GetProp(getProp, getProp2, index, propID, prop));
if (prop.vt == VT_BOOL)
res = VARIANT_BOOLToBool(prop.boolVal);
else if (prop.vt != VT_EMPTY)
@@ -182,132 +269,150 @@ static HRESULT ReadBoolProp(
return S_OK;
}
-static HRESULT ReadStringProp(
- GetHandlerPropertyFunc getProp,
- GetHandlerPropertyFunc2 getProp2,
- UInt32 index, PROPID propID, UString &res)
+static HRESULT GetProp_UInt32(
+ Func_GetHandlerProperty getProp,
+ Func_GetHandlerProperty2 getProp2,
+ UInt32 index, PROPID propID, UInt32 &res, bool &defined)
{
+ res = 0;
+ defined = false;
NCOM::CPropVariant prop;
- RINOK(ReadProp(getProp, getProp2, index, propID, prop));
- if (prop.vt == VT_BSTR)
- res = prop.bstrVal;
+ RINOK(GetProp(getProp, getProp2, index, propID, prop));
+ if (prop.vt == VT_UI4)
+ {
+ res = prop.ulVal;
+ defined = true;
+ }
else if (prop.vt != VT_EMPTY)
return E_FAIL;
return S_OK;
}
-#endif
-
-static const unsigned int kNumArcsMax = 48;
-static unsigned int g_NumArcs = 0;
-static const CArcInfo *g_Arcs[kNumArcsMax];
-void RegisterArc(const CArcInfo *arcInfo)
+static HRESULT GetProp_String(
+ Func_GetHandlerProperty getProp,
+ Func_GetHandlerProperty2 getProp2,
+ UInt32 index, PROPID propID, UString &res)
{
- if (g_NumArcs < kNumArcsMax)
- g_Arcs[g_NumArcs++] = arcInfo;
+ res.Empty();
+ NCOM::CPropVariant prop;
+ RINOK(GetProp(getProp, getProp2, index, propID, prop));
+ if (prop.vt == VT_BSTR)
+ res = prop.bstrVal;
+ else if (prop.vt != VT_EMPTY)
+ return E_FAIL;
+ return S_OK;
}
-static void SplitString(const UString &srcString, UStringVector &destStrings)
+static HRESULT GetProp_RawData(
+ Func_GetHandlerProperty getProp,
+ Func_GetHandlerProperty2 getProp2,
+ UInt32 index, PROPID propID, CByteBuffer &bb)
{
- destStrings.Clear();
- UString s;
- int len = srcString.Length();
- if (len == 0)
- return;
- for (int i = 0; i < len; i++)
+ bb.Free();
+ NCOM::CPropVariant prop;
+ RINOK(GetProp(getProp, getProp2, index, propID, prop));
+ if (prop.vt == VT_BSTR)
{
- wchar_t c = srcString[i];
- if (c == L' ')
- {
- if (!s.IsEmpty())
- {
- destStrings.Add(s);
- s.Empty();
- }
- }
- else
- s += c;
+ UINT len = ::SysStringByteLen(prop.bstrVal);
+ bb.CopyFrom((const Byte *)prop.bstrVal, len);
}
- if (!s.IsEmpty())
- destStrings.Add(s);
+ else if (prop.vt != VT_EMPTY)
+ return E_FAIL;
+ return S_OK;
}
-void CArcInfoEx::AddExts(const wchar_t *ext, const wchar_t *addExt)
+static const UInt32 kArcFlagsPars[] =
{
- UStringVector exts, addExts;
- if (ext != 0)
- SplitString(ext, exts);
- if (addExt != 0)
- SplitString(addExt, addExts);
- for (int i = 0; i < exts.Size(); i++)
- {
- CArcExtInfo extInfo;
- extInfo.Ext = exts[i];
- if (i < addExts.Size())
- {
- extInfo.AddExt = addExts[i];
- if (extInfo.AddExt == L"*")
- extInfo.AddExt.Empty();
- }
- Exts.Add(extInfo);
- }
-}
-
-#ifdef EXTERNAL_CODECS
+ NArchive::NHandlerPropID::kKeepName, NArcInfoFlags::kKeepName,
+ NArchive::NHandlerPropID::kAltStreams, NArcInfoFlags::kAltStreams,
+ NArchive::NHandlerPropID::kNtSecure, NArcInfoFlags::kNtSecure
+};
HRESULT CCodecs::LoadFormats()
{
const NDLL::CLibrary &lib = Libs.Back().Lib;
- GetHandlerPropertyFunc getProp = 0;
- GetHandlerPropertyFunc2 getProp2 = (GetHandlerPropertyFunc2)lib.GetProc("GetHandlerProperty2");
- if (getProp2 == NULL)
- {
- getProp = (GetHandlerPropertyFunc)lib.GetProc("GetHandlerProperty");
- if (getProp == NULL)
- return S_OK;
- }
+
+ Func_GetHandlerProperty getProp = NULL;
+ Func_GetHandlerProperty2 getProp2 = (Func_GetHandlerProperty2)lib.GetProc("GetHandlerProperty2");
+ Func_GetIsArc getIsArc = (Func_GetIsArc)lib.GetProc("GetIsArc");
UInt32 numFormats = 1;
- GetNumberOfFormatsFunc getNumberOfFormats = (GetNumberOfFormatsFunc)lib.GetProc("GetNumberOfFormats");
- if (getNumberOfFormats != NULL)
+
+ if (getProp2)
{
- RINOK(getNumberOfFormats(&numFormats));
+ Func_GetNumberOfFormats getNumberOfFormats = (Func_GetNumberOfFormats)lib.GetProc("GetNumberOfFormats");
+ if (getNumberOfFormats)
+ {
+ RINOK(getNumberOfFormats(&numFormats));
+ }
+ }
+ else
+ {
+ getProp = (Func_GetHandlerProperty)lib.GetProc("GetHandlerProperty");
+ if (!getProp)
+ return S_OK;
}
- if (getProp2 == NULL)
- numFormats = 1;
- for(UInt32 i = 0; i < numFormats; i++)
+ for (UInt32 i = 0; i < numFormats; i++)
{
CArcInfoEx item;
item.LibIndex = Libs.Size() - 1;
item.FormatIndex = i;
- RINOK(ReadStringProp(getProp, getProp2, i, NArchive::kName, item.Name));
+ RINOK(GetProp_String(getProp, getProp2, i, NArchive::NHandlerPropID::kName, item.Name));
- NCOM::CPropVariant prop;
- if (ReadProp(getProp, getProp2, i, NArchive::kClassID, prop) != S_OK)
- continue;
- if (prop.vt != VT_BSTR)
- continue;
- item.ClassID = *(const GUID *)prop.bstrVal;
- prop.Clear();
+ {
+ NCOM::CPropVariant prop;
+ if (GetProp(getProp, getProp2, i, NArchive::NHandlerPropID::kClassID, prop) != S_OK)
+ continue;
+ if (prop.vt != VT_BSTR)
+ continue;
+ if (::SysStringByteLen(prop.bstrVal) != sizeof(GUID))
+ return E_FAIL;
+ item.ClassID = *(const GUID *)prop.bstrVal;
+ prop.Clear();
+ }
UString ext, addExt;
- RINOK(ReadStringProp(getProp, getProp2, i, NArchive::kExtension, ext));
- RINOK(ReadStringProp(getProp, getProp2, i, NArchive::kAddExtension, addExt));
+ RINOK(GetProp_String(getProp, getProp2, i, NArchive::NHandlerPropID::kExtension, ext));
+ RINOK(GetProp_String(getProp, getProp2, i, NArchive::NHandlerPropID::kAddExtension, addExt));
item.AddExts(ext, addExt);
- ReadBoolProp(getProp, getProp2, i, NArchive::kUpdate, item.UpdateEnabled);
- if (item.UpdateEnabled)
- ReadBoolProp(getProp, getProp2, i, NArchive::kKeepName, item.KeepName);
-
- if (ReadProp(getProp, getProp2, i, NArchive::kStartSignature, prop) == S_OK)
- if (prop.vt == VT_BSTR)
+ GetProp_Bool(getProp, getProp2, i, NArchive::NHandlerPropID::kUpdate, item.UpdateEnabled);
+ bool flags_Defined = false;
+ RINOK(GetProp_UInt32(getProp, getProp2, i, NArchive::NHandlerPropID::kFlags, item.Flags, flags_Defined));
+ item.NewInterface = flags_Defined;
+ if (!flags_Defined) // && item.UpdateEnabled
+ {
+ // support for DLL version before 9.31:
+ for (unsigned j = 0; j < ARRAY_SIZE(kArcFlagsPars); j += 2)
{
- UINT len = ::SysStringByteLen(prop.bstrVal);
- item.StartSignature.SetCapacity(len);
- memmove((Byte *)item.StartSignature, prop.bstrVal, len);
+ bool val = false;
+ GetProp_Bool(getProp, getProp2, i, kArcFlagsPars[j], val);
+ if (val)
+ item.Flags |= kArcFlagsPars[j + 1];
}
+ }
+
+ CByteBuffer sig;
+ RINOK(GetProp_RawData(getProp, getProp2, i, NArchive::NHandlerPropID::kSignature, sig));
+ if (sig.Size() != 0)
+ item.Signatures.Add(sig);
+ else
+ {
+ RINOK(GetProp_RawData(getProp, getProp2, i, NArchive::NHandlerPropID::kMultiSignature, sig));
+ ParseSignatures(sig, (unsigned)sig.Size(), item.Signatures);
+ }
+
+ bool signatureOffset_Defined;
+ RINOK(GetProp_UInt32(getProp, getProp2, i, NArchive::NHandlerPropID::kSignatureOffset, item.SignatureOffset, signatureOffset_Defined));
+
+ // bool version_Defined;
+ // RINOK(GetProp_UInt32(getProp, getProp2, i, NArchive::NHandlerPropID::kVersion, item.Version, version_Defined));
+
+ if (getIsArc)
+ getIsArc(i, &item.IsArcFunc);
+
Formats.Add(item);
}
return S_OK;
@@ -317,25 +422,26 @@ HRESULT CCodecs::LoadFormats()
void CCodecIcons::LoadIcons(HMODULE m)
{
#ifdef _WIN32
- UString iconTypes = MyLoadStringW(m, kIconTypesResId);
+ UString iconTypes;
+ MyLoadString(m, kIconTypesResId, iconTypes);
UStringVector pairs;
SplitString(iconTypes, pairs);
- for (int i = 0; i < pairs.Size(); i++)
+ FOR_VECTOR (i, pairs)
{
const UString &s = pairs[i];
int pos = s.Find(L':');
CIconPair iconPair;
iconPair.IconIndex = -1;
if (pos < 0)
- pos = s.Length();
+ pos = s.Len();
else
{
- UString num = s.Mid(pos + 1);
+ UString num = s.Ptr(pos + 1);
if (!num.IsEmpty())
{
const wchar_t *end;
- iconPair.IconIndex = (UInt32)ConvertStringToUInt64(num, &end);
- if (*end != L'\0')
+ iconPair.IconIndex = ConvertStringToUInt32(num, &end);
+ if (*end != 0)
continue;
}
}
@@ -349,10 +455,10 @@ bool CCodecIcons::FindIconIndex(const UString &ext, int &iconIndex) const
{
#ifdef _WIN32
iconIndex = -1;
- for (int i = 0; i < IconPairs.Size(); i++)
+ FOR_VECTOR (i, IconPairs)
{
const CIconPair &pair = IconPairs[i];
- if (ext.CompareNoCase(pair.Ext) == 0)
+ if (ext.IsEqualToNoCase(pair.Ext))
{
iconIndex = pair.IconIndex;
return true;
@@ -361,7 +467,8 @@ bool CCodecIcons::FindIconIndex(const UString &ext, int &iconIndex) const
#endif // #ifdef _WIN32
return false;
}
-#endif
+
+#endif // EXTERNAL_CODECS
#ifdef _7ZIP_LARGE_PAGES
extern "C"
@@ -370,7 +477,7 @@ extern "C"
}
#endif
-HRESULT CCodecs::LoadDll(const CSysString &dllPath, bool needCheckDll)
+HRESULT CCodecs::LoadDll(const FString &dllPath, bool needCheckDll)
{
#ifdef _WIN32
if (needCheckDll)
@@ -382,9 +489,7 @@ HRESULT CCodecs::LoadDll(const CSysString &dllPath, bool needCheckDll)
#endif
Libs.Add(CCodecLib());
CCodecLib &lib = Libs.Back();
- #ifdef NEW_FOLDER_INTERFACE
lib.Path = dllPath;
- #endif
bool used = false;
HRESULT res = S_OK;
if (lib.Lib.Load(dllPath))
@@ -396,23 +501,31 @@ HRESULT CCodecs::LoadDll(const CSysString &dllPath, bool needCheckDll)
#ifdef _7ZIP_LARGE_PAGES
if (g_LargePageSize != 0)
{
- SetLargePageModeFunc setLargePageMode = (SetLargePageModeFunc)lib.Lib.GetProc("SetLargePageMode");
- if (setLargePageMode != 0)
+ Func_SetLargePageMode setLargePageMode = (Func_SetLargePageMode)lib.Lib.GetProc("SetLargePageMode");
+ if (setLargePageMode)
setLargePageMode();
}
#endif
- lib.CreateObject = (CreateObjectFunc)lib.Lib.GetProc("CreateObject");
- if (lib.CreateObject != 0)
+ if (CaseSensitiveChange)
{
- int startSize = Codecs.Size();
+ Func_SetCaseSensitive setCaseSensitive = (Func_SetCaseSensitive)lib.Lib.GetProc("SetCaseSensitive");
+ if (setCaseSensitive)
+ setCaseSensitive(CaseSensitive ? 1 : 0);
+ }
+
+ lib.CreateObject = (Func_CreateObject)lib.Lib.GetProc("CreateObject");
+ if (lib.CreateObject)
+ {
+ unsigned startSize = Codecs.Size() + Hashers.Size();
res = LoadCodecs();
- used = (Codecs.Size() != startSize);
+ used = (startSize != Codecs.Size() + Hashers.Size());
if (res == S_OK)
{
startSize = Formats.Size();
res = LoadFormats();
- used = used || (Formats.Size() != startSize);
+ if (startSize != Formats.Size())
+ used = true;
}
}
}
@@ -421,15 +534,10 @@ HRESULT CCodecs::LoadDll(const CSysString &dllPath, bool needCheckDll)
return res;
}
-HRESULT CCodecs::LoadDllsFromFolder(const CSysString &folderPrefix)
+HRESULT CCodecs::LoadDllsFromFolder(const FString &folderPrefix)
{
-#ifdef _UNICODE
- NFile::NFind::CEnumeratorW enumerator(folderPrefix + CSysString(TEXT("*")));
- NFile::NFind::CFileInfoW fi;
-#else
- NFile::NFind::CEnumerator enumerator(folderPrefix + CSysString(TEXT("*")));
+ NFile::NFind::CEnumerator enumerator(folderPrefix + FCHAR_ANY_MASK);
NFile::NFind::CFileInfo fi;
-#endif
while (enumerator.Next(fi))
{
if (fi.IsDir())
@@ -441,48 +549,65 @@ HRESULT CCodecs::LoadDllsFromFolder(const CSysString &folderPrefix)
#endif
-#ifndef _SFX
-static inline void SetBuffer(CByteBuffer &bb, const Byte *data, int size)
-{
- bb.SetCapacity(size);
- memmove((Byte *)bb, data, size);
-}
-#endif
-
HRESULT CCodecs::Load()
{
#ifdef NEW_FOLDER_INTERFACE
#ifdef _WIN32
- InternalIcons.LoadIcons(g_hInstance);
+ InternalIcons.LoadIcons(g_hInstance);
#endif
#endif
Formats.Clear();
+
#ifdef EXTERNAL_CODECS
- Codecs.Clear();
+ Codecs.Clear();
+ Hashers.Clear();
#endif
+
for (UInt32 i = 0; i < g_NumArcs; i++)
{
const CArcInfo &arc = *g_Arcs[i];
CArcInfoEx item;
- item.Name = arc.Name;
+
+ item.Name.SetFromAscii(arc.Name);
item.CreateInArchive = arc.CreateInArchive;
- item.CreateOutArchive = arc.CreateOutArchive;
- item.AddExts(arc.Ext, arc.AddExt);
- item.UpdateEnabled = (arc.CreateOutArchive != 0);
- item.KeepName = arc.KeepName;
+ item.IsArcFunc = arc.IsArc;
+ item.Flags = arc.Flags;
+
+ {
+ UString e, ae;
+ if (arc.Ext)
+ e.SetFromAscii(arc.Ext);
+ if (arc.AddExt)
+ ae.SetFromAscii(arc.AddExt);
+ item.AddExts(e, ae);
+ }
#ifndef _SFX
- SetBuffer(item.StartSignature, arc.Signature, arc.SignatureSize);
+
+ item.CreateOutArchive = arc.CreateOutArchive;
+ item.UpdateEnabled = (arc.CreateOutArchive != NULL);
+ item.SignatureOffset = arc.SignatureOffset;
+ // item.Version = MY_VER_MIX;
+ item.NewInterface = true;
+
+ if (arc.IsMultiSignature())
+ ParseSignatures(arc.Signature, arc.SignatureSize, item.Signatures);
+ else
+ item.Signatures.AddNew().CopyFrom(arc.Signature, arc.SignatureSize);
+
#endif
+
Formats.Add(item);
}
+
#ifdef EXTERNAL_CODECS
- const CSysString baseFolder = GetBaseFolderPrefixFromRegistry();
- RINOK(LoadDll(baseFolder + kMainDll, false));
- RINOK(LoadDllsFromFolder(baseFolder + kCodecsFolderName TEXT(STRING_PATH_SEPARATOR)));
- RINOK(LoadDllsFromFolder(baseFolder + kFormatsFolderName TEXT(STRING_PATH_SEPARATOR)));
+ const FString baseFolder = GetBaseFolderPrefixFromRegistry();
+ RINOK(LoadDll(baseFolder + kMainDll, false));
+ RINOK(LoadDllsFromFolder(baseFolder + kCodecsFolderName FSTRING_PATH_SEPARATOR));
+ RINOK(LoadDllsFromFolder(baseFolder + kFormatsFolderName FSTRING_PATH_SEPARATOR));
#endif
+
return S_OK;
}
@@ -490,17 +615,22 @@ HRESULT CCodecs::Load()
int CCodecs::FindFormatForArchiveName(const UString &arcPath) const
{
- int slashPos1 = arcPath.ReverseFind(WCHAR_PATH_SEPARATOR);
- int slashPos2 = arcPath.ReverseFind(L'.');
+ int slashPos = arcPath.ReverseFind(WCHAR_PATH_SEPARATOR);
int dotPos = arcPath.ReverseFind(L'.');
- if (dotPos < 0 || dotPos < slashPos1 || dotPos < slashPos2)
+ if (dotPos < 0 || dotPos < slashPos)
+ return -1;
+ const UString ext = arcPath.Ptr(dotPos + 1);
+ if (ext.IsEmpty())
return -1;
- UString ext = arcPath.Mid(dotPos + 1);
- for (int i = 0; i < Formats.Size(); i++)
+ if (ext.IsEqualToNoCase(L"exe"))
+ return -1;
+ FOR_VECTOR (i, Formats)
{
const CArcInfoEx &arc = Formats[i];
+ /*
if (!arc.UpdateEnabled)
continue;
+ */
if (arc.FindExtension(ext) >= 0)
return i;
}
@@ -511,7 +641,7 @@ int CCodecs::FindFormatForExtension(const UString &ext) const
{
if (ext.IsEmpty())
return -1;
- for (int i = 0; i < Formats.Size(); i++)
+ FOR_VECTOR (i, Formats)
if (Formats[i].FindExtension(ext) >= 0)
return i;
return -1;
@@ -519,8 +649,8 @@ int CCodecs::FindFormatForExtension(const UString &ext) const
int CCodecs::FindFormatForArchiveType(const UString &arcType) const
{
- for (int i = 0; i < Formats.Size(); i++)
- if (Formats[i].Name.CompareNoCase(arcType) == 0)
+ FOR_VECTOR (i, Formats)
+ if (Formats[i].Name.IsEqualToNoCase(arcType))
return i;
return -1;
}
@@ -528,12 +658,14 @@ int CCodecs::FindFormatForArchiveType(const UString &arcType) const
bool CCodecs::FindFormatForArchiveType(const UString &arcType, CIntVector &formatIndices) const
{
formatIndices.Clear();
- for (int pos = 0; pos < arcType.Length();)
+ for (unsigned pos = 0; pos < arcType.Len();)
{
int pos2 = arcType.Find('.', pos);
if (pos2 < 0)
- pos2 = arcType.Length();
+ pos2 = arcType.Len();
const UString name = arcType.Mid(pos, pos2 - pos);
+ if (name.IsEmpty())
+ return false;
int index = FindFormatForArchiveType(name);
if (index < 0 && name != L"*")
{
@@ -546,24 +678,39 @@ bool CCodecs::FindFormatForArchiveType(const UString &arcType, CIntVector &forma
return true;
}
-#endif
+#endif // _SFX
+
#ifdef EXTERNAL_CODECS
+// #define EXPORT_CODECS
+
#ifdef EXPORT_CODECS
-extern unsigned int g_NumCodecs;
+
+extern unsigned g_NumCodecs;
STDAPI CreateCoder2(bool encode, UInt32 index, const GUID *iid, void **outObject);
STDAPI GetMethodProperty(UInt32 codecIndex, PROPID propID, PROPVARIANT *value);
-// STDAPI GetNumberOfMethods(UInt32 *numCodecs);
-#endif
+#define NUM_EXPORT_CODECS g_NumCodecs
+
+extern unsigned g_NumHashers;
+STDAPI CreateHasher(UInt32 index, IHasher **hasher);
+STDAPI GetHasherProp(UInt32 codecIndex, PROPID propID, PROPVARIANT *value);
+#define NUM_EXPORT_HASHERS g_NumHashers
+
+#else // EXPORT_CODECS
+
+#define NUM_EXPORT_CODECS 0
+#define NUM_EXPORT_HASHERS 0
+
+#endif // EXPORT_CODECS
STDMETHODIMP CCodecs::GetNumberOfMethods(UInt32 *numMethods)
{
- *numMethods =
- #ifdef EXPORT_CODECS
- g_NumCodecs +
- #endif
- Codecs.Size();
+ *numMethods = NUM_EXPORT_CODECS
+ #ifdef EXTERNAL_CODECS
+ + Codecs.Size()
+ #endif
+ ;
return S_OK;
}
@@ -574,27 +721,23 @@ STDMETHODIMP CCodecs::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *valu
return GetMethodProperty(index, propID, value);
#endif
- const CDllCodecInfo &ci = Codecs[index
- #ifdef EXPORT_CODECS
- - g_NumCodecs
- #endif
- ];
+ #ifdef EXTERNAL_CODECS
+ const CDllCodecInfo &ci = Codecs[index - NUM_EXPORT_CODECS];
- if (propID == NMethodPropID::kDecoderIsAssigned)
- {
- NWindows::NCOM::CPropVariant propVariant;
- propVariant = ci.DecoderIsAssigned;
- propVariant.Detach(value);
- return S_OK;
- }
- if (propID == NMethodPropID::kEncoderIsAssigned)
+ if (propID == NMethodPropID::kDecoderIsAssigned ||
+ propID == NMethodPropID::kEncoderIsAssigned)
{
- NWindows::NCOM::CPropVariant propVariant;
- propVariant = ci.EncoderIsAssigned;
- propVariant.Detach(value);
+ NCOM::CPropVariant prop;
+ prop = (propID == NMethodPropID::kDecoderIsAssigned) ?
+ ci.DecoderIsAssigned :
+ ci.EncoderIsAssigned;
+ prop.Detach(value);
return S_OK;
}
return Libs[ci.LibIndex].GetMethodProperty(ci.CodecIndex, propID, value);
+ #else
+ return E_FAIL;
+ #endif
}
STDMETHODIMP CCodecs::CreateDecoder(UInt32 index, const GUID *iid, void **coder)
@@ -603,14 +746,14 @@ STDMETHODIMP CCodecs::CreateDecoder(UInt32 index, const GUID *iid, void **coder)
if (index < g_NumCodecs)
return CreateCoder2(false, index, iid, coder);
#endif
- const CDllCodecInfo &ci = Codecs[index
- #ifdef EXPORT_CODECS
- - g_NumCodecs
- #endif
- ];
+ #ifdef EXTERNAL_CODECS
+ const CDllCodecInfo &ci = Codecs[index - NUM_EXPORT_CODECS];
if (ci.DecoderIsAssigned)
return Libs[ci.LibIndex].CreateObject(&ci.Decoder, iid, (void **)coder);
return S_OK;
+ #else
+ return E_FAIL;
+ #endif
}
STDMETHODIMP CCodecs::CreateEncoder(UInt32 index, const GUID *iid, void **coder)
@@ -619,35 +762,53 @@ STDMETHODIMP CCodecs::CreateEncoder(UInt32 index, const GUID *iid, void **coder)
if (index < g_NumCodecs)
return CreateCoder2(true, index, iid, coder);
#endif
- const CDllCodecInfo &ci = Codecs[index
- #ifdef EXPORT_CODECS
- - g_NumCodecs
- #endif
- ];
+ #ifdef EXTERNAL_CODECS
+ const CDllCodecInfo &ci = Codecs[index - NUM_EXPORT_CODECS];
if (ci.EncoderIsAssigned)
return Libs[ci.LibIndex].CreateObject(&ci.Encoder, iid, (void **)coder);
return S_OK;
+ #else
+ return E_FAIL;
+ #endif
}
-HRESULT CCodecs::CreateCoder(const UString &name, bool encode, CMyComPtr<ICompressCoder> &coder) const
+
+STDMETHODIMP_(UInt32) CCodecs::GetNumHashers()
{
- for (int i = 0; i < Codecs.Size(); i++)
- {
- const CDllCodecInfo &codec = Codecs[i];
- if (encode && !codec.EncoderIsAssigned || !encode && !codec.DecoderIsAssigned)
- continue;
- const CCodecLib &lib = Libs[codec.LibIndex];
- UString res;
- NWindows::NCOM::CPropVariant prop;
- RINOK(lib.GetMethodProperty(codec.CodecIndex, NMethodPropID::kName, &prop));
- if (prop.vt == VT_BSTR)
- res = prop.bstrVal;
- else if (prop.vt != VT_EMPTY)
- continue;
- if (name.CompareNoCase(res) == 0)
- return lib.CreateObject(encode ? &codec.Encoder : &codec.Decoder, &IID_ICompressCoder, (void **)&coder);
- }
- return CLASS_E_CLASSNOTAVAILABLE;
+ return NUM_EXPORT_HASHERS
+ #ifdef EXTERNAL_CODECS
+ + Hashers.Size()
+ #endif
+ ;
+}
+
+STDMETHODIMP CCodecs::GetHasherProp(UInt32 index, PROPID propID, PROPVARIANT *value)
+{
+ #ifdef EXPORT_CODECS
+ if (index < g_NumHashers)
+ return ::GetHasherProp(index, propID, value);
+ #endif
+
+ #ifdef EXTERNAL_CODECS
+ const CDllHasherInfo &ci = Hashers[index - NUM_EXPORT_HASHERS];
+ return Libs[ci.LibIndex].Hashers->GetHasherProp(ci.HasherIndex, propID, value);
+ #else
+ return E_FAIL;
+ #endif
+}
+
+STDMETHODIMP CCodecs::CreateHasher(UInt32 index, IHasher **hasher)
+{
+ #ifdef EXPORT_CODECS
+ if (index < g_NumHashers)
+ return CreateHasher(index, hasher);
+ #endif
+ #ifdef EXTERNAL_CODECS
+ const CDllHasherInfo &ci = Hashers[index - NUM_EXPORT_HASHERS];
+ return Libs[ci.LibIndex].Hashers->CreateHasher(ci.HasherIndex, hasher);
+ #else
+ return E_FAIL;
+ #endif
}
int CCodecs::GetCodecLibIndex(UInt32 index)
@@ -657,11 +818,21 @@ int CCodecs::GetCodecLibIndex(UInt32 index)
return -1;
#endif
#ifdef EXTERNAL_CODECS
- const CDllCodecInfo &ci = Codecs[index
- #ifdef EXPORT_CODECS
- - g_NumCodecs
- #endif
- ];
+ const CDllCodecInfo &ci = Codecs[index - NUM_EXPORT_CODECS];
+ return ci.LibIndex;
+ #else
+ return -1;
+ #endif
+}
+
+int CCodecs::GetHasherLibIndex(UInt32 index)
+{
+ #ifdef EXPORT_CODECS
+ if (index < g_NumHashers)
+ return -1;
+ #endif
+ #ifdef EXTERNAL_CODECS
+ const CDllHasherInfo &ci = Hashers[index - NUM_EXPORT_HASHERS];
return ci.LibIndex;
#else
return -1;
@@ -673,7 +844,7 @@ bool CCodecs::GetCodecEncoderIsAssigned(UInt32 index)
#ifdef EXPORT_CODECS
if (index < g_NumCodecs)
{
- NWindows::NCOM::CPropVariant prop;
+ NCOM::CPropVariant prop;
if (GetProperty(index, NMethodPropID::kEncoder, &prop) == S_OK)
if (prop.vt != VT_EMPTY)
return true;
@@ -681,11 +852,7 @@ bool CCodecs::GetCodecEncoderIsAssigned(UInt32 index)
}
#endif
#ifdef EXTERNAL_CODECS
- const CDllCodecInfo &ci = Codecs[index
- #ifdef EXPORT_CODECS
- - g_NumCodecs
- #endif
- ];
+ const CDllCodecInfo &ci = Codecs[index - NUM_EXPORT_CODECS];
return ci.EncoderIsAssigned;
#else
return false;
@@ -694,8 +861,7 @@ bool CCodecs::GetCodecEncoderIsAssigned(UInt32 index)
HRESULT CCodecs::GetCodecId(UInt32 index, UInt64 &id)
{
- UString s;
- NWindows::NCOM::CPropVariant prop;
+ NCOM::CPropVariant prop;
RINOK(GetProperty(index, NMethodPropID::kID, &prop));
if (prop.vt != VT_UI8)
return E_INVALIDARG;
@@ -706,11 +872,39 @@ HRESULT CCodecs::GetCodecId(UInt32 index, UInt64 &id)
UString CCodecs::GetCodecName(UInt32 index)
{
UString s;
- NWindows::NCOM::CPropVariant prop;
+ NCOM::CPropVariant prop;
if (GetProperty(index, NMethodPropID::kName, &prop) == S_OK)
if (prop.vt == VT_BSTR)
s = prop.bstrVal;
return s;
}
-#endif
+UInt64 CCodecs::GetHasherId(UInt32 index)
+{
+ NCOM::CPropVariant prop;
+ RINOK(GetHasherProp(index, NMethodPropID::kID, &prop));
+ if (prop.vt != VT_UI8)
+ return 0;
+ return prop.uhVal.QuadPart;
+}
+
+UString CCodecs::GetHasherName(UInt32 index)
+{
+ UString s;
+ NCOM::CPropVariant prop;
+ if (GetHasherProp(index, NMethodPropID::kName, &prop) == S_OK)
+ if (prop.vt == VT_BSTR)
+ s = prop.bstrVal;
+ return s;
+}
+
+UInt32 CCodecs::GetHasherDigestSize(UInt32 index)
+{
+ NCOM::CPropVariant prop;
+ RINOK(GetHasherProp(index, NMethodPropID::kDigestSize, &prop));
+ if (prop.vt != VT_UI4)
+ return 0;
+ return prop.ulVal;
+}
+
+#endif // EXTERNAL_CODECS
diff --git a/src/libs/7zip/unix/CPP/7zip/UI/Common/LoadCodecs.h b/src/libs/7zip/unix/CPP/7zip/UI/Common/LoadCodecs.h
index a633dd2e1..d254ae659 100644
--- a/src/libs/7zip/unix/CPP/7zip/UI/Common/LoadCodecs.h
+++ b/src/libs/7zip/unix/CPP/7zip/UI/Common/LoadCodecs.h
@@ -1,12 +1,13 @@
// LoadCodecs.h
-#ifndef __LOADCODECS_H
-#define __LOADCODECS_H
+#ifndef __LOAD_CODECS_H
+#define __LOAD_CODECS_H
-#include "../../../Common/Types.h"
+#include "../../../Common/MyBuffer.h"
#include "../../../Common/MyCom.h"
#include "../../../Common/MyString.h"
-#include "../../../Common/Buffer.h"
+#include "../../../Common/ComTry.h"
+
#include "../../ICoder.h"
#ifdef EXTERNAL_CODECS
@@ -23,15 +24,19 @@ struct CDllCodecInfo
UInt32 CodecIndex;
};
-#include "../../Archive/IArchive.h"
+struct CDllHasherInfo
+{
+ int LibIndex;
+ UInt32 HasherIndex;
+};
-typedef IInArchive * (*CreateInArchiveP)();
-typedef IOutArchive * (*CreateOutArchiveP)();
+#include "../../Archive/IArchive.h"
struct CArcExtInfo
{
UString Ext;
UString AddExt;
+
CArcExtInfo() {}
CArcExtInfo(const UString &ext): Ext(ext) {}
CArcExtInfo(const UString &ext, const UString &addExt): Ext(ext), AddExt(addExt) {}
@@ -40,37 +45,55 @@ struct CArcExtInfo
struct CArcInfoEx
{
- #ifdef EXTERNAL_CODECS
- int LibIndex;
- UInt32 FormatIndex;
- CLSID ClassID;
- #endif
- bool UpdateEnabled;
- CreateInArchiveP CreateInArchive;
- CreateOutArchiveP CreateOutArchive;
+ UInt32 Flags;
+
+ Func_CreateInArchive CreateInArchive;
+ Func_IsArc IsArcFunc;
+
UString Name;
CObjectVector<CArcExtInfo> Exts;
+
#ifndef _SFX
- CByteBuffer StartSignature;
- // CByteBuffer FinishSignature;
- #ifdef NEW_FOLDER_INTERFACE
- UStringVector AssociateExts;
+ Func_CreateOutArchive CreateOutArchive;
+ bool UpdateEnabled;
+ bool NewInterface;
+ // UInt32 Version;
+ UInt32 SignatureOffset;
+ CObjectVector<CByteBuffer> Signatures;
+ #ifdef NEW_FOLDER_INTERFACE
+ UStringVector AssociateExts;
+ #endif
#endif
+
+ #ifdef EXTERNAL_CODECS
+ int LibIndex;
+ UInt32 FormatIndex;
+ CLSID ClassID;
#endif
- bool KeepName;
+
+ bool Flags_KeepName() const { return (Flags & NArcInfoFlags::kKeepName) != 0; }
+ bool Flags_FindSignature() const { return (Flags & NArcInfoFlags::kFindSignature) != 0; }
+
+ bool Flags_AltStreams() const { return (Flags & NArcInfoFlags::kAltStreams) != 0; }
+ bool Flags_NtSecure() const { return (Flags & NArcInfoFlags::kNtSecure) != 0; }
+ bool Flags_SymLinks() const { return (Flags & NArcInfoFlags::kSymLinks) != 0; }
+ bool Flags_HardLinks() const { return (Flags & NArcInfoFlags::kHardLinks) != 0; }
+
+ bool Flags_UseGlobalOffset() const { return (Flags & NArcInfoFlags::kUseGlobalOffset) != 0; }
+ bool Flags_StartOpen() const { return (Flags & NArcInfoFlags::kStartOpen) != 0; }
+ bool Flags_BackwardOpen() const { return (Flags & NArcInfoFlags::kBackwardOpen) != 0; }
+ bool Flags_PreArc() const { return (Flags & NArcInfoFlags::kPreArc) != 0; }
+ bool Flags_PureStartOpen() const { return (Flags & NArcInfoFlags::kPureStartOpen) != 0; }
+
UString GetMainExt() const
{
if (Exts.IsEmpty())
return UString();
return Exts[0].Ext;
}
- int FindExtension(const UString &ext) const
- {
- for (int i = 0; i < Exts.Size(); i++)
- if (ext.CompareNoCase(Exts[i].Ext) == 0)
- return i;
- return -1;
- }
+ int FindExtension(const UString &ext) const;
+
+ /*
UString GetAllExtensions() const
{
UString s;
@@ -82,25 +105,31 @@ struct CArcInfoEx
}
return s;
}
+ */
+
+ void AddExts(const UString &ext, const UString &addExt);
- void AddExts(const wchar_t* ext, const wchar_t* addExt);
+ bool IsSplit() const { return StringsAreEqualNoCase_Ascii(Name, "Split"); }
+ // bool IsRar() const { return StringsAreEqualNoCase_Ascii(Name, "Rar"); }
CArcInfoEx():
- #ifdef EXTERNAL_CODECS
- LibIndex(-1),
- #endif
- UpdateEnabled(false),
- CreateInArchive(0), CreateOutArchive(0),
- KeepName(false)
- #ifndef _SFX
- #endif
+ Flags(0),
+ CreateInArchive(NULL),
+ IsArcFunc(NULL)
+ #ifndef _SFX
+ , CreateOutArchive(NULL)
+ , UpdateEnabled(false)
+ , NewInterface(false)
+ // , Version(0)
+ , SignatureOffset(0)
+ #endif
+ #ifdef EXTERNAL_CODECS
+ , LibIndex(-1)
+ #endif
{}
};
#ifdef EXTERNAL_CODECS
-typedef UInt32 (WINAPI *GetMethodPropertyFunc)(UInt32 index, PROPID propID, PROPVARIANT *value);
-typedef UInt32 (WINAPI *CreateObjectFunc)(const GUID *clsID, const GUID *interfaceID, void **outObject);
-
#ifdef NEW_FOLDER_INTERFACE
struct CCodecIcons
@@ -117,24 +146,28 @@ struct CCodecIcons
#endif
struct CCodecLib
-#ifdef NEW_FOLDER_INTERFACE
-: public CCodecIcons
-#endif
+ #ifdef NEW_FOLDER_INTERFACE
+ : public CCodecIcons
+ #endif
{
NWindows::NDLL::CLibrary Lib;
- GetMethodPropertyFunc GetMethodProperty;
- CreateObjectFunc CreateObject;
+ FString Path;
+ Func_GetMethodProperty GetMethodProperty;
+ Func_CreateObject CreateObject;
+ CMyComPtr<IHashers> Hashers;
+
#ifdef NEW_FOLDER_INTERFACE
- CSysString Path;
void LoadIcons() { CCodecIcons::LoadIcons((HMODULE)Lib); }
#endif
- CCodecLib(): GetMethodProperty(0) {}
+
+ CCodecLib(): GetMethodProperty(NULL) {}
};
#endif
class CCodecs:
#ifdef EXTERNAL_CODECS
public ICompressCodecsInfo,
+ public IHashers,
#else
public IUnknown,
#endif
@@ -143,7 +176,8 @@ class CCodecs:
public:
#ifdef EXTERNAL_CODECS
CObjectVector<CCodecLib> Libs;
- CObjectVector<CDllCodecInfo> Codecs;
+ CRecordVector<CDllCodecInfo> Codecs;
+ CRecordVector<CDllHasherInfo> Hashers;
#ifdef NEW_FOLDER_INTERFACE
CCodecIcons InternalIcons;
@@ -151,8 +185,8 @@ public:
HRESULT LoadCodecs();
HRESULT LoadFormats();
- HRESULT LoadDll(const CSysString &path, bool needCheckDll);
- HRESULT LoadDllsFromFolder(const CSysString &folderPrefix);
+ HRESULT LoadDll(const FString &path, bool needCheckDll);
+ HRESULT LoadDllsFromFolder(const FString &folderPrefix);
HRESULT CreateArchiveHandler(const CArcInfoEx &ai, void **archive, bool outHandler) const
{
@@ -162,8 +196,18 @@ public:
public:
CObjectVector<CArcInfoEx> Formats;
+ bool CaseSensitiveChange;
+ bool CaseSensitive;
+
+ CCodecs(): CaseSensitiveChange(false), CaseSensitive(false) {}
+
+ const wchar_t *GetFormatNamePtr(int formatIndex)
+ {
+ return formatIndex < 0 ? L"#" : (const wchar_t *)Formats[formatIndex].Name;
+ }
+
HRESULT Load();
-
+
#ifndef _SFX
int FindFormatForArchiveName(const UString &arcPath) const;
int FindFormatForExtension(const UString &ext) const;
@@ -171,65 +215,89 @@ public:
bool FindFormatForArchiveType(const UString &arcType, CIntVector &formatIndices) const;
#endif
- MY_UNKNOWN_IMP
-
#ifdef EXTERNAL_CODECS
+
+ MY_UNKNOWN_IMP2(ICompressCodecsInfo, IHashers)
+
STDMETHOD(GetNumberOfMethods)(UInt32 *numMethods);
STDMETHOD(GetProperty)(UInt32 index, PROPID propID, PROPVARIANT *value);
STDMETHOD(CreateDecoder)(UInt32 index, const GUID *interfaceID, void **coder);
STDMETHOD(CreateEncoder)(UInt32 index, const GUID *interfaceID, void **coder);
- #endif
+
+ STDMETHOD_(UInt32, GetNumHashers)();
+ STDMETHOD(GetHasherProp)(UInt32 index, PROPID propID, PROPVARIANT *value);
+ STDMETHOD(CreateHasher)(UInt32 index, IHasher **hasher);
+
+ #else
+
+ MY_UNKNOWN_IMP
+
+ #endif // EXTERNAL_CODECS
+
+ #ifdef EXTERNAL_CODECS
int GetCodecLibIndex(UInt32 index);
bool GetCodecEncoderIsAssigned(UInt32 index);
HRESULT GetCodecId(UInt32 index, UInt64 &id);
UString GetCodecName(UInt32 index);
- HRESULT CreateInArchive(int formatIndex, CMyComPtr<IInArchive> &archive) const
+ int GetHasherLibIndex(UInt32 index);
+ UInt64 GetHasherId(UInt32 index);
+ UString GetHasherName(UInt32 index);
+ UInt32 GetHasherDigestSize(UInt32 index);
+
+ #endif
+
+ HRESULT CreateInArchive(unsigned formatIndex, CMyComPtr<IInArchive> &archive) const
{
const CArcInfoEx &ai = Formats[formatIndex];
#ifdef EXTERNAL_CODECS
if (ai.LibIndex < 0)
#endif
{
+ COM_TRY_BEGIN
archive = ai.CreateInArchive();
return S_OK;
+ COM_TRY_END
}
#ifdef EXTERNAL_CODECS
return CreateArchiveHandler(ai, (void **)&archive, false);
#endif
}
- HRESULT CreateOutArchive(int formatIndex, CMyComPtr<IOutArchive> &archive) const
+
+ #ifndef _SFX
+
+ HRESULT CreateOutArchive(unsigned formatIndex, CMyComPtr<IOutArchive> &archive) const
{
const CArcInfoEx &ai = Formats[formatIndex];
#ifdef EXTERNAL_CODECS
if (ai.LibIndex < 0)
#endif
{
+ COM_TRY_BEGIN
archive = ai.CreateOutArchive();
return S_OK;
+ COM_TRY_END
}
#ifdef EXTERNAL_CODECS
return CreateArchiveHandler(ai, (void **)&archive, true);
#endif
}
+
int FindOutFormatFromName(const UString &name) const
{
- for (int i = 0; i < Formats.Size(); i++)
+ FOR_VECTOR (i, Formats)
{
const CArcInfoEx &arc = Formats[i];
if (!arc.UpdateEnabled)
continue;
- if (arc.Name.CompareNoCase(name) == 0)
+ if (arc.Name.IsEqualToNoCase(name))
return i;
}
return -1;
}
- #ifdef EXTERNAL_CODECS
- HRESULT CreateCoder(const UString &name, bool encode, CMyComPtr<ICompressCoder> &coder) const;
- #endif
-
+ #endif // _SFX
};
#endif
diff --git a/src/libs/7zip/unix/CPP/7zip/UI/Common/OpenArchive.cpp b/src/libs/7zip/unix/CPP/7zip/UI/Common/OpenArchive.cpp
index 5e67915bb..7c53bd99f 100644
--- a/src/libs/7zip/unix/CPP/7zip/UI/Common/OpenArchive.cpp
+++ b/src/libs/7zip/unix/CPP/7zip/UI/Common/OpenArchive.cpp
@@ -2,27 +2,487 @@
#include "StdAfx.h"
-#include "Common/Wildcard.h"
+// #define SHOW_DEBUG_INFO
-#include "Windows/FileDir.h"
-#include "Windows/PropVariant.h"
+#ifdef SHOW_DEBUG_INFO
+#include <stdio.h>
+#endif
+
+#include "../../../../C/CpuArch.h"
+
+#include "../../../Common/ComTry.h"
+#include "../../../Common/IntToString.h"
+#include "../../../Common/StringConvert.h"
+#include "../../../Common/StringToInt.h"
+#include "../../../Common/Wildcard.h"
+
+#include "../../../Windows/FileDir.h"
#include "../../Common/FileStreams.h"
+#include "../../Common/LimitedStreams.h"
+#include "../../Common/ProgressUtils.h"
#include "../../Common/StreamUtils.h"
+#include "../../Compress/CopyCoder.h"
+
#include "DefaultName.h"
#include "OpenArchive.h"
+#ifndef _SFX
+#include "SetProperties.h"
+#endif
+
+#ifdef SHOW_DEBUG_INFO
+#define PRF(x) x
+#else
+#define PRF(x)
+#endif
+
+// increase it, if you need to support larger SFX stubs
+static const UInt64 kMaxCheckStartPosition = 1 << 22;
+
+/*
+Open:
+ - formatIndex >= 0 (exact Format)
+ 1) Open with main type. Archive handler is allowed to use archive start finder.
+ Warning, if there is tail.
+
+ - formatIndex = -1 (Parser:0) (default)
+ - same as #1 but doesn't return Parser
+
+ - formatIndex = -2 (#1)
+ - file has supported extension (like a.7z)
+ Open with that main type (only starting from start of file).
+ - open OK:
+ - if there is no tail - return OK
+ - if there is tail:
+ - archive is not "Self Exe" - return OK with Warning, that there is tail
+ - archive is "Self Exe"
+ ignore "Self Exe" stub, and tries to open tail
+ - tail can be open as archive - shows that archive and stub size property.
+ - tail can't be open as archive - shows Parser ???
+ - open FAIL:
+ Try to open with all other types from offset 0 only.
+ If some open type is OK and physical archive size is uequal or larger
+ than file size, then return that archive with warning that can not be open as [extension type].
+ If extension was EXE, it will try to open as unknown_extension case
+ - file has unknown extension (like a.hhh)
+ It tries to open via parser code.
+ - if there is full archive or tail archive and unknown block or "Self Exe"
+ at front, it shows tail archive and stub size property.
+ - in another cases, if there is some archive inside file, it returns parser/
+ - in another cases, it retuens S_FALSE
+
+
+ - formatIndex = -3 (#2)
+ - same as #1, but
+ - stub (EXE) + archive is open in Parser
+
+ - formatIndex = -4 (#3)
+ - returns only Parser. skip full file archive. And show other sub-archives
+
+ - formatIndex = -5 (#4)
+ - returns only Parser. skip full file archive. And show other sub-archives for each byte pos
+
+*/
+
+
+
+
using namespace NWindows;
-// Static-SFX (for Linux) can be big.
-const UInt64 kMaxCheckStartPosition = 1 << 22;
+/*
+#ifdef _SFX
+#define OPEN_PROPS_PARAM
+#else
+#define OPEN_PROPS_PARAM , props
+#endif
+*/
+
+/*
+CArc::~CArc()
+{
+ GetRawProps.Release();
+ Archive.Release();
+ printf("\nCArc::~CArc()\n");
+}
+*/
+
+#ifndef _SFX
+
+namespace NArchive {
+namespace NParser {
+
+struct CParseItem
+{
+ UInt64 Offset;
+ UInt64 Size;
+ // UInt64 OkSize;
+ UString Name;
+ UString Extension;
+ FILETIME FileTime;
+ UString Comment;
+ UString ArcType;
+
+ bool FileTime_Defined;
+ bool UnpackSize_Defined;
+ bool NumSubDirs_Defined;
+ bool NumSubFiles_Defined;
+
+ bool IsSelfExe;
+ bool IsNotArcType;
+
+ UInt64 UnpackSize;
+ UInt64 NumSubDirs;
+ UInt64 NumSubFiles;
+
+ int FormatIndex;
+
+ bool LenIsUnknown;
+
+ CParseItem():
+ LenIsUnknown(false),
+ FileTime_Defined(false),
+ UnpackSize_Defined(false),
+ NumSubFiles_Defined(false),
+ NumSubDirs_Defined(false),
+ IsSelfExe(false),
+ IsNotArcType(false)
+ // OkSize(0)
+ {}
+
+ /*
+ bool IsEqualTo(const CParseItem &item) const
+ {
+ return Offset == item.Offset && Size == item.Size;
+ }
+ */
+
+ void NormalizeOffset()
+ {
+ if ((Int64)Offset < 0)
+ {
+ Size += Offset;
+ // OkSize += Offset;
+ Offset = 0;
+ }
+ }
+};
+
+class CHandler:
+ public IInArchive,
+ public IInArchiveGetStream,
+ public CMyUnknownImp
+{
+public:
+ CObjectVector<CParseItem> _items;
+ UInt64 _maxEndOffset;
+ CMyComPtr<IInStream> _stream;
+
+ MY_UNKNOWN_IMP2(
+ IInArchive,
+ IInArchiveGetStream)
+
+ INTERFACE_IInArchive(;)
+ STDMETHOD(GetStream)(UInt32 index, ISequentialInStream **stream);
+
+ UInt64 GetLastEnd() const
+ {
+ if (_items.IsEmpty())
+ return 0;
+ const CParseItem &back = _items.Back();
+ return back.Offset + back.Size;
+ }
+
+ void AddUnknownItem(UInt64 next);
+ int FindInsertPos(const CParseItem &item);
+ void AddItem(const CParseItem &item);
+ // void Init();
+
+ CHandler()
+ {
+ _maxEndOffset = 0;
+ }
+};
+
+int CHandler::FindInsertPos(const CParseItem &item)
+{
+ unsigned left = 0, right = _items.Size();
+ while (left != right)
+ {
+ unsigned mid = (left + right) / 2;
+ const CParseItem & midItem = _items[mid];
+ if (item.Offset < midItem.Offset)
+ right = mid;
+ else if (item.Offset > midItem.Offset)
+ left = mid + 1;
+ else if (item.Size < midItem.Size)
+ right = mid;
+ else if (item.Size > midItem.Size)
+ left = mid + 1;
+ else
+ {
+ left = mid + 1;
+ // return -1;
+ }
+ }
+ return left;
+}
-HRESULT GetArchiveItemBoolProp(IInArchive *archive, UInt32 index, PROPID propID, bool &result)
+void CHandler::AddUnknownItem(UInt64 next)
+{
+ /*
+ UInt64 prevEnd = 0;
+ if (!_items.IsEmpty())
+ {
+ const CParseItem &back = _items.Back();
+ prevEnd = back.Offset + back.Size;
+ }
+ */
+ if (_maxEndOffset < next)
+ {
+ CParseItem item2;
+ item2.Offset = _maxEndOffset;
+ item2.Size = next - _maxEndOffset;
+ _maxEndOffset = next;
+ _items.Add(item2);
+ }
+ else if (_maxEndOffset > next && !_items.IsEmpty())
+ {
+ CParseItem &back = _items.Back();
+ if (back.LenIsUnknown)
+ {
+ back.Size = next - back.Offset;
+ _maxEndOffset = next;
+ }
+ }
+}
+
+void CHandler::AddItem(const CParseItem &item)
+{
+ AddUnknownItem(item.Offset);
+ int pos = FindInsertPos(item);
+ if (pos >= 0)
+ {
+ _items.Insert(pos, item);
+ UInt64 next = item.Offset + item.Size;
+ if (_maxEndOffset < next)
+ _maxEndOffset = next;
+ }
+}
+
+/*
+static const STATPROPSTG kProps[] =
+{
+ { NULL, kpidPath, VT_BSTR},
+ { NULL, kpidSize, VT_UI8},
+ { NULL, kpidMTime, VT_FILETIME},
+ { NULL, kpidType, VT_BSTR},
+ { NULL, kpidComment, VT_BSTR},
+ { NULL, kpidOffset, VT_UI8},
+ { NULL, kpidUnpackSize, VT_UI8},
+// { NULL, kpidNumSubDirs, VT_UI8},
+};
+*/
+
+static const Byte kProps[] =
+{
+ kpidPath,
+ kpidSize,
+ kpidMTime,
+ kpidType,
+ kpidComment,
+ kpidOffset,
+ kpidUnpackSize
+};
+
+IMP_IInArchive_Props
+IMP_IInArchive_ArcProps_NO
+
+STDMETHODIMP CHandler::Open(IInStream *stream, const UInt64 *, IArchiveOpenCallback * /* openArchiveCallback */)
+{
+ COM_TRY_BEGIN
+ {
+ Close();
+ _stream = stream;
+ }
+ return S_OK;
+ COM_TRY_END
+}
+
+STDMETHODIMP CHandler::Close()
+{
+ _items.Clear();
+ _stream.Release();
+ return S_OK;
+}
+
+STDMETHODIMP CHandler::GetNumberOfItems(UInt32 *numItems)
+{
+ *numItems = _items.Size();
+ return S_OK;
+}
+
+STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *value)
+{
+ COM_TRY_BEGIN
+ NCOM::CPropVariant prop;
+
+ const CParseItem &item = _items[index];
+
+ switch (propID)
+ {
+ case kpidPath:
+ {
+ wchar_t sz[32];
+ ConvertUInt32ToString(index + 1, sz);
+ UString s = sz;
+ if (!item.Name.IsEmpty())
+ {
+ s += L'.';
+ s += item.Name;
+ }
+ if (!item.Extension.IsEmpty())
+ {
+ s += L'.';
+ s += item.Extension;
+ }
+ prop = s; break;
+ }
+ case kpidSize:
+ case kpidPackSize: prop = item.Size; break;
+ case kpidOffset: prop = item.Offset; break;
+ case kpidUnpackSize: if (item.UnpackSize_Defined) prop = item.UnpackSize; break;
+ case kpidNumSubFiles: if (item.NumSubFiles_Defined) prop = item.NumSubFiles; break;
+ case kpidNumSubDirs: if (item.NumSubDirs_Defined) prop = item.NumSubDirs; break;
+ case kpidMTime: if (item.FileTime_Defined) prop = item.FileTime; break;
+ case kpidComment: if (!item.Comment.IsEmpty()) prop = item.Comment; break;
+ case kpidType: if (!item.ArcType.IsEmpty()) prop = item.ArcType; break;
+ }
+ prop.Detach(value);
+ return S_OK;
+ COM_TRY_END
+}
+
+HRESULT CHandler::Extract(const UInt32 *indices, UInt32 numItems,
+ Int32 testMode, IArchiveExtractCallback *extractCallback)
+{
+ COM_TRY_BEGIN
+ bool allFilesMode = (numItems == (UInt32)(Int32)-1);
+ if (allFilesMode)
+ numItems = _items.Size();
+ if (_stream && numItems == 0)
+ return S_OK;
+ UInt64 totalSize = 0;
+ UInt32 i;
+ for (i = 0; i < numItems; i++)
+ totalSize += _items[allFilesMode ? i : indices[i]].Size;
+ extractCallback->SetTotal(totalSize);
+
+ totalSize = 0;
+
+ CLocalProgress *lps = new CLocalProgress;
+ CMyComPtr<ICompressProgressInfo> progress = lps;
+ lps->Init(extractCallback, false);
+
+ CLimitedSequentialInStream *streamSpec = new CLimitedSequentialInStream;
+ CMyComPtr<ISequentialInStream> inStream(streamSpec);
+ streamSpec->SetStream(_stream);
+
+ CLimitedSequentialOutStream *outStreamSpec = new CLimitedSequentialOutStream;
+ CMyComPtr<ISequentialOutStream> outStream(outStreamSpec);
+
+ NCompress::CCopyCoder *copyCoderSpec = new NCompress::CCopyCoder();
+ CMyComPtr<ICompressCoder> copyCoder = copyCoderSpec;
+
+ for (i = 0; i < numItems; i++)
+ {
+ lps->InSize = totalSize;
+ lps->OutSize = totalSize;
+ RINOK(lps->SetCur());
+ CMyComPtr<ISequentialOutStream> realOutStream;
+ Int32 askMode = testMode ?
+ NExtract::NAskMode::kTest :
+ NExtract::NAskMode::kExtract;
+ Int32 index = allFilesMode ? i : indices[i];
+ const CParseItem &item = _items[index];
+
+ RINOK(extractCallback->GetStream(index, &realOutStream, askMode));
+ UInt64 unpackSize = item.Size;
+ totalSize += unpackSize;
+ bool skipMode = false;
+ if (!testMode && !realOutStream)
+ continue;
+ RINOK(extractCallback->PrepareOperation(askMode));
+
+ outStreamSpec->SetStream(realOutStream);
+ realOutStream.Release();
+ outStreamSpec->Init(skipMode ? 0 : unpackSize, true);
+
+ Int32 opRes = NExtract::NOperationResult::kOK;
+ RINOK(_stream->Seek(item.Offset, STREAM_SEEK_SET, NULL));
+ streamSpec->Init(unpackSize);
+ RINOK(copyCoder->Code(inStream, outStream, NULL, NULL, progress));
+
+ if (outStreamSpec->GetRem() != 0)
+ opRes = NExtract::NOperationResult::kDataError;
+ outStreamSpec->ReleaseStream();
+ RINOK(extractCallback->SetOperationResult(opRes));
+ }
+ return S_OK;
+ COM_TRY_END
+}
+
+
+STDMETHODIMP CHandler::GetStream(UInt32 index, ISequentialInStream **stream)
+{
+ COM_TRY_BEGIN
+ const CParseItem &item = _items[index];
+ return CreateLimitedInStream(_stream, item.Offset, item.Size, stream);
+ COM_TRY_END
+}
+
+}}
+
+#endif
+
+HRESULT Archive_GetItemBoolProp(IInArchive *arc, UInt32 index, PROPID propID, bool &result) throw()
+{
+ NCOM::CPropVariant prop;
+ result = false;
+ RINOK(arc->GetProperty(index, propID, &prop));
+ if (prop.vt == VT_BOOL)
+ result = VARIANT_BOOLToBool(prop.boolVal);
+ else if (prop.vt != VT_EMPTY)
+ return E_FAIL;
+ return S_OK;
+}
+
+HRESULT Archive_IsItem_Folder(IInArchive *arc, UInt32 index, bool &result) throw()
+{
+ return Archive_GetItemBoolProp(arc, index, kpidIsDir, result);
+}
+
+HRESULT Archive_IsItem_Aux(IInArchive *arc, UInt32 index, bool &result) throw()
+{
+ return Archive_GetItemBoolProp(arc, index, kpidIsAux, result);
+}
+
+HRESULT Archive_IsItem_AltStream(IInArchive *arc, UInt32 index, bool &result) throw()
+{
+ return Archive_GetItemBoolProp(arc, index, kpidIsAltStream, result);
+}
+
+HRESULT Archive_IsItem_Deleted(IInArchive *arc, UInt32 index, bool &result) throw()
+{
+ return Archive_GetItemBoolProp(arc, index, kpidIsDeleted, result);
+}
+
+static HRESULT Archive_GetArcBoolProp(IInArchive *arc, PROPID propid, bool &result)
{
NCOM::CPropVariant prop;
result = false;
- RINOK(archive->GetProperty(index, propID, &prop));
+ RINOK(arc->GetArchiveProperty(propid, &prop));
if (prop.vt == VT_BOOL)
result = VARIANT_BOOLToBool(prop.boolVal);
else if (prop.vt != VT_EMPTY)
@@ -30,13 +490,179 @@ HRESULT GetArchiveItemBoolProp(IInArchive *archive, UInt32 index, PROPID propID,
return S_OK;
}
-HRESULT IsArchiveItemFolder(IInArchive *archive, UInt32 index, bool &result)
+static HRESULT Archive_GetArcProp_UInt(IInArchive *arc, PROPID propid, UInt64 &result, bool &defined)
+{
+ defined = false;
+ NCOM::CPropVariant prop;
+ RINOK(arc->GetArchiveProperty(propid, &prop));
+ switch (prop.vt)
+ {
+ case VT_UI4: result = prop.ulVal; defined = true; break;
+ case VT_I4: result = prop.lVal; defined = true; break;
+ case VT_UI8: result = (UInt64)prop.uhVal.QuadPart; defined = true; break;
+ case VT_I8: result = (UInt64)prop.hVal.QuadPart; defined = true; break;
+ case VT_EMPTY: break;
+ default: return E_FAIL;
+ }
+ return S_OK;
+}
+
+static HRESULT Archive_GetArcProp_Int(IInArchive *arc, PROPID propid, Int64 &result, bool &defined)
{
- return GetArchiveItemBoolProp(archive, index, kpidIsDir, result);
+ defined = false;
+ NCOM::CPropVariant prop;
+ RINOK(arc->GetArchiveProperty(propid, &prop));
+ switch (prop.vt)
+ {
+ case VT_UI4: result = prop.ulVal; defined = true; break;
+ case VT_I4: result = prop.lVal; defined = true; break;
+ case VT_UI8: result = (Int64)prop.uhVal.QuadPart; defined = true; break;
+ case VT_I8: result = (Int64)prop.hVal.QuadPart; defined = true; break;
+ case VT_EMPTY: break;
+ default: return E_FAIL;
+ }
+ return S_OK;
+}
+
+HRESULT CArc::GetItemPathToParent(UInt32 index, UInt32 parent, UStringVector &parts) const
+{
+ if (!GetRawProps)
+ return E_FAIL;
+ UInt32 curIndex = index;
+ bool prevWasAltStream = false;
+ for (;;)
+ {
+ UString s;
+
+ #ifdef MY_CPU_LE
+ const void *p;
+ UInt32 size;
+ UInt32 propType;
+ RINOK(GetRawProps->GetRawProp(curIndex, kpidName, &p, &size, &propType));
+ if (p && propType == PROP_DATA_TYPE_wchar_t_PTR_Z_LE)
+ s = (const wchar_t *)p;
+ else
+ #endif
+ {
+ NCOM::CPropVariant prop;
+ RINOK(Archive->GetProperty(curIndex, kpidName, &prop));
+ if (prop.vt == VT_BSTR)
+ s = prop.bstrVal;
+ else if (prop.vt == VT_EMPTY)
+ s = L"[Content]";
+ else
+ return E_FAIL;
+ }
+
+ if (prevWasAltStream)
+ parts[0] = s + L":" + parts[0];
+ else
+ parts.Insert(0, s);
+
+ UInt32 curParent = (UInt32)(Int32)-1;
+ UInt32 parentType = 0;
+ RINOK(GetRawProps->GetParent(curIndex, &curParent, &parentType));
+ if (parent == curParent)
+ return S_OK;
+ if (curParent == (UInt32)(Int32)-1)
+ return E_FAIL;
+ prevWasAltStream = (parentType == NParentType::kAltStream);
+ curIndex = curParent;
+ }
}
HRESULT CArc::GetItemPath(UInt32 index, UString &result) const
{
+ #ifdef MY_CPU_LE
+ if (GetRawProps)
+ {
+ const void *p;
+ UInt32 size;
+ UInt32 propType;
+ if (!IsTree)
+ {
+ if (GetRawProps->GetRawProp(index, kpidPath, &p, &size, &propType) == S_OK &&
+ propType == NPropDataType::kUtf16z)
+ {
+ unsigned len = size / 2 - 1;
+ wchar_t *s = result.GetBuffer(len);
+ for (unsigned i = 0; i < len; i++)
+ {
+ wchar_t c = GetUi16(p);
+ p = (const void *)((const Byte *)p + 2);
+ #if WCHAR_PATH_SEPARATOR != L'/'
+ if (c == L'/')
+ c = WCHAR_PATH_SEPARATOR;
+ #endif
+ *s++ = c;
+ }
+ result.ReleaseBuffer(len);
+ if (len != 0)
+ return S_OK;
+ }
+ }
+ /*
+ else if (GetRawProps->GetRawProp(index, kpidName, &p, &size, &propType) == S_OK &&
+ p && propType == NPropDataType::kUtf16z)
+ {
+ UInt32 totalSize = size;
+ bool isOK = false;
+ {
+ UInt32 index2 = index;
+ for (;;)
+ {
+ UInt32 parent = (UInt32)(Int32)-1;
+ UInt32 parentType = 0;
+ if (GetRawProps->GetParent(index2, &parent, &parentType) != S_OK)
+ break;
+ if (parent == (UInt32)(Int32)-1)
+ {
+ isOK = true;
+ break;
+ }
+ index2 = parent;
+ UInt32 size2;
+ const void *p2;
+ if (GetRawProps->GetRawProp(index2, kpidName, &p2, &size2, &propType) != S_OK)
+ break;
+ totalSize += size2;
+ }
+ }
+
+ if (isOK)
+ {
+ wchar_t *sz = result.GetBuffer(totalSize / 2);
+ UInt32 pos = totalSize - size;
+ memcpy((Byte *)sz + pos, p, size - 2);
+ UInt32 index2 = index;
+ for (;;)
+ {
+ UInt32 parent = (UInt32)(Int32)-1;
+ UInt32 parentType = 0;
+ if (GetRawProps->GetParent(index2, &parent, &parentType) != S_OK)
+ break;
+ if (parent == (UInt32)(Int32)-1)
+ break;
+ index2 = parent;
+ UInt32 size2;
+ const void *p2;
+ if (GetRawProps->GetRawProp(index2, kpidName, &p2, &size2, &propType) != S_OK)
+ break;
+ pos -= size2;
+ memcpy((Byte *)sz + pos, p2, size2);
+ sz[(pos + size2 - 2) / 2] = (parentType == 0) ? WCHAR_PATH_SEPARATOR : L':';
+ }
+ result.ReleaseBuffer((totalSize - 2) / 2);
+ #ifdef _WIN32
+ // result.Replace(L'/', WCHAR_PATH_SEPARATOR);
+ #endif
+ return S_OK;
+ }
+ }
+ */
+ }
+ #endif
+
{
NCOM::CPropVariant prop;
RINOK(Archive->GetProperty(index, kpidPath, &prop));
@@ -47,6 +673,7 @@ HRESULT CArc::GetItemPath(UInt32 index, UString &result) const
else
return E_FAIL;
}
+
if (result.IsEmpty())
{
result = DefaultName;
@@ -63,6 +690,61 @@ HRESULT CArc::GetItemPath(UInt32 index, UString &result) const
return S_OK;
}
+HRESULT CArc::GetItemPath2(UInt32 index, UString &result) const
+{
+ RINOK(GetItemPath(index, result));
+ if (Ask_Deleted)
+ {
+ bool isDeleted = false;
+ RINOK(Archive_IsItem_Deleted(Archive, index, isDeleted));
+ if (isDeleted)
+ result.Insert(0, L"[DELETED]" WSTRING_PATH_SEPARATOR);
+ }
+ return S_OK;
+}
+
+#ifndef _SFX
+
+static HRESULT Archive_GetItem_Size(IInArchive *archive, UInt32 index, UInt64 &size, bool &defined)
+{
+ NCOM::CPropVariant prop;
+ defined = false;
+ size = 0;
+ RINOK(archive->GetProperty(index, kpidSize, &prop));
+ switch (prop.vt)
+ {
+ case VT_UI1: size = prop.bVal; break;
+ case VT_UI2: size = prop.uiVal; break;
+ case VT_UI4: size = prop.ulVal; break;
+ case VT_UI8: size = (UInt64)prop.uhVal.QuadPart; break;
+ case VT_EMPTY: return S_OK;
+ default: return E_FAIL;
+ }
+ defined = true;
+ return S_OK;
+}
+
+#endif
+
+HRESULT CArc::GetItemSize(UInt32 index, UInt64 &size, bool &defined) const
+{
+ NCOM::CPropVariant prop;
+ defined = false;
+ size = 0;
+ RINOK(Archive->GetProperty(index, kpidSize, &prop));
+ switch (prop.vt)
+ {
+ case VT_UI1: size = prop.bVal; break;
+ case VT_UI2: size = prop.uiVal; break;
+ case VT_UI4: size = prop.ulVal; break;
+ case VT_UI8: size = (UInt64)prop.uhVal.QuadPart; break;
+ case VT_EMPTY: return S_OK;
+ default: return E_FAIL;
+ }
+ defined = true;
+ return S_OK;
+}
+
HRESULT CArc::GetItemMTime(UInt32 index, FILETIME &ft, bool &defined) const
{
NCOM::CPropVariant prop;
@@ -85,6 +767,7 @@ HRESULT CArc::GetItemMTime(UInt32 index, FILETIME &ft, bool &defined) const
}
#ifndef _SFX
+
static inline bool TestSignature(const Byte *p1, const Byte *p2, size_t size)
{
for (size_t i = 0; i < size; i++)
@@ -92,327 +775,2107 @@ static inline bool TestSignature(const Byte *p1, const Byte *p2, size_t size)
return false;
return true;
}
+
+static void MakeCheckOrder(CCodecs *codecs,
+ CIntVector &orderIndices, unsigned numTypes, CIntVector &orderIndices2,
+ const Byte *data, size_t dataSize)
+{
+ for (unsigned i = 0; i < numTypes; i++)
+ {
+ int index = orderIndices[i];
+ if (index < 0)
+ continue;
+ const CArcInfoEx &ai = codecs->Formats[index];
+ if (ai.SignatureOffset != 0)
+ {
+ orderIndices2.Add(index);
+ orderIndices[i] = -1;
+ continue;
+ }
+
+ const CObjectVector<CByteBuffer> &sigs = ai.Signatures;
+ FOR_VECTOR (k, sigs)
+ {
+ const CByteBuffer &sig = sigs[k];
+ if (sig.Size() == 0 && dataSize == 0 ||
+ sig.Size() != 0 && sig.Size() <= dataSize &&
+ TestSignature(data, sig, sig.Size()))
+ {
+ orderIndices2.Add(index);
+ orderIndices[i] = -1;
+ break;
+ }
+ }
+ }
+}
+
#endif
#ifdef UNDER_CE
-static const int kNumHashBytes = 1;
-#define HASH_VAL(buf, pos) ((buf)[pos])
+ static const unsigned kNumHashBytes = 1;
+ #define HASH_VAL(buf, pos) ((buf)[pos])
#else
-static const int kNumHashBytes = 2;
-#define HASH_VAL(buf, pos) ((buf)[pos] | ((UInt32)(buf)[pos + 1] << 8))
+ static const unsigned kNumHashBytes = 2;
+ #define HASH_VAL(buf, pos) ((buf)[pos] | ((UInt32)(buf)[pos + 1] << 8))
#endif
-HRESULT CArc::OpenStream(
- CCodecs *codecs,
- int formatIndex,
- IInStream *stream,
- ISequentialInStream *seqStream,
- IArchiveOpenCallback *callback)
+#ifndef _SFX
+
+static bool IsExeExt(const UString &ext)
{
- Archive.Release();
+ return ext.IsEqualToNoCase(L"exe");
+}
+
+static const char *k_PreArcFormats[] =
+{
+ "pe"
+ , "elf"
+ , "macho"
+ , "mub"
+ , "te"
+};
+
+static bool IsNameFromList(const UString &s, const char *names[], size_t num)
+{
+ for (unsigned i = 0; i < num; i++)
+ if (StringsAreEqualNoCase_Ascii(s, names[i]))
+ return true;
+ return false;
+}
+
+
+static bool IsPreArcFormat(const CArcInfoEx &ai)
+{
+ if (ai.Flags_PreArc())
+ return true;
+ return IsNameFromList(ai.Name, k_PreArcFormats, ARRAY_SIZE(k_PreArcFormats));
+}
+
+static const char *k_Formats_with_simple_signuature[] =
+{
+ "7z"
+ , "xz"
+ , "rar"
+ , "bzip2"
+ , "gzip"
+ , "cab"
+ , "wim"
+ , "rpm"
+ , "vhd"
+ , "xar"
+};
+
+static bool IsNewStyleSignature(const CArcInfoEx &ai)
+{
+ // if (ai.Version >= 0x91F)
+ if (ai.NewInterface)
+ return true;
+ return IsNameFromList(ai.Name, k_Formats_with_simple_signuature, ARRAY_SIZE(k_Formats_with_simple_signuature));
+}
+
+class CArchiveOpenCallback_Offset:
+ public IArchiveOpenCallback,
+ #ifndef _NO_CRYPTO
+ public ICryptoGetTextPassword,
+ #endif
+ public CMyUnknownImp
+{
+public:
+ CMyComPtr<IArchiveOpenCallback> Callback;
+ UInt64 Files;
+ UInt64 Offset;
+
+ #ifndef _NO_CRYPTO
+ CMyComPtr<ICryptoGetTextPassword> GetTextPassword;
+ MY_UNKNOWN_IMP2(
+ IArchiveOpenCallback,
+ ICryptoGetTextPassword)
+ #else
+ MY_UNKNOWN_IMP1(IArchiveOpenCallback)
+ #endif
+ STDMETHOD(SetTotal)(const UInt64 *files, const UInt64 *bytes);
+ STDMETHOD(SetCompleted)(const UInt64 *files, const UInt64 *bytes);
+ #ifndef _NO_CRYPTO
+ STDMETHOD(CryptoGetTextPassword)(BSTR *password);
+ #endif
+};
+
+#ifndef _NO_CRYPTO
+STDMETHODIMP CArchiveOpenCallback_Offset::CryptoGetTextPassword(BSTR *password)
+{
+ COM_TRY_BEGIN
+ if (GetTextPassword)
+ return GetTextPassword->CryptoGetTextPassword(password);
+ return E_NOTIMPL;
+ COM_TRY_END
+}
+#endif
+
+STDMETHODIMP CArchiveOpenCallback_Offset::SetTotal(const UInt64 * /* files */, const UInt64 * /* bytes */)
+{
+ return S_OK;
+}
+
+STDMETHODIMP CArchiveOpenCallback_Offset::SetCompleted(const UInt64 * /* files */, const UInt64 *bytes)
+{
+ if (!Callback)
+ return S_OK;
+ UInt64 value = Offset;
+ if (bytes)
+ value += *bytes;
+ return Callback->SetCompleted(&Files, &value);
+}
+
+#endif
+
+UInt32 GetOpenArcErrorFlags(const NCOM::CPropVariant &prop, bool *isDefinedProp)
+{
+ if (isDefinedProp != NULL)
+ *isDefinedProp = false;
+
+ switch (prop.vt)
+ {
+ case VT_UI8: if (isDefinedProp) *isDefinedProp = true; return (UInt32)prop.uhVal.QuadPart;
+ case VT_UI4: if (isDefinedProp) *isDefinedProp = true; return prop.ulVal;
+ case VT_EMPTY: return 0;
+ default: throw 151199;
+ }
+}
+
+void CArcErrorInfo::ClearErrors()
+{
+ // ErrorFormatIndex = -1; // we don't need to clear ErrorFormatIndex here !!!
+
+ ThereIsTail = false;
+ UnexpecedEnd = false;
+ IgnoreTail = false;
+ // NonZerosTail = false;
+ ErrorFlags_Defined = false;
+ ErrorFlags = 0;
+ WarningFlags = 0;
+ TailSize = 0;
+
ErrorMessage.Empty();
+ WarningMessage.Empty();
+}
+
+HRESULT CArc::ReadBasicProps(IInArchive *archive, UInt64 startPos, HRESULT openRes)
+{
+ // OkPhySize_Defined = false;
+ PhySizeDefined = false;
+ PhySize = 0;
+ Offset = 0;
+ AvailPhySize = FileSize - startPos;
+
+ ErrorInfo.ClearErrors();
+ {
+ NCOM::CPropVariant prop;
+ RINOK(archive->GetArchiveProperty(kpidErrorFlags, &prop));
+ ErrorInfo.ErrorFlags = GetOpenArcErrorFlags(prop, &ErrorInfo.ErrorFlags_Defined);
+ }
+ {
+ NCOM::CPropVariant prop;
+ RINOK(archive->GetArchiveProperty(kpidWarningFlags, &prop));
+ ErrorInfo.WarningFlags = GetOpenArcErrorFlags(prop);
+ }
+
+ {
+ NCOM::CPropVariant prop;
+ RINOK(archive->GetArchiveProperty(kpidError, &prop));
+ if (prop.vt != VT_EMPTY)
+ ErrorInfo.ErrorMessage = (prop.vt == VT_BSTR) ? prop.bstrVal : L"Unknown error";
+ }
+
+ {
+ NCOM::CPropVariant prop;
+ RINOK(archive->GetArchiveProperty(kpidWarning, &prop));
+ if (prop.vt != VT_EMPTY)
+ ErrorInfo.WarningMessage = (prop.vt == VT_BSTR) ? prop.bstrVal : L"Unknown warning";
+ }
+
+ if (openRes == S_OK || ErrorInfo.IsArc_After_NonOpen())
+ {
+ RINOK(Archive_GetArcProp_UInt(archive, kpidPhySize, PhySize, PhySizeDefined));
+ /*
+ RINOK(Archive_GetArcProp_UInt(archive, kpidOkPhySize, OkPhySize, OkPhySize_Defined));
+ if (!OkPhySize_Defined)
+ {
+ OkPhySize_Defined = PhySizeDefined;
+ OkPhySize = PhySize;
+ }
+ */
+
+ bool offsetDefined;
+ RINOK(Archive_GetArcProp_Int(archive, kpidOffset, Offset, offsetDefined));
+
+ Int64 globalOffset = startPos + Offset;
+ AvailPhySize = FileSize - globalOffset;
+ if (PhySizeDefined)
+ {
+ UInt64 endPos = globalOffset + PhySize;
+ if (endPos < FileSize)
+ {
+ AvailPhySize = PhySize;
+ ErrorInfo.ThereIsTail = true;
+ ErrorInfo.TailSize = FileSize - endPos;
+ }
+ else if (endPos > FileSize)
+ ErrorInfo.UnexpecedEnd = true;
+ }
+ }
+
+ return S_OK;
+}
+
+/*
+static PrintNumber(const char *s, int n)
+{
+ char temp[100];
+ sprintf(temp, "%s %d", s, n);
+ OutputDebugStringA(temp);
+}
+*/
+
+HRESULT CArc::PrepareToOpen(const COpenOptions &op, unsigned formatIndex, CMyComPtr<IInArchive> &archive)
+{
+ // OutputDebugStringW(L"a1");
+ // PrintNumber("formatIndex", formatIndex);
+
+ RINOK(op.codecs->CreateInArchive(formatIndex, archive));
+ // OutputDebugStringW(L"a2");
+ if (!archive)
+ return S_OK;
+
+ #ifdef EXTERNAL_CODECS
+ {
+ CMyComPtr<ISetCompressCodecsInfo> setCompressCodecsInfo;
+ archive.QueryInterface(IID_ISetCompressCodecsInfo, (void **)&setCompressCodecsInfo);
+ if (setCompressCodecsInfo)
+ {
+ RINOK(setCompressCodecsInfo->SetCompressCodecsInfo(op.codecs));
+ }
+ }
+ #endif
+
+ // OutputDebugStringW(ai.Name);
+ // OutputDebugStringW(L"a3");
+
+ #ifndef _SFX
+ const CArcInfoEx &ai = op.codecs->Formats[formatIndex];
+ if (ai.Flags_PreArc())
+ {
+ /* we notify parsers that extract executables, that they don't need
+ to open archive, if there is tail after executable (for SFX cases) */
+ CMyComPtr<IArchiveAllowTail> allowTail;
+ archive.QueryInterface(IID_IArchiveAllowTail, (void **)&allowTail);
+ if (allowTail)
+ allowTail->AllowTail(BoolToInt(true));
+ }
+ if (op.props)
+ {
+ /*
+ FOR_VECTOR (y, op.props)
+ {
+ const COptionalOpenProperties &optProps = (*op.props)[y];
+ if (optProps.FormatName.IsEmpty() || optProps.FormatName.CompareNoCase(ai.Name) == 0)
+ {
+ RINOK(SetProperties(archive, optProps.Props));
+ break;
+ }
+ }
+ */
+ RINOK(SetProperties(archive, *op.props));
+ }
+ #endif
+ return S_OK;
+}
+
+#ifndef _SFX
+
+static HRESULT ReadParseItemProps(IInArchive *archive, const CArcInfoEx &ai, NArchive::NParser::CParseItem &pi)
+{
+ pi.Extension = ai.GetMainExt();
+ pi.FileTime_Defined = false;
+ pi.ArcType = ai.Name;
+
+ RINOK(Archive_GetArcBoolProp(archive, kpidIsNotArcType, pi.IsNotArcType));
+
+ // RINOK(Archive_GetArcBoolProp(archive, kpidIsSelfExe, pi.IsSelfExe));
+ pi.IsSelfExe = ai.Flags_PreArc();
+
+ {
+ NCOM::CPropVariant prop;
+ RINOK(archive->GetArchiveProperty(kpidMTime, &prop));
+ if (prop.vt == VT_FILETIME)
+ {
+ pi.FileTime_Defined = true;
+ pi.FileTime = prop.filetime;
+ }
+ }
+
+ if (!pi.FileTime_Defined)
+ {
+ NCOM::CPropVariant prop;
+ RINOK(archive->GetArchiveProperty(kpidCTime, &prop));
+ if (prop.vt == VT_FILETIME)
+ {
+ pi.FileTime_Defined = true;
+ pi.FileTime = prop.filetime;
+ }
+ }
+
+ {
+ NCOM::CPropVariant prop;
+ RINOK(archive->GetArchiveProperty(kpidName, &prop));
+ if (prop.vt == VT_BSTR)
+ {
+ pi.Name = prop.bstrVal;
+ pi.Extension.Empty();
+ }
+ else
+ {
+ RINOK(archive->GetArchiveProperty(kpidExtension, &prop));
+ if (prop.vt == VT_BSTR)
+ pi.Extension = prop.bstrVal;
+ }
+ }
+
+ {
+ NCOM::CPropVariant prop;
+ RINOK(archive->GetArchiveProperty(kpidShortComment, &prop));
+ if (prop.vt == VT_BSTR)
+ pi.Comment = prop.bstrVal;
+ }
+
+
+ UInt32 numItems;
+ RINOK(archive->GetNumberOfItems(&numItems));
+
+ // pi.NumSubFiles = numItems;
+ // RINOK(Archive_GetArcProp_UInt(archive, kpidUnpackSize, pi.UnpackSize, pi.UnpackSize_Defined));
+ // if (!pi.UnpackSize_Defined)
+ {
+ pi.NumSubFiles = 0;
+ pi.NumSubDirs = 0;
+ pi.UnpackSize = 0;
+ for (UInt32 i = 0; i < numItems; i++)
+ {
+ UInt64 size = 0;
+ bool defined = false;
+ Archive_GetItem_Size(archive, i, size, defined);
+ if (defined)
+ {
+ pi.UnpackSize_Defined = true;
+ pi.UnpackSize += size;
+ }
+
+ bool isDir = false;
+ Archive_IsItem_Folder(archive, i, isDir);
+ if (isDir)
+ pi.NumSubDirs++;
+ else
+ pi.NumSubFiles++;
+ }
+ if (pi.NumSubDirs != 0)
+ pi.NumSubDirs_Defined = true;
+ pi.NumSubFiles_Defined = true;
+ }
+
+ return S_OK;
+}
+
+#endif
+
+HRESULT CArc::CheckZerosTail(const COpenOptions &op, UInt64 offset)
+{
+ if (!op.stream)
+ return S_OK;
+ RINOK(op.stream->Seek(offset, STREAM_SEEK_SET, NULL));
+ const UInt32 kBufSize = 1 << 11;
+ Byte buf[kBufSize];
+
+ for (;;)
+ {
+ UInt32 processed = 0;
+ RINOK(op.stream->Read(buf, kBufSize, &processed));
+ if (processed == 0)
+ {
+ // ErrorInfo.NonZerosTail = false;
+ ErrorInfo.IgnoreTail = true;
+ return S_OK;
+ }
+ for (size_t i = 0; i < processed; i++)
+ {
+ if (buf[i] != 0)
+ {
+ // ErrorInfo.IgnoreTail = false;
+ // ErrorInfo.NonZerosTail = true;
+ return S_OK;
+ }
+ }
+ }
+}
+
+#ifndef _SFX
+
+class CExtractCallback_To_OpenCallback:
+ public IArchiveExtractCallback,
+ public ICompressProgressInfo,
+ public CMyUnknownImp
+{
+public:
+ CMyComPtr<IArchiveOpenCallback> Callback;
+ UInt64 Files;
+ UInt64 Offset;
+
+ MY_UNKNOWN_IMP2(IArchiveExtractCallback, ICompressProgressInfo)
+ INTERFACE_IArchiveExtractCallback(;)
+ STDMETHOD(SetRatioInfo)(const UInt64 *inSize, const UInt64 *outSize);
+ void Init(IArchiveOpenCallback *callback)
+ {
+ Callback = callback;
+ Files = 0;
+ Offset = 0;
+ }
+};
+
+STDMETHODIMP CExtractCallback_To_OpenCallback::SetTotal(UInt64 /* size */)
+{
+ return S_OK;
+}
+
+STDMETHODIMP CExtractCallback_To_OpenCallback::SetCompleted(const UInt64 * /* completeValue */)
+{
+ return S_OK;
+}
+
+STDMETHODIMP CExtractCallback_To_OpenCallback::SetRatioInfo(const UInt64 *inSize, const UInt64 * /* outSize */)
+{
+ if (Callback)
+ {
+ UInt64 value = Offset;
+ if (inSize)
+ value += *inSize;
+ return Callback->SetCompleted(&Files, &value);
+ }
+ return S_OK;
+}
+
+STDMETHODIMP CExtractCallback_To_OpenCallback::GetStream(UInt32 /* index */, ISequentialOutStream **outStream, Int32 /* askExtractMode */)
+{
+ *outStream = 0;
+ return S_OK;
+}
+
+STDMETHODIMP CExtractCallback_To_OpenCallback::PrepareOperation(Int32 /* askExtractMode */)
+{
+ return S_OK;
+}
+
+STDMETHODIMP CExtractCallback_To_OpenCallback::SetOperationResult(Int32 /* operationResult */)
+{
+ return S_OK;
+}
+
+static HRESULT OpenArchiveSpec(IInArchive *archive, bool needPhySize,
+ IInStream *stream, const UInt64 *maxCheckStartPosition,
+ IArchiveOpenCallback *openCallback,
+ IArchiveExtractCallback *extractCallback)
+{
+ /*
+ if (needPhySize)
+ {
+ CMyComPtr<IArchiveOpen2> open2;
+ archive->QueryInterface(IID_IArchiveOpen2, (void **)&open2);
+ if (open2)
+ return open2->ArcOpen2(stream, kOpenFlags_RealPhySize, openCallback);
+ }
+ */
+ RINOK(archive->Open(stream, maxCheckStartPosition, openCallback));
+ if (needPhySize)
+ {
+ bool phySize_Defined = false;
+ UInt64 phySize = 0;
+ RINOK(Archive_GetArcProp_UInt(archive, kpidPhySize, phySize, phySize_Defined));
+ if (phySize_Defined)
+ return S_OK;
+
+ bool phySizeCantBeDetected = false;;
+ RINOK(Archive_GetArcBoolProp(archive, kpidPhySizeCantBeDetected, phySizeCantBeDetected));
+
+ if (!phySizeCantBeDetected)
+ {
+ RINOK(archive->Extract(0, (UInt32)(Int32)-1, BoolToInt(true), extractCallback));
+ }
+ }
+ return S_OK;
+}
+
+static int FindFormatForArchiveType(CCodecs *codecs, CIntVector orderIndices, const char *name)
+{
+ FOR_VECTOR (i, orderIndices)
+ if (StringsAreEqualNoCase_Ascii(codecs->Formats[orderIndices[i]].Name, name))
+ return i;
+ return -1;
+}
+
+#endif
+
+HRESULT CArc::OpenStream2(const COpenOptions &op)
+{
+ // fprintf(stdout, "\nOpen: %S", Path); fflush(stdout);
+
+ Archive.Release();
+ GetRawProps.Release();
+ GetRootProps.Release();
+
+ ErrorInfo.ClearErrors();
+ ErrorInfo.ErrorFormatIndex = -1;
+
+ IsParseArc = false;
+ ArcStreamOffset = 0;
+
+ // OutputDebugStringW(L"1");
+ // OutputDebugStringW(Path);
+
const UString fileName = ExtractFileNameFromPath(Path);
UString extension;
{
int dotPos = fileName.ReverseFind(L'.');
if (dotPos >= 0)
- extension = fileName.Mid(dotPos + 1);
+ extension = fileName.Ptr(dotPos + 1);
}
+
CIntVector orderIndices;
+
+ bool searchMarkerInHandler = false;
+ #ifdef _SFX
+ searchMarkerInHandler = true;
+ #endif
+
+ CBoolArr isMainFormatArr(op.codecs->Formats.Size());
+ {
+ FOR_VECTOR(i, op.codecs->Formats)
+ isMainFormatArr[i] = false;
+ }
+
+ UInt64 maxStartOffset =
+ op.openType.MaxStartOffset_Defined ?
+ op.openType.MaxStartOffset :
+ kMaxCheckStartPosition;
+
+ #ifndef _SFX
+ bool isUnknownExt = false;
+ #endif
+
+ bool isForced = false;
+ unsigned numMainTypes = 0;
+ int formatIndex = op.openType.FormatIndex;
+
if (formatIndex >= 0)
+ {
+ isForced = true;
orderIndices.Add(formatIndex);
+ numMainTypes = 1;
+ isMainFormatArr[formatIndex] = true;
+
+ searchMarkerInHandler = true;
+ }
else
{
+ unsigned numFinded = 0;
+ #ifndef _SFX
+ bool isPrearcExt = false;
+ #endif
- int i;
- int numFinded = 0;
- for (i = 0; i < codecs->Formats.Size(); i++)
- if (codecs->Formats[i].FindExtension(extension) >= 0)
- orderIndices.Insert(numFinded++, i);
- else
- orderIndices.Add(i);
-
- if (!stream)
+ {
+ FOR_VECTOR (i, op.codecs->Formats)
+ {
+ const CArcInfoEx &ai = op.codecs->Formats[i];
+
+ if (IgnoreSplit || !op.openType.CanReturnArc)
+ if (ai.IsSplit())
+ continue;
+ if (op.excludedFormats->FindInSorted(i) >= 0)
+ continue;
+
+ #ifndef _SFX
+ if (IsPreArcFormat(ai))
+ isPrearcExt = true;
+ #endif
+
+ if (ai.FindExtension(extension) >= 0)
+ {
+ // PrintNumber("orderIndices.Insert", i);
+ orderIndices.Insert(numFinded++, i);
+ isMainFormatArr[i] = true;
+ }
+ else
+ orderIndices.Add(i);
+ }
+ }
+
+ if (!op.stream)
+ {
+ if (numFinded != 1)
+ return E_NOTIMPL;
+ orderIndices.DeleteFrom(1);
+ }
+ // PrintNumber("numFinded", numFinded );
+
+ /*
+ if (op.openOnlySpecifiedByExtension)
+ {
+ if (numFinded != 0 && !IsExeExt(extension))
+ orderIndices.DeleteFrom(numFinded);
+ }
+ */
+
+ #ifndef _SFX
+
+ if (op.stream && orderIndices.Size() >= 2)
+ {
+ RINOK(op.stream->Seek(0, STREAM_SEEK_SET, NULL));
+ CByteBuffer byteBuffer;
+ CIntVector orderIndices2;
+ if (numFinded == 0 || IsExeExt(extension))
+ {
+ // signature search was here
+ }
+ else if (extension == L"000" || extension == L"001")
+ {
+ int i = FindFormatForArchiveType(op.codecs, orderIndices, "rar");
+ if (i >= 0)
+ {
+ const size_t kBufSize = (1 << 10);
+ byteBuffer.Alloc(kBufSize);
+ size_t processedSize = kBufSize;
+ RINOK(ReadStream(op.stream, byteBuffer, &processedSize));
+ if (processedSize >= 16)
+ {
+ const Byte *buf = byteBuffer;
+ const Byte kRarHeader[] = { 0x52 , 0x61, 0x72, 0x21, 0x1a, 0x07, 0x00 };
+ if (TestSignature(buf, kRarHeader, 7) && buf[9] == 0x73 && (buf[10] & 1) != 0)
+ {
+ orderIndices2.Add(orderIndices[i]);
+ orderIndices[i] = -1;
+ if (i >= (int)numFinded)
+ numFinded++;
+ }
+ }
+ }
+ }
+ else
+ {
+ const size_t kBufSize = (1 << 10);
+ byteBuffer.Alloc(kBufSize);
+ size_t processedSize = kBufSize;
+ RINOK(ReadStream(op.stream, byteBuffer, &processedSize));
+ if (processedSize == 0)
+ return S_FALSE;
+
+ /*
+ check type order:
+ 1) matched extension, no signuature
+ 2) matched extension, matched signuature
+ // 3) no signuature
+ // 4) matched signuature
+ */
+
+ MakeCheckOrder(op.codecs, orderIndices, numFinded, orderIndices2, NULL, 0);
+ MakeCheckOrder(op.codecs, orderIndices, numFinded, orderIndices2, byteBuffer, processedSize);
+ // MakeCheckOrder(op.codecs, orderIndices, orderIndices.Size(), orderIndices2, NULL, 0);
+ // MakeCheckOrder(op.codecs, orderIndices, orderIndices.Size(), orderIndices2, byteBuffer, processedSize);
+ }
+
+ FOR_VECTOR (i, orderIndices)
+ {
+ int val = orderIndices[i];
+ if (val != -1)
+ orderIndices2.Add(val);
+ }
+ orderIndices = orderIndices2;
+ }
+
+ if (orderIndices.Size() >= 2)
+ {
+ int iIso = FindFormatForArchiveType(op.codecs, orderIndices, "iso");
+ int iUdf = FindFormatForArchiveType(op.codecs, orderIndices, "udf");
+ if (iUdf > iIso && iIso >= 0)
+ {
+ int isoIndex = orderIndices[iIso];
+ int udfIndex = orderIndices[iUdf];
+ orderIndices[iUdf] = isoIndex;
+ orderIndices[iIso] = udfIndex;
+ }
+ }
+
+ numMainTypes = numFinded;
+ isUnknownExt = (numMainTypes == 0) || isPrearcExt;
+
+ #else // _SFX
+
+ numMainTypes = orderIndices.Size();
+
+ #endif
+ }
+
+ UInt64 fileSize = 0;
+ if (op.stream)
{
- if (numFinded != 1)
- return E_NOTIMPL;
- orderIndices.DeleteFrom(1);
+ RINOK(op.stream->Seek(0, STREAM_SEEK_END, &fileSize));
+ RINOK(op.stream->Seek(0, STREAM_SEEK_SET, NULL));
}
+ FileSize = fileSize;
+
#ifndef _SFX
- if (orderIndices.Size() >= 2 && (numFinded == 0 || extension.CompareNoCase(L"exe") == 0))
+
+ CBoolArr skipFrontalFormat(op.codecs->Formats.Size());
{
- CIntVector orderIndices2;
- CByteBuffer byteBuffer;
- const size_t kBufferSize = (1 << 21);
- byteBuffer.SetCapacity(kBufferSize);
- RINOK(stream->Seek(0, STREAM_SEEK_SET, NULL));
- size_t processedSize = kBufferSize;
- RINOK(ReadStream(stream, byteBuffer, &processedSize));
- if (processedSize == 0)
- return S_FALSE;
+ FOR_VECTOR(i, op.codecs->Formats)
+ skipFrontalFormat[i] = false;
+ }
- const Byte *buf = byteBuffer;
- CByteBuffer hashBuffer;
- const UInt32 kNumVals = 1 << (kNumHashBytes * 8);
- hashBuffer.SetCapacity(kNumVals);
- Byte *hash = hashBuffer;
- memset(hash, 0xFF, kNumVals);
- Byte prevs[256];
- if (orderIndices.Size() >= 256)
- return S_FALSE;
- int i;
- for (i = 0; i < orderIndices.Size(); i++)
+ #endif
+
+ const COpenType &mode = op.openType;
+
+
+
+
+
+ if (mode.CanReturnArc)
+ {
+ // ---------- OPEN main type by extenssion ----------
+
+ unsigned numCheckTypes = orderIndices.Size();
+ if (formatIndex >= 0)
+ numCheckTypes = numMainTypes;
+
+ for (unsigned i = 0; i < numCheckTypes; i++)
{
- const CArcInfoEx &ai = codecs->Formats[orderIndices[i]];
- const CByteBuffer &sig = ai.StartSignature;
- if (sig.GetCapacity() < kNumHashBytes)
+ FormatIndex = orderIndices[i];
+ const CArcInfoEx &ai = op.codecs->Formats[FormatIndex];
+ // OutputDebugStringW(ai.Name);
+
+ bool exactOnly = false;
+ if (i >= numMainTypes)
+ {
+ if (!ai.Flags_BackwardOpen()
+ // && !ai.Flags_PureStartOpen()
+ )
+ continue;
+ exactOnly = true;
+ }
+
+ // Some handlers do not set total bytes. So we set it here
+ RINOK(op.callback->SetTotal(NULL, &fileSize));
+ if (op.stream)
+ {
+ RINOK(op.stream->Seek(0, STREAM_SEEK_SET, NULL));
+ }
+
+ CMyComPtr<IInArchive> archive;
+
+ RINOK(PrepareToOpen(op, FormatIndex, archive));
+ if (!archive)
continue;
- UInt32 v = HASH_VAL(sig, 0);
- prevs[i] = hash[v];
- hash[v] = (Byte)i;
- }
- processedSize -= (kNumHashBytes - 1);
- for (UInt32 pos = 0; pos < processedSize; pos++)
- {
- for (; pos < processedSize && hash[HASH_VAL(buf, pos)] == 0xFF; pos++) {}
- if (pos == processedSize)
- break;
- UInt32 v = HASH_VAL(buf, pos);
- Byte *ptr = &hash[v];
- int i = *ptr;
- do
+ HRESULT result;
+ if (op.stream)
{
- int index = orderIndices[i];
- const CArcInfoEx &ai = codecs->Formats[index];
- const CByteBuffer &sig = ai.StartSignature;
- if (sig.GetCapacity() != 0 && pos + sig.GetCapacity() <= processedSize + (kNumHashBytes - 1) &&
- TestSignature(buf + pos, sig, sig.GetCapacity()))
+ UInt64 searchLimit = (!exactOnly && searchMarkerInHandler) ? maxStartOffset: 0;
+ result = archive->Open(op.stream, &searchLimit, op.callback);
+ }
+ else
+ {
+ CMyComPtr<IArchiveOpenSeq> openSeq;
+ archive.QueryInterface(IID_IArchiveOpenSeq, (void **)&openSeq);
+ if (!openSeq)
+ return E_NOTIMPL;
+ result = openSeq->OpenSeq(op.seqStream);
+ }
+
+ RINOK(ReadBasicProps(archive, 0, result));
+
+ if (result == S_FALSE)
+ {
+ bool isArc = ErrorInfo.IsArc_After_NonOpen();
+
+ #ifndef _SFX
+ // if it's archive, we allow another open attempt for parser
+ if (!mode.CanReturnParser || !isArc)
+ skipFrontalFormat[FormatIndex] = true;
+ #endif
+
+ if (exactOnly)
+ continue;
+
+ if (i == 0 && numMainTypes == 1)
{
- orderIndices2.Add(index);
- orderIndices[i] = 0xFF;
- *ptr = prevs[i];
+ // we set NonOpenErrorInfo, only if there is only one main format (defined by extension).
+ ErrorInfo.ErrorFormatIndex = FormatIndex;
+ NonOpen_ErrorInfo = ErrorInfo;
+
+ if (!mode.CanReturnParser && isArc)
+ {
+ // if (formatIndex < 0 && !searchMarkerInHandler)
+ {
+ // if bad archive was detected, we don't need additional open attempts
+ #ifndef _SFX
+ if (!IsPreArcFormat(ai) /* || !mode.SkipSfxStub */)
+ #endif
+ return S_FALSE;
+ }
+ }
}
- else
- ptr = &prevs[i];
- i = *ptr;
+
+ /*
+ #ifndef _SFX
+ if (IsExeExt(extension) || ai.Flags_PreArc())
+ {
+ // openOnlyFullArc = false;
+ // canReturnTailArc = true;
+ // limitSignatureSearch = true;
+ }
+ #endif
+ */
+
+ continue;
+ }
+
+ RINOK(result);
+
+ #ifndef _SFX
+
+ bool isMainFormat = isMainFormatArr[FormatIndex];
+ const COpenSpecFlags &specFlags = mode.GetSpec(isForced, isMainFormat, isUnknownExt);
+
+ bool thereIsTail = ErrorInfo.ThereIsTail;
+ if (thereIsTail && mode.ZerosTailIsAllowed)
+ {
+ RINOK(CheckZerosTail(op, Offset + PhySize));
+ if (ErrorInfo.IgnoreTail)
+ thereIsTail = false;
+ }
+
+ if (Offset > 0)
+ {
+ if (exactOnly
+ || !searchMarkerInHandler
+ || !specFlags.CanReturn_NonStart()
+ || (mode.MaxStartOffset_Defined && (UInt64)Offset > mode.MaxStartOffset))
+ continue;
}
- while (i != 0xFF);
+ if (thereIsTail)
+ {
+ if (Offset > 0)
+ {
+ if (!specFlags.CanReturnMid)
+ continue;
+ }
+ else if (!specFlags.CanReturnFrontal)
+ continue;
+ }
+
+ if (Offset > 0 || thereIsTail)
+ {
+ if (formatIndex < 0)
+ {
+ if (IsPreArcFormat(ai))
+ {
+ // openOnlyFullArc = false;
+ // canReturnTailArc = true;
+ /*
+ if (mode.SkipSfxStub)
+ limitSignatureSearch = true;
+ */
+ // if (mode.SkipSfxStub)
+ {
+ // skipFrontalFormat[FormatIndex] = true;
+ continue;
+ }
+ }
+ }
+ }
+
+ #endif
+
+ Archive = archive;
+ return S_OK;
}
-
- for (i = 0; i < orderIndices.Size(); i++)
+ }
+
+
+
+ #ifndef _SFX
+
+ if (!op.stream)
+ return S_FALSE;
+
+ if (formatIndex >= 0 && !mode.CanReturnParser)
+ {
+ if (mode.MaxStartOffset_Defined)
{
- int val = orderIndices[i];
- if (val != 0xFF)
- orderIndices2.Add(val);
+ if (mode.MaxStartOffset == 0)
+ return S_FALSE;
+ }
+ else
+ {
+ const CArcInfoEx &ai = op.codecs->Formats[formatIndex];
+ if (ai.FindExtension(extension) >= 0)
+ {
+ const CArcInfoEx &ai = op.codecs->Formats[formatIndex];
+ if (ai.Flags_FindSignature() && searchMarkerInHandler)
+ return S_FALSE;
+ }
}
- orderIndices = orderIndices2;
}
- else if (extension == L"000" || extension == L"001")
+
+ NArchive::NParser::CHandler *handlerSpec = new NArchive::NParser::CHandler;
+ CMyComPtr<IInArchive> handler = handlerSpec;
+
+ CExtractCallback_To_OpenCallback *extractCallback_To_OpenCallback_Spec = new CExtractCallback_To_OpenCallback;
+ CMyComPtr<IArchiveExtractCallback> extractCallback_To_OpenCallback = extractCallback_To_OpenCallback_Spec;
+ extractCallback_To_OpenCallback_Spec->Init(op.callback);
+
{
+ // ---------- Check all possible START archives ----------
+ // this code is better for full file archives than Parser's code.
+
CByteBuffer byteBuffer;
- const size_t kBufferSize = (1 << 10);
- byteBuffer.SetCapacity(kBufferSize);
- Byte *buffer = byteBuffer;
- RINOK(stream->Seek(0, STREAM_SEEK_SET, NULL));
- size_t processedSize = kBufferSize;
- RINOK(ReadStream(stream, buffer, &processedSize));
- if (processedSize >= 16)
- {
- Byte kRarHeader[] = {0x52 , 0x61, 0x72, 0x21, 0x1a, 0x07, 0x00};
- if (TestSignature(buffer, kRarHeader, 7) && buffer[9] == 0x73 && (buffer[10] & 1) != 0)
- {
- for (int i = 0; i < orderIndices.Size(); i++)
- {
- int index = orderIndices[i];
- const CArcInfoEx &ai = codecs->Formats[index];
- if (ai.Name.CompareNoCase(L"rar") != 0)
- continue;
- orderIndices.Delete(i--);
- orderIndices.Insert(0, index);
- break;
- }
+ bool endOfFile = false;
+ size_t processedSize;
+ {
+ size_t bufSize = 1 << 20; // it must be larger than max signature offset or IsArcFunc offset ((1 << 19) + x for UDF)
+ if (bufSize > fileSize)
+ {
+ bufSize = (size_t)fileSize;
+ endOfFile = true;
}
+ byteBuffer.Alloc(bufSize);
+ RINOK(op.stream->Seek(0, STREAM_SEEK_SET, NULL));
+ processedSize = bufSize;
+ RINOK(ReadStream(op.stream, byteBuffer, &processedSize));
+ if (processedSize == 0)
+ return S_FALSE;
+ if (processedSize < bufSize)
+ endOfFile = true;
}
- }
- if (orderIndices.Size() >= 2)
- {
- int isoIndex = codecs->FindFormatForArchiveType(L"iso");
- int udfIndex = codecs->FindFormatForArchiveType(L"udf");
- int iIso = -1;
- int iUdf = -1;
- for (int i = 0; i < orderIndices.Size(); i++)
+ CUIntVector sortedFormats;
+
+ unsigned i;
+
+ int splitIndex = -1;
+
+ for (i = 0; i < orderIndices.Size(); i++)
{
- if (orderIndices[i] == isoIndex) iIso = i;
- if (orderIndices[i] == udfIndex) iUdf = i;
+ unsigned form = orderIndices[i];
+ if (skipFrontalFormat[form])
+ continue;
+ const CArcInfoEx &ai = op.codecs->Formats[form];
+ if (ai.IsSplit())
+ {
+ splitIndex = form;
+ continue;
+ }
+
+ if (ai.IsArcFunc)
+ {
+ UInt32 isArcRes = ai.IsArcFunc(byteBuffer, processedSize);
+ if (isArcRes == k_IsArc_Res_NO)
+ continue;
+ if (isArcRes == k_IsArc_Res_NEED_MORE && endOfFile)
+ continue;
+ // if (isArcRes == k_IsArc_Res_YES_LOW_PROB) continue;
+ sortedFormats.Insert(0, form);
+ continue;
+ }
+
+ bool isNewStyleSignature = IsNewStyleSignature(ai);
+ bool needCheck = !isNewStyleSignature
+ || ai.Signatures.IsEmpty()
+ || ai.Flags_PureStartOpen()
+ || ai.Flags_StartOpen()
+ || ai.Flags_BackwardOpen();
+
+ if (isNewStyleSignature && !ai.Signatures.IsEmpty())
+ {
+ unsigned k;
+ for (k = 0; k < ai.Signatures.Size(); k++)
+ {
+ const CByteBuffer &sig = ai.Signatures[k];
+ UInt32 signatureEnd = ai.SignatureOffset + (UInt32)sig.Size();
+ if (processedSize < signatureEnd)
+ {
+ if (!endOfFile)
+ needCheck = true;
+ }
+ else if (memcmp(sig, byteBuffer + ai.SignatureOffset, sig.Size()) == 0)
+ break;
+ }
+ if (k != ai.Signatures.Size())
+ {
+ sortedFormats.Insert(0, form);
+ continue;
+ }
+ }
+ if (needCheck)
+ sortedFormats.Add(form);
}
- if (iUdf > iIso && iIso >= 0)
+
+ if (splitIndex >= 0)
+ sortedFormats.Insert(0, splitIndex);
+
+ for (i = 0; i < sortedFormats.Size(); i++)
{
- orderIndices[iUdf] = isoIndex;
- orderIndices[iIso] = udfIndex;
+ FormatIndex = sortedFormats[i];
+ const CArcInfoEx &ai = op.codecs->Formats[FormatIndex];
+
+ RINOK(op.callback->SetTotal(NULL, &fileSize));
+ RINOK(op.stream->Seek(0, STREAM_SEEK_SET, NULL));
+
+ CMyComPtr<IInArchive> archive;
+ RINOK(PrepareToOpen(op, FormatIndex, archive));
+ if (!archive)
+ continue;
+
+ PRF(printf("\nSorted Open %S", (const wchar_t *)ai.Name));
+ HRESULT result;
+ {
+ UInt64 searchLimit = 0;
+ /*
+ if (mode.CanReturnArc)
+ result = archive->Open(op.stream, &searchLimit, op.callback);
+ else
+ */
+ result = OpenArchiveSpec(archive, !mode.CanReturnArc, op.stream, &searchLimit, op.callback, extractCallback_To_OpenCallback);
+ }
+
+ if (result == S_FALSE)
+ {
+ skipFrontalFormat[FormatIndex] = true;
+ // FIXME: maybe we must use LenIsUnknown.
+ // printf(" OpenForSize Error");
+ continue;
+ }
+ RINOK(result);
+
+ RINOK(ReadBasicProps(archive, 0, result));
+
+ if (Offset > 0)
+ {
+ continue; // good handler doesn't return such Offset > 0
+ // but there are some cases like false prefixed PK00 archive, when
+ // we can support it?
+ }
+
+ NArchive::NParser::CParseItem pi;
+ pi.Offset = Offset;
+ pi.Size = AvailPhySize;
+
+ // bool needScan = false;
+
+ if (!PhySizeDefined)
+ {
+ // it's for Z format
+ pi.LenIsUnknown = true;
+ // needScan = true;
+ // phySize = arcRem;
+ // nextNeedCheckStartOpen = false;
+ }
+
+ /*
+ if (OkPhySize_Defined)
+ pi.OkSize = pi.OkPhySize;
+ else
+ pi.OkSize = pi.Size;
+ */
+
+ pi.NormalizeOffset();
+ // printf(" phySize = %8d", (unsigned)phySize);
+
+
+ if (mode.CanReturnArc)
+ {
+ bool isMainFormat = isMainFormatArr[FormatIndex];
+ const COpenSpecFlags &specFlags = mode.GetSpec(isForced, isMainFormat, isUnknownExt);
+ bool openCur = false;
+
+ if (!ErrorInfo.ThereIsTail)
+ openCur = true;
+ else
+ {
+ if (mode.ZerosTailIsAllowed)
+ {
+ RINOK(CheckZerosTail(op, Offset + PhySize));
+ if (ErrorInfo.IgnoreTail)
+ openCur = true;
+ }
+ if (!openCur)
+ {
+ openCur = specFlags.CanReturnFrontal;
+ if (formatIndex < 0) // format is not forced
+ {
+ if (IsPreArcFormat(ai))
+ {
+ // if (mode.SkipSfxStub)
+ {
+ openCur = false;
+ }
+ }
+ }
+ }
+ }
+
+ if (openCur)
+ {
+ InStream = op.stream;
+ Archive = archive;
+ return S_OK;
+ }
+ }
+
+ skipFrontalFormat[FormatIndex] = true;
+
+
+ // if (!mode.CanReturnArc)
+ /*
+ if (!ErrorInfo.ThereIsTail)
+ continue;
+ */
+ if (pi.Offset == 0 && !pi.LenIsUnknown && pi.Size >= FileSize)
+ continue;
+
+ // printf("\nAdd offset = %d", (int)pi.Offset);
+ RINOK(ReadParseItemProps(archive, ai, pi));
+ handlerSpec->AddItem(pi);
}
}
- #endif
+
+
+
+
+ // ---------- PARSER ----------
+
+ CUIntVector arc2sig; // formatIndex to signatureIndex
+ CUIntVector sig2arc; // signatureIndex to formatIndex;
+ {
+ unsigned sum = 0;
+ FOR_VECTOR (i, op.codecs->Formats)
+ {
+ arc2sig.Add(sum);
+ const CObjectVector<CByteBuffer> &sigs = op.codecs->Formats[i].Signatures;
+ sum += sigs.Size();
+ FOR_VECTOR (k, sigs)
+ sig2arc.Add(i);
+ }
}
- for (int i = 0; i < orderIndices.Size(); i++)
{
- if (stream)
+ CArchiveOpenCallback_Offset *openCallback_Offset_Spec = new CArchiveOpenCallback_Offset;
+ CMyComPtr<IArchiveOpenCallback> openCallback_Offset = openCallback_Offset_Spec;
+
+ const size_t kBeforeSize = 1 << 16;
+ const size_t kAfterSize = 1 << 20;
+ const size_t kBufSize = 1 << 22; // it must be more than kBeforeSize + kAfterSize
+
+ const UInt32 kNumVals = (UInt32)1 << (kNumHashBytes * 8);
+ CByteArr hashBuffer(kNumVals);
+ Byte *hash = hashBuffer;
+ memset(hash, 0xFF, kNumVals);
+ Byte prevs[256];
+ memset(prevs, 0xFF, sizeof(prevs));
+ if (sig2arc.Size() >= 0xFF)
+ return S_FALSE;
+
+ CUIntVector difficultFormats;
+ CBoolArr difficultBools(256);
{
- RINOK(stream->Seek(0, STREAM_SEEK_SET, NULL));
+ for (unsigned i = 0; i < 256; i++)
+ difficultBools[i] = false;
}
- CMyComPtr<IInArchive> archive;
- FormatIndex = orderIndices[i];
- RINOK(codecs->CreateInArchive(FormatIndex, archive));
- if (!archive)
- continue;
+ bool thereAreHandlersForSearch = false;
- #ifdef EXTERNAL_CODECS
+ // UInt32 maxSignatureEnd = 0;
+
+ FOR_VECTOR (i, orderIndices)
{
- CMyComPtr<ISetCompressCodecsInfo> setCompressCodecsInfo;
- archive.QueryInterface(IID_ISetCompressCodecsInfo, (void **)&setCompressCodecsInfo);
- if (setCompressCodecsInfo)
+ int index = orderIndices[i];
+ if (index < 0)
+ continue;
+ const CArcInfoEx &ai = op.codecs->Formats[index];
+ bool isDifficult = false;
+ // if (ai.Version < 0x91F) // we don't use parser with old DLL (before 9.31)
+ if (!ai.NewInterface)
+ isDifficult = true;
+ else
+ {
+ if (ai.Flags_StartOpen())
+ isDifficult = true;
+ FOR_VECTOR (k, ai.Signatures)
+ {
+ const CByteBuffer &sig = ai.Signatures[k];
+ /*
+ UInt32 signatureEnd = ai.SignatureOffset + (UInt32)sig.Size();
+ if (maxSignatureEnd < signatureEnd)
+ maxSignatureEnd = signatureEnd;
+ */
+ if (sig.Size() < kNumHashBytes)
+ {
+ isDifficult = true;
+ continue;
+ }
+ thereAreHandlersForSearch = true;
+ UInt32 v = HASH_VAL(sig, 0);
+ unsigned sigIndex = arc2sig[index] + k;
+ prevs[sigIndex] = hash[v];
+ hash[v] = (Byte)sigIndex;
+ }
+ }
+ if (isDifficult)
{
- RINOK(setCompressCodecsInfo->SetCompressCodecsInfo(codecs));
+ difficultFormats.Add(index);
+ difficultBools[index] = true;
}
}
+
+ if (!thereAreHandlersForSearch)
+ {
+ // openOnlyFullArc = true;
+ // canReturnTailArc = true;
+ }
+
+ RINOK(op.stream->Seek(0, STREAM_SEEK_SET, NULL));
+
+ CLimitedCachedInStream *limitedStreamSpec = new CLimitedCachedInStream;
+ CMyComPtr<IInStream> limitedStream = limitedStreamSpec;
+ limitedStreamSpec->SetStream(op.stream);
+
+ openCallback_Offset_Spec->Callback = op.callback;
+
+ #ifndef _NO_CRYPTO
+ if (op.callback)
+ {
+ openCallback_Offset_Spec->Callback.QueryInterface(IID_ICryptoGetTextPassword, &openCallback_Offset_Spec->GetTextPassword);
+ }
#endif
- // OutputDebugStringW(codecs->Formats[FormatIndex].Name);
+ RINOK(op.callback->SetTotal(NULL, &fileSize));
+ CByteBuffer &byteBuffer = limitedStreamSpec->Buffer;
+ byteBuffer.Alloc(kBufSize);
- HRESULT result;
- if (stream)
- result = archive->Open(stream, &kMaxCheckStartPosition, callback);
- else
+ UInt64 callbackPrev = 0;
+ bool needCheckStartOpen = true; // = true, if we need to test all archives types for current pos.
+
+ bool endOfFile = false;
+ UInt64 bufPhyPos = 0;
+ size_t bytesInBuf = 0;
+ // UInt64 prevPos = 0;
+
+ // ---------- Main Scan Loop ----------
+
+ UInt64 pos = 0;
+
+ if (!mode.EachPos && handlerSpec->_items.Size() == 1)
{
- CMyComPtr<IArchiveOpenSeq> openSeq;
- archive.QueryInterface(IID_IArchiveOpenSeq, (void **)&openSeq);
- if (!openSeq)
- return E_NOTIMPL;
- result = openSeq->OpenSeq(seqStream);
+ NArchive::NParser::CParseItem &pi = handlerSpec->_items[0];
+ if (!pi.LenIsUnknown && pi.Offset == 0)
+ pos = pi.Size;
}
- if (result == S_FALSE)
- continue;
- RINOK(result);
+ for (;;)
+ {
+ // printf("\nPos = %d", (int)pos);
+ UInt64 posInBuf = pos - bufPhyPos;
+
+ // if (pos > ((UInt64)1 << 35)) break;
+
+ if (!endOfFile)
+ {
+ if (bytesInBuf < kBufSize)
+ {
+ size_t processedSize = kBufSize - bytesInBuf;
+ // printf("\nRead ask = %d", (unsigned)processedSize);
+ UInt64 seekPos = bufPhyPos + bytesInBuf;
+ RINOK(op.stream->Seek(bufPhyPos + bytesInBuf, STREAM_SEEK_SET, NULL));
+ RINOK(ReadStream(op.stream, byteBuffer + bytesInBuf, &processedSize));
+ // printf(" processed = %d", (unsigned)processedSize);
+ if (processedSize == 0)
+ {
+ fileSize = seekPos;
+ endOfFile = true;
+ }
+ else
+ {
+ bytesInBuf += processedSize;
+ limitedStreamSpec->SetCache(processedSize, (size_t)bufPhyPos);
+ }
+ continue;
+ }
+
+ if (bytesInBuf < posInBuf)
+ {
+ UInt64 skipSize = posInBuf - bytesInBuf;
+ if (skipSize <= kBeforeSize)
+ {
+ size_t keepSize = (size_t)(kBeforeSize - skipSize);
+ // printf("\nmemmove skip = %d", (int)keepSize);
+ memmove(byteBuffer, byteBuffer + bytesInBuf - keepSize, keepSize);
+ bytesInBuf = keepSize;
+ bufPhyPos = pos - keepSize;
+ continue;
+ }
+ // printf("\nSkip %d", (int)(skipSize - kBeforeSize));
+ // RINOK(op.stream->Seek(skipSize - kBeforeSize, STREAM_SEEK_CUR, NULL));
+ bytesInBuf = 0;
+ bufPhyPos = pos - kBeforeSize;
+ continue;
+ }
+
+ if (bytesInBuf - posInBuf < kAfterSize)
+ {
+ size_t beg = (size_t)posInBuf - kBeforeSize;
+ // printf("\nmemmove for after beg = %d", (int)beg);
+ memmove(byteBuffer, byteBuffer + beg, bytesInBuf - beg);
+ bufPhyPos += beg;
+ bytesInBuf -= beg;
+ continue;
+ }
+ }
+
+ if (pos >= callbackPrev + (1 << 23))
+ {
+ openCallback_Offset_Spec->Files = handlerSpec->_items.Size();
+ openCallback_Offset_Spec->Offset = pos;
+ RINOK(openCallback_Offset->SetCompleted(NULL, NULL));
+ callbackPrev = pos;
+ }
+
+ {
+ UInt64 endPos = bufPhyPos + bytesInBuf;
+ if (fileSize < endPos)
+ {
+ FileSize = fileSize; // why ????
+ fileSize = endPos;
+ }
+ }
+
+ size_t availSize = bytesInBuf - (size_t)posInBuf;
+ if (availSize < kNumHashBytes)
+ break;
+ size_t scanSize = availSize -
+ ((availSize >= kAfterSize) ? kAfterSize : kNumHashBytes);
+
+ {
+ /*
+ UInt64 scanLimit = openOnlyFullArc ?
+ maxSignatureEnd :
+ op.openType.ScanSize + maxSignatureEnd;
+ */
+ if (!mode.CanReturnParser)
+ {
+ if (pos > maxStartOffset)
+ break;
+ UInt64 remScan = maxStartOffset - pos;
+ if (scanSize > remScan)
+ scanSize = (size_t)remScan;
+ }
+ }
+ scanSize++;
+
+ const Byte *buf = byteBuffer + (size_t)posInBuf;
+ size_t ppp = 0;
+
+ if (!needCheckStartOpen)
+ {
+ for (; ppp < scanSize && hash[HASH_VAL(buf, ppp)] == 0xFF; ppp++);
+ pos += ppp;
+ if (ppp == scanSize)
+ continue;
+ }
+
+ UInt32 v = HASH_VAL(buf, ppp);
+ bool nextNeedCheckStartOpen = true;
+ unsigned i = hash[v];
+ unsigned indexOfDifficult = 0;
+
+ // ---------- Open Loop for Current Pos ----------
+ bool wasOpen = false;
+
+ for (;;)
+ {
+ unsigned index;
+ bool isDifficult;
+ if (needCheckStartOpen && indexOfDifficult < difficultFormats.Size())
+ {
+ index = difficultFormats[indexOfDifficult++];
+ isDifficult = true;
+ }
+ else
+ {
+ if (i == 0xFF)
+ break;
+ index = sig2arc[i];
+ unsigned sigIndex = i - arc2sig[index];
+ i = prevs[i];
+ if (needCheckStartOpen && difficultBools[index])
+ continue;
+ const CArcInfoEx &ai = op.codecs->Formats[index];
+
+ if (pos < ai.SignatureOffset)
+ continue;
+
+ /*
+ if (openOnlyFullArc)
+ if (pos != ai.SignatureOffset)
+ continue;
+ */
+
+ const CByteBuffer &sig = ai.Signatures[sigIndex];
+
+ if (ppp + sig.Size() > availSize
+ || !TestSignature(buf + ppp, sig, sig.Size()))
+ continue;
+ // printf("\nSignature OK: %10S %8x %5d", (const wchar_t *)ai.Name, (int)pos, (int)(pos - prevPos));
+ // prevPos = pos;
+ isDifficult = false;
+ }
+
+ const CArcInfoEx &ai = op.codecs->Formats[index];
+
+
+ if ((isDifficult && pos == 0) || ai.SignatureOffset == pos)
+ {
+ // we don't check same archive second time */
+ if (skipFrontalFormat[index])
+ continue;
+ }
+
+ UInt64 startArcPos = pos;
+ if (!isDifficult)
+ {
+ if (pos < ai.SignatureOffset)
+ continue;
+ startArcPos = pos - ai.SignatureOffset;
+ /*
+ // we don't need the check for Z files
+ if (startArcPos < handlerSpec->GetLastEnd())
+ continue;
+ */
+ }
+
+ if (ai.IsArcFunc && startArcPos >= bufPhyPos)
+ {
+ size_t offsetInBuf = (size_t)(startArcPos - bufPhyPos);
+ if (offsetInBuf < bytesInBuf)
+ {
+ UInt32 isArcRes = ai.IsArcFunc(byteBuffer + offsetInBuf, bytesInBuf - offsetInBuf);
+ if (isArcRes == k_IsArc_Res_NO)
+ continue;
+ if (isArcRes == k_IsArc_Res_NEED_MORE && endOfFile)
+ continue;
+ /*
+ if (isArcRes == k_IsArc_Res_YES_LOW_PROB)
+ {
+ // if (pos != ai.SignatureOffset)
+ continue;
+ }
+ */
+ }
+ // printf("\nIsArc OK: %S", (const wchar_t *)ai.Name);
+ }
+
+ /*
+ if (pos == 67109888)
+ pos = pos;
+ */
+ PRF(printf("\npos = %9I64d : %S", pos, (const wchar_t *)ai.Name));
+
+ bool isMainFormat = isMainFormatArr[index];
+ const COpenSpecFlags &specFlags = mode.GetSpec(isForced, isMainFormat, isUnknownExt);
+
+ CMyComPtr<IInArchive> archive;
+ RINOK(PrepareToOpen(op, index, archive));
+ if (!archive)
+ return E_FAIL;
+
+ // OutputDebugStringW(ai.Name);
+
+ UInt64 rem = fileSize - startArcPos;
+
+ UInt64 arcStreamOffset = 0;
+
+ if (ai.Flags_UseGlobalOffset())
+ {
+ limitedStreamSpec->InitAndSeek(0, fileSize);
+ limitedStream->Seek(startArcPos, STREAM_SEEK_SET, NULL);
+ }
+ else
+ {
+ limitedStreamSpec->InitAndSeek(startArcPos, rem);
+ arcStreamOffset = startArcPos;
+ }
+
+ UInt64 maxCheckStartPosition = 0;
+ openCallback_Offset_Spec->Files = handlerSpec->_items.Size();
+ openCallback_Offset_Spec->Offset = startArcPos;
+ // HRESULT result = archive->Open(limitedStream, &maxCheckStartPosition, openCallback_Offset);
+ extractCallback_To_OpenCallback_Spec->Files = 0;
+ extractCallback_To_OpenCallback_Spec->Offset = startArcPos;
+
+ HRESULT result = OpenArchiveSpec(archive, true, limitedStream, &maxCheckStartPosition, openCallback_Offset, extractCallback_To_OpenCallback);
+
+ RINOK(ReadBasicProps(archive, ai.Flags_UseGlobalOffset() ? 0 : startArcPos, result));
+
+ bool isOpen = false;
+ if (result == S_FALSE)
+ {
+ if (!mode.CanReturnParser)
+ {
+ if (formatIndex < 0 && ErrorInfo.IsArc_After_NonOpen())
+ {
+ ErrorInfo.ErrorFormatIndex = index;
+ NonOpen_ErrorInfo = ErrorInfo;
+ // if archive was detected, we don't need additional open attempts
+ return S_FALSE;
+ }
+ continue;
+ }
+ if (!ErrorInfo.IsArc_After_NonOpen() || !PhySizeDefined || PhySize == 0)
+ continue;
+ }
+ else
+ {
+ isOpen = true;
+ RINOK(result);
+ PRF(printf(" OK "));
+ }
+
+ // fprintf(stderr, "\n %8X %S", startArcPos, Path);
+ // printf("\nOpen OK: %S", ai.Name);
+
+
+ NArchive::NParser::CParseItem pi;
+ pi.Offset = startArcPos;
+
+ if (ai.Flags_UseGlobalOffset())
+ pi.Offset = Offset;
+ else if (Offset != 0)
+ return E_FAIL;
+ UInt64 arcRem = FileSize - pi.Offset;
+ UInt64 phySize = arcRem;
+ bool phySizeDefined = PhySizeDefined;
+ if (phySizeDefined)
+ {
+ if (pi.Offset + PhySize > FileSize)
+ {
+ // ErrorInfo.ThereIsTail = true;
+ PhySize = FileSize - pi.Offset;
+ }
+ phySize = PhySize;
+ }
+ if (phySize == 0 || (UInt64)phySize > ((UInt64)1 << 63))
+ return E_FAIL;
+
+ /*
+ if (!ai.UseGlobalOffset)
+ {
+ if (phySize > arcRem)
+ {
+ ThereIsTail = true;
+ phySize = arcRem;
+ }
+ }
+ */
+
+ bool needScan = false;
+
+
+ if (isOpen && !phySizeDefined)
+ {
+ // it's for Z format
+ pi.LenIsUnknown = true;
+ needScan = true;
+ phySize = arcRem;
+ nextNeedCheckStartOpen = false;
+ }
+
+ pi.Size = phySize;
+ /*
+ if (OkPhySize_Defined)
+ pi.OkSize = OkPhySize;
+ */
+ pi.NormalizeOffset();
+ // printf(" phySize = %8d", (unsigned)phySize);
+
+ /*
+ if (needSkipFullArc)
+ if (pi.Offset == 0 && phySizeDefined && pi.Size >= fileSize)
+ continue;
+ */
+ if (pi.Offset == 0 && !pi.LenIsUnknown && pi.Size >= FileSize)
+ {
+ // it's possible for dmg archives
+ if (!mode.CanReturnArc)
+ continue;
+ }
+
+ if (mode.EachPos)
+ pos++;
+ else if (needScan)
+ {
+ pos++;
+ /*
+ if (!OkPhySize_Defined)
+ pos++;
+ else
+ pos = pi.Offset + pi.OkSize;
+ */
+ }
+ else
+ pos = pi.Offset + pi.Size;
+
+
+ RINOK(ReadParseItemProps(archive, ai, pi));
+
+ if (pi.Offset < startArcPos && !mode.EachPos /* && phySizeDefined */)
+ {
+ /* It's for DMG format.
+ This code deletes all previous items that are included to current item */
+
+ while (!handlerSpec->_items.IsEmpty())
+ {
+ {
+ const NArchive::NParser::CParseItem &back = handlerSpec->_items.Back();
+ if (back.Offset < pi.Offset)
+ break;
+ if (back.Offset + back.Size > pi.Offset + pi.Size)
+ break;
+ }
+ handlerSpec->_items.DeleteBack();
+ }
+ }
+
+
+ if (isOpen && mode.CanReturnArc && phySizeDefined)
+ {
+ // if (pi.Offset + pi.Size >= fileSize)
+ bool openCur = false;
+
+ bool thereIsTail = ErrorInfo.ThereIsTail;
+ if (thereIsTail && mode.ZerosTailIsAllowed)
+ {
+ RINOK(CheckZerosTail(op, arcStreamOffset + Offset + PhySize));
+ if (ErrorInfo.IgnoreTail)
+ thereIsTail = false;
+ }
+
+ if (pi.Offset != 0)
+ {
+ if (!pi.IsNotArcType)
+ if (thereIsTail)
+ openCur = specFlags.CanReturnMid;
+ else
+ openCur = specFlags.CanReturnTail;
+ }
+ else
+ {
+ if (!thereIsTail)
+ openCur = true;
+ else
+ openCur = specFlags.CanReturnFrontal;
+
+
+ if (formatIndex >= -2)
+ openCur = true;
+ }
+ if (formatIndex < 0 && pi.IsSelfExe /* && mode.SkipSfxStub */)
+ openCur = false;
+
+ // We open file as SFX, if there is front archive or first archive is "Self Executable"
+ if (!openCur && !pi.IsSelfExe && !thereIsTail &&
+ (!pi.IsNotArcType || pi.Offset == 0))
+ {
+ if (handlerSpec->_items.IsEmpty())
+ {
+ if (specFlags.CanReturnTail)
+ openCur = true;
+ }
+ else if (handlerSpec->_items.Size() == 1)
+ {
+ if (handlerSpec->_items[0].IsSelfExe)
+ {
+ if (mode.SpecUnknownExt.CanReturnTail)
+ openCur = true;
+ }
+ }
+ }
+
+ if (openCur)
+ {
+ InStream = op.stream;
+ Archive = archive;
+ FormatIndex = index;
+ ArcStreamOffset = arcStreamOffset;
+ return S_OK;
+ }
+ }
+
+ /*
+ if (openOnlyFullArc)
+ {
+ ErrorInfo.ClearErrors();
+ return S_FALSE;
+ }
+ */
+
+ pi.FormatIndex = index;
+
+ // printf("\nAdd offset = %d", (int)pi.Offset);
+ handlerSpec->AddItem(pi);
+ wasOpen = true;
+ break;
+ }
+ // ---------- End of Open Loop for Current Pos ----------
+
+ if (!wasOpen)
+ pos++;
+ needCheckStartOpen = (nextNeedCheckStartOpen && wasOpen);
+ }
+ // ---------- End of Main Scan Loop ----------
+
+ /*
+ if (handlerSpec->_items.Size() == 1)
{
- NCOM::CPropVariant prop;
- archive->GetArchiveProperty(kpidError, &prop);
- if (prop.vt != VT_EMPTY)
- ErrorMessage = (prop.vt == VT_BSTR) ? prop.bstrVal : L"Unknown error";
- }
-
- Archive = archive;
- const CArcInfoEx &format = codecs->Formats[FormatIndex];
- if (format.Exts.Size() == 0)
- DefaultName = GetDefaultName2(fileName, L"", L"");
- else
+ const NArchive::NParser::CParseItem &pi = handlerSpec->_items[0];
+ if (pi.Size == fileSize && pi.Offset == 0)
+ {
+ Archive = archive;
+ FormatIndex2 = pi.FormatIndex;
+ return S_OK;
+ }
+ }
+ */
+
+ if (mode.CanReturnParser)
{
- int subExtIndex = format.FindExtension(extension);
- if (subExtIndex < 0)
- subExtIndex = 0;
- const CArcExtInfo &extInfo = format.Exts[subExtIndex];
- DefaultName = GetDefaultName2(fileName, extInfo.Ext, extInfo.AddExt);
+ bool returnParser = (handlerSpec->_items.Size() == 1); // it's possible if fileSize was not correct at start of parsing
+ handlerSpec->AddUnknownItem(fileSize);
+ if (handlerSpec->_items.Size() == 0)
+ return S_FALSE;
+ if (returnParser || handlerSpec->_items.Size() != 1)
+ {
+ // return S_FALSE;
+ handlerSpec->_stream = op.stream;
+ Archive = handler;
+ ErrorInfo.ClearErrors();
+ IsParseArc = true;
+ FormatIndex = -1; // It's parser
+ Offset = 0;
+ return S_OK;
+ }
+ }
+ }
+
+ #endif
+
+ if (!Archive)
+ return S_FALSE;
+ return S_OK;
+}
+
+HRESULT CArc::OpenStream(const COpenOptions &op)
+{
+ RINOK(OpenStream2(op));
+ // PrintNumber("op.formatIndex 3", op.formatIndex);
+
+ if (Archive)
+ {
+ GetRawProps.Release();
+ GetRootProps.Release();
+ Archive->QueryInterface(IID_IArchiveGetRawProps, (void **)&GetRawProps);
+ Archive->QueryInterface(IID_IArchiveGetRootProps, (void **)&GetRootProps);
+
+ RINOK(Archive_GetArcBoolProp(Archive, kpidIsTree, IsTree));
+ RINOK(Archive_GetArcBoolProp(Archive, kpidIsDeleted, Ask_Deleted));
+ RINOK(Archive_GetArcBoolProp(Archive, kpidIsAltStream, Ask_AltStream));
+ RINOK(Archive_GetArcBoolProp(Archive, kpidIsAux, Ask_Aux));
+ RINOK(Archive_GetArcBoolProp(Archive, kpidINode, Ask_INode));
+
+ const UString fileName = ExtractFileNameFromPath(Path);
+ UString extension;
+ {
+ int dotPos = fileName.ReverseFind(L'.');
+ if (dotPos >= 0)
+ extension = fileName.Ptr(dotPos + 1);
+ }
+
+ DefaultName.Empty();
+ if (FormatIndex >= 0)
+ {
+ const CArcInfoEx &ai = op.codecs->Formats[FormatIndex];
+ if (ai.Exts.Size() == 0)
+ DefaultName = GetDefaultName2(fileName, L"", L"");
+ else
+ {
+ int subExtIndex = ai.FindExtension(extension);
+ if (subExtIndex < 0)
+ subExtIndex = 0;
+ const CArcExtInfo &extInfo = ai.Exts[subExtIndex];
+ DefaultName = GetDefaultName2(fileName, extInfo.Ext, extInfo.AddExt);
+ }
}
- return S_OK;
}
- return S_FALSE;
+
+ return S_OK;
}
-HRESULT CArc::OpenStreamOrFile(
- CCodecs *codecs,
- int formatIndex,
- bool stdInMode,
- IInStream *stream,
- IArchiveOpenCallback *callback)
+#ifdef _SFX
+
+#ifdef _WIN32
+ static const wchar_t *k_ExeExt = L".exe";
+ static const unsigned k_ExeExt_Len = 4;
+#else
+ static const wchar_t *k_ExeExt = L"";
+ static const unsigned k_ExeExt_Len = 0;
+#endif
+
+#endif
+
+HRESULT CArc::OpenStreamOrFile(COpenOptions &op)
{
CMyComPtr<IInStream> fileStream;
CMyComPtr<ISequentialInStream> seqStream;
- if (stdInMode)
+ CInFileStream *fileStreamSpec = NULL;
+ if (op.stdInMode)
+ {
seqStream = new CStdInFileStream;
- else if (!stream)
+ op.seqStream = seqStream;
+ }
+ else if (!op.stream)
{
- CInFileStream *fileStreamSpec = new CInFileStream(true);
+ fileStreamSpec = new CInFileStream(true);
fileStream = fileStreamSpec;
- if (!fileStreamSpec->Open(Path))
+ Path = filePath;
+ if (!fileStreamSpec->Open(us2fs(Path)))
+ {
return GetLastError();
- stream = fileStream;
+ }
+ op.stream = fileStream;
+ #ifdef _SFX
+ IgnoreSplit = true;
+ #endif
}
/*
if (callback)
{
UInt64 fileSize;
- RINOK(stream->Seek(0, STREAM_SEEK_END, &fileSize));
- RINOK(callback->SetTotal(NULL, &fileSize))
+ RINOK(op.stream->Seek(0, STREAM_SEEK_END, &fileSize));
+ RINOK(op.callback->SetTotal(NULL, &fileSize))
}
*/
- return OpenStream(codecs, formatIndex, stream, seqStream, callback);
+ HRESULT res = OpenStream(op);
+ IgnoreSplit = false;
+
+ #ifdef _SFX
+
+ if (res != S_FALSE
+ || !fileStreamSpec
+ || !op.callbackSpec
+ || NonOpen_ErrorInfo.IsArc_After_NonOpen())
+ return res;
+ {
+ if (filePath.Len() > k_ExeExt_Len
+ && MyStringCompareNoCase(filePath.RightPtr(k_ExeExt_Len), k_ExeExt) == 0)
+ {
+ const UString path2 = filePath.Left(filePath.Len() - k_ExeExt_Len);
+ FOR_VECTOR (i, op.codecs->Formats)
+ {
+ const CArcInfoEx &ai = op.codecs->Formats[i];
+ if (ai.IsSplit())
+ continue;
+ UString path3 = path2;
+ path3 += L".";
+ path3 += ai.GetMainExt(); // "7z" for SFX.
+ Path = path3 + L".001";
+ bool isOk = op.callbackSpec->SetSecondFileInfo(us2fs(Path));
+ if (!isOk)
+ {
+ Path = path3;
+ isOk = op.callbackSpec->SetSecondFileInfo(us2fs(Path));
+ }
+ if (isOk)
+ {
+ if (fileStreamSpec->Open(us2fs(Path)))
+ {
+ op.stream = fileStream;
+ NonOpen_ErrorInfo.ClearErrors_Full();
+ if (OpenStream(op) == S_OK)
+ return S_OK;
+ }
+ }
+ }
+ }
+ }
+
+ #endif
+
+ return res;
+}
+
+void CArchiveLink::KeepModeForNextOpen()
+{
+ for (int i = Arcs.Size() - 1; i >= 0; i--)
+ {
+ CMyComPtr<IArchiveKeepModeForNextOpen> keep;
+ Arcs[i].Archive->QueryInterface(IID_IArchiveKeepModeForNextOpen, (void **)&keep);
+ if (keep)
+ keep->KeepModeForNextOpen();
+ }
}
HRESULT CArchiveLink::Close()
{
- for (int i = Arcs.Size() - 1; i >= 0; i--)
+ for (int i = Arcs.Size() - 1; i >= 0; i--)
{
- RINOK(Arcs[i].Archive->Close());
+ RINOK(Arcs[i].Close());
}
IsOpen = false;
+ // ErrorsText.Empty();
return S_OK;
}
void CArchiveLink::Release()
{
+ // NonOpenErrorFormatIndex = -1;
+ NonOpen_ErrorInfo.ClearErrors();
+ NonOpen_ArcPath.Empty();
while (!Arcs.IsEmpty())
Arcs.DeleteBack();
}
-HRESULT CArchiveLink::Open(
- CCodecs *codecs,
- const CIntVector &formatIndices,
- bool stdInMode,
- IInStream *stream,
- const UString &filePath,
- IArchiveOpenCallback *callback)
+/*
+void CArchiveLink::Set_ErrorsText()
+{
+ FOR_VECTOR(i, Arcs)
+ {
+ const CArc &arc = Arcs[i];
+ if (!arc.ErrorFlagsText.IsEmpty())
+ {
+ if (!ErrorsText.IsEmpty())
+ ErrorsText += L'\n';
+ ErrorsText += GetUnicodeString(arc.ErrorFlagsText);
+ }
+ if (!arc.ErrorMessage.IsEmpty())
+ {
+ if (!ErrorsText.IsEmpty())
+ ErrorsText += L'\n';
+ ErrorsText += arc.ErrorMessage;
+ }
+
+ if (!arc.WarningMessage.IsEmpty())
+ {
+ if (!ErrorsText.IsEmpty())
+ ErrorsText += L'\n';
+ ErrorsText += arc.WarningMessage;
+ }
+ }
+}
+*/
+
+HRESULT CArchiveLink::Open(COpenOptions &op)
{
Release();
- if (formatIndices.Size() >= 32)
+ if (op.types->Size() >= 32)
return E_NOTIMPL;
-
+
HRESULT resSpec;
for (;;)
{
resSpec = S_OK;
- int formatIndex = -1;
- if (formatIndices.Size() >= 1)
+
+ op.openType = COpenType();
+ if (op.types->Size() >= 1)
{
- if (Arcs.Size() >= formatIndices.Size())
- break;
- formatIndex = formatIndices[formatIndices.Size() - Arcs.Size() - 1];
+ COpenType latest;
+ if (Arcs.Size() < op.types->Size())
+ latest = (*op.types)[op.types->Size() - Arcs.Size() - 1];
+ else
+ {
+ latest = (*op.types)[0];
+ if (!latest.Recursive)
+ break;
+ }
+ op.openType = latest;
}
else if (Arcs.Size() >= 32)
break;
+ /*
+ op.formatIndex = -1;
+ if (op.types->Size() >= 1)
+ {
+ int latest;
+ if (Arcs.Size() < op.types->Size())
+ latest = (*op.types)[op.types->Size() - Arcs.Size() - 1];
+ else
+ {
+ latest = (*op.types)[0];
+ if (latest != -2 && latest != -3)
+ break;
+ }
+ if (latest >= 0)
+ op.formatIndex = latest;
+ else if (latest == -1 || latest == -2)
+ {
+ // default
+ }
+ else if (latest == -3)
+ op.formatIndex = -2;
+ else
+ op.formatIndex = latest + 2;
+ }
+ else if (Arcs.Size() >= 32)
+ break;
+ */
+
if (Arcs.IsEmpty())
{
CArc arc;
- arc.Path = filePath;
+ arc.filePath = op.filePath;
+ arc.Path = op.filePath;
arc.SubfileIndex = (UInt32)(Int32)-1;
- RINOK(arc.OpenStreamOrFile(codecs, formatIndex, stdInMode, stream, callback));
+ HRESULT result = arc.OpenStreamOrFile(op);
+ if (result != S_OK)
+ {
+ if (result == S_FALSE)
+ {
+ NonOpen_ErrorInfo = arc.NonOpen_ErrorInfo;
+ // NonOpenErrorFormatIndex = arc.ErrorFormatIndex;
+ NonOpen_ArcPath = arc.Path;
+ }
+ return result;
+ }
Arcs.Add(arc);
continue;
}
-
+
+ // PrintNumber("op.formatIndex 11", op.formatIndex);
+
const CArc &arc = Arcs.Back();
-
- resSpec = (formatIndices.Size() == 0 ? S_OK : E_NOTIMPL);
-
+
+ if (op.types->Size() > Arcs.Size())
+ resSpec = E_NOTIMPL;
+
UInt32 mainSubfile;
{
NCOM::CPropVariant prop;
@@ -427,41 +2890,68 @@ HRESULT CArchiveLink::Open(
break;
}
-
+
CMyComPtr<IInArchiveGetStream> getStream;
if (arc.Archive->QueryInterface(IID_IInArchiveGetStream, (void **)&getStream) != S_OK || !getStream)
break;
-
+
CMyComPtr<ISequentialInStream> subSeqStream;
if (getStream->GetStream(mainSubfile, &subSeqStream) != S_OK || !subSeqStream)
break;
-
+
CMyComPtr<IInStream> subStream;
if (subSeqStream.QueryInterface(IID_IInStream, &subStream) != S_OK || !subStream)
break;
-
+
CArc arc2;
RINOK(arc.GetItemPath(mainSubfile, arc2.Path));
-
+
+ bool zerosTailIsAllowed;
+ RINOK(Archive_GetItemBoolProp(arc.Archive, mainSubfile, kpidZerosTailIsAllowed, zerosTailIsAllowed));
+
CMyComPtr<IArchiveOpenSetSubArchiveName> setSubArchiveName;
- callback->QueryInterface(IID_IArchiveOpenSetSubArchiveName, (void **)&setSubArchiveName);
+ op.callback->QueryInterface(IID_IArchiveOpenSetSubArchiveName, (void **)&setSubArchiveName);
if (setSubArchiveName)
setSubArchiveName->SetSubArchiveName(arc2.Path);
-
+
arc2.SubfileIndex = mainSubfile;
- HRESULT result = arc2.OpenStream(codecs, formatIndex, subStream, NULL, callback);
- resSpec = (formatIndices.Size() == 0 ? S_OK : S_FALSE);
+
+ // CIntVector incl;
+ CIntVector excl;
+
+ COpenOptions op2;
+ #ifndef _SFX
+ op2.props = op.props;
+ #endif
+ op2.codecs = op.codecs;
+ // op2.types = &incl;
+ op2.openType = op.openType;
+ op2.openType.ZerosTailIsAllowed = zerosTailIsAllowed;
+ op2.excludedFormats = &excl;
+ op2.stdInMode = false;
+ op2.stream = subStream;
+ op2.filePath = arc2.Path;
+ op2.callback = op.callback;
+ op2.callbackSpec = op.callbackSpec;
+
+
+ HRESULT result = arc2.OpenStream(op2);
+ resSpec = (op.types->Size() == 0 ? S_OK : S_FALSE);
if (result == S_FALSE)
+ {
+ NonOpen_ErrorInfo = arc2.ErrorInfo;
+ NonOpen_ArcPath = arc2.Path;
break;
+ }
RINOK(result);
RINOK(arc.GetItemMTime(mainSubfile, arc2.MTime, arc2.MTimeDefined));
Arcs.Add(arc2);
}
IsOpen = !Arcs.IsEmpty();
- return S_OK;
+ return resSpec;
}
-static void SetCallback(const UString &filePath,
+static void SetCallback(const FString &filePath,
IOpenCallbackUI *callbackUI,
IArchiveOpenCallback *reOpenCallback,
CMyComPtr<IArchiveOpenCallback> &callback)
@@ -471,19 +2961,12 @@ static void SetCallback(const UString &filePath,
openCallbackSpec->Callback = callbackUI;
openCallbackSpec->ReOpenCallback = reOpenCallback;
- UString fullName;
- int fileNamePartStartIndex;
- NFile::NDirectory::MyGetFullPathName(filePath, fullName, fileNamePartStartIndex);
- openCallbackSpec->Init(
- fullName.Left(fileNamePartStartIndex),
- fullName.Mid(fileNamePartStartIndex));
+ FString dirPrefix, fileName;
+ NFile::NDir::GetFullPathAndSplit(filePath, dirPrefix, fileName);
+ openCallbackSpec->Init(dirPrefix, fileName);
}
-HRESULT CArchiveLink::Open2(CCodecs *codecs,
- const CIntVector &formatIndices,
- bool stdInMode,
- IInStream *stream,
- const UString &filePath,
+HRESULT CArchiveLink::Open2(COpenOptions &op,
IOpenCallbackUI *callbackUI)
{
VolumesSize = 0;
@@ -491,46 +2974,237 @@ HRESULT CArchiveLink::Open2(CCodecs *codecs,
CMyComPtr<IArchiveOpenCallback> callback = openCallbackSpec;
openCallbackSpec->Callback = callbackUI;
- UString fullName, prefix, name;
- if (!stream && !stdInMode)
+ FString prefix, name;
+ if (!op.stream && !op.stdInMode)
{
- int fileNamePartStartIndex;
- if (!NFile::NDirectory::MyGetFullPathName(filePath, fullName, fileNamePartStartIndex))
- return GetLastError();
- prefix = fullName.Left(fileNamePartStartIndex);
- name = fullName.Mid(fileNamePartStartIndex);
+ NFile::NDir::GetFullPathAndSplit(us2fs(op.filePath), prefix, name);
openCallbackSpec->Init(prefix, name);
}
else
{
- openCallbackSpec->SetSubArchiveName(filePath);
+ openCallbackSpec->SetSubArchiveName(op.filePath);
}
- RINOK(Open(codecs, formatIndices, stdInMode, stream, filePath, callback));
- VolumePaths.Add(prefix + name);
- for (int i = 0; i < openCallbackSpec->FileNames.Size(); i++)
- VolumePaths.Add(prefix + openCallbackSpec->FileNames[i]);
- VolumesSize = openCallbackSpec->TotalSize;
+ op.callback = callback;
+ op.callbackSpec = openCallbackSpec;
+ RINOK(Open(op));
+ // VolumePaths.Add(fs2us(prefix + name));
+
+ FOR_VECTOR (i, openCallbackSpec->FileNames_WasUsed)
+ {
+ if (openCallbackSpec->FileNames_WasUsed[i])
+ {
+ VolumePaths.Add(fs2us(prefix) + openCallbackSpec->FileNames[i]);
+ VolumesSize += openCallbackSpec->FileSizes[i];
+ }
+ }
+ // VolumesSize = openCallbackSpec->TotalSize;
return S_OK;
}
-HRESULT CArchiveLink::ReOpen(CCodecs *codecs, const UString &filePath,
- IArchiveOpenCallback *callback)
+HRESULT CArc::ReOpen(const COpenOptions &op)
+{
+ ErrorInfo.ClearErrors();
+ ErrorInfo.ErrorFormatIndex = -1;
+
+ UInt64 fileSize = 0;
+ if (op.stream)
+ {
+ RINOK(op.stream->Seek(0, STREAM_SEEK_END, &fileSize));
+ RINOK(op.stream->Seek(0, STREAM_SEEK_SET, NULL));
+ }
+ FileSize = fileSize;
+
+ CMyComPtr<IInStream> stream2;
+ Int64 globalOffset = GetGlobalOffset();
+ if (globalOffset <= 0)
+ stream2 = op.stream;
+ else
+ {
+ CTailInStream *tailStreamSpec = new CTailInStream;
+ stream2 = tailStreamSpec;
+ tailStreamSpec->Stream = op.stream;
+ tailStreamSpec->Offset = globalOffset;
+ tailStreamSpec->Init();
+ RINOK(tailStreamSpec->SeekToStart());
+ }
+
+ // There are archives with embedded STUBs (like ZIP), so we must support signature scanning
+ // But for another archives we can use 0 here. So the code can be fixed !!!
+ UInt64 maxStartPosition = kMaxCheckStartPosition;
+ HRESULT res = Archive->Open(stream2, &maxStartPosition, op.callback);
+
+ if (res == S_OK)
+ {
+ RINOK(ReadBasicProps(Archive, globalOffset, res));
+ ArcStreamOffset = globalOffset;
+ if (ArcStreamOffset != 0)
+ InStream = op.stream;
+ }
+ return res;
+}
+
+
+HRESULT CArchiveLink::ReOpen(COpenOptions &op)
{
if (Arcs.Size() > 1)
return E_NOTIMPL;
- if (Arcs.Size() == 0)
- return Open2(codecs, CIntVector(), false, NULL, filePath, 0);
+ CObjectVector<COpenType> inc;
+ CIntVector excl;
- CMyComPtr<IArchiveOpenCallback> openCallbackNew;
- SetCallback(filePath, NULL, callback, openCallbackNew);
+ op.types = &inc;
+ op.excludedFormats = &excl;
+ op.stdInMode = false;
+ op.stream = NULL;
+ if (Arcs.Size() == 0) // ???
+ return Open2(op, NULL);
+ CMyComPtr<IArchiveOpenCallback> openCallbackNew;
+ SetCallback(us2fs(op.filePath), NULL, op.callback, openCallbackNew);
CInFileStream *fileStreamSpec = new CInFileStream(true);
CMyComPtr<IInStream> stream(fileStreamSpec);
- if (!fileStreamSpec->Open(filePath))
+ if (!fileStreamSpec->Open(us2fs(op.filePath)))
return GetLastError();
- HRESULT res = GetArchive()->Open(stream, &kMaxCheckStartPosition, callback);
+ op.stream = stream;
+
+ CArc &arc = Arcs[0];
+ HRESULT res = arc.ReOpen(op);
IsOpen = (res == S_OK);
return res;
}
+
+#ifndef _SFX
+
+bool ParseComplexSize(const wchar_t *s, UInt64 &result)
+{
+ result = 0;
+ const wchar_t *end;
+ UInt64 number = ConvertStringToUInt64(s, &end);
+ if (end == s)
+ return false;
+ if (*end == 0)
+ {
+ result = number;
+ return true;
+ }
+ if (end[1] != 0)
+ return false;
+ unsigned numBits;
+ switch (MyCharLower_Ascii(*end))
+ {
+ case 'b': result = number; return true;
+ case 'k': numBits = 10; break;
+ case 'm': numBits = 20; break;
+ case 'g': numBits = 30; break;
+ case 't': numBits = 40; break;
+ default: return false;
+ }
+ if (number >= ((UInt64)1 << (64 - numBits)))
+ return false;
+ result = number << numBits;
+ return true;
+}
+
+static bool ParseTypeParams(const UString &s, COpenType &type)
+{
+ if (s[0] == 0)
+ return true;
+ if (s[1] == 0)
+ {
+ switch ((unsigned)(Byte)s[0])
+ {
+ case 'e': type.EachPos = true; return true;
+ case 'a': type.CanReturnArc = true; return true;
+ case 'r': type.Recursive = true; return true;
+ }
+ return false;
+ }
+ if (s[0] == 's')
+ {
+ UInt64 result;
+ if (!ParseComplexSize(s.Ptr(1), result))
+ return false;
+ type.MaxStartOffset = result;
+ type.MaxStartOffset_Defined = true;
+ return true;
+ }
+
+ return false;
+}
+
+bool ParseType(CCodecs &codecs, const UString &s, COpenType &type)
+{
+ int pos2 = s.Find(':');
+ UString name;
+ if (pos2 < 0)
+ {
+ name = s;
+ pos2 = s.Len();
+ }
+ else
+ {
+ name = s.Left(pos2);
+ pos2++;
+ }
+
+ int index = codecs.FindFormatForArchiveType(name);
+ type.Recursive = false;
+
+ if (index < 0)
+ {
+ if (name[0] == '*')
+ {
+ if (name[1] != 0)
+ return false;
+ }
+ else if (name[0] == '#')
+ {
+ if (name[1] != 0)
+ return false;
+ type.CanReturnArc = false;
+ type.CanReturnParser = true;
+ }
+ else
+ return false;
+ }
+
+ type.FormatIndex = index;
+
+ for (unsigned i = pos2; i < s.Len();)
+ {
+ int next = s.Find(':', i);
+ if (next < 0)
+ next = s.Len();
+ UString name = s.Mid(i, next - i);
+ if (name.IsEmpty())
+ return false;
+ if (!ParseTypeParams(name, type))
+ return false;
+ i = next + 1;
+ }
+
+ return true;
+}
+
+bool ParseOpenTypes(CCodecs &codecs, const UString &s, CObjectVector<COpenType> &types)
+{
+ types.Clear();
+ for (unsigned pos = 0; pos < s.Len();)
+ {
+ int pos2 = s.Find('.', pos);
+ if (pos2 < 0)
+ pos2 = s.Len();
+ UString name = s.Mid(pos, pos2 - pos);
+ if (name.IsEmpty())
+ return false;
+ COpenType type;
+ if (!ParseType(codecs, name, type))
+ return false;
+ types.Add(type);
+ pos = pos2 + 1;
+ }
+ return true;
+}
+
+#endif
diff --git a/src/libs/7zip/unix/CPP/7zip/UI/Common/OpenArchive.h b/src/libs/7zip/unix/CPP/7zip/UI/Common/OpenArchive.h
index 4a003ee63..f2a5ce9fe 100644
--- a/src/libs/7zip/unix/CPP/7zip/UI/Common/OpenArchive.h
+++ b/src/libs/7zip/unix/CPP/7zip/UI/Common/OpenArchive.h
@@ -3,49 +3,309 @@
#ifndef __OPEN_ARCHIVE_H
#define __OPEN_ARCHIVE_H
-#include "Common/MyString.h"
-
-#include "Windows/FileFind.h"
-
-#include "../../Archive/IArchive.h"
+#include "../../../Windows/PropVariant.h"
#include "ArchiveOpenCallback.h"
#include "LoadCodecs.h"
+#include "Property.h"
-HRESULT GetArchiveItemBoolProp(IInArchive *archive, UInt32 index, PROPID propID, bool &result);
-HRESULT IsArchiveItemFolder(IInArchive *archive, UInt32 index, bool &result);
+HRESULT Archive_GetItemBoolProp(IInArchive *arc, UInt32 index, PROPID propID, bool &result) throw();
+HRESULT Archive_IsItem_Folder(IInArchive *arc, UInt32 index, bool &result) throw();
+HRESULT Archive_IsItem_Aux(IInArchive *arc, UInt32 index, bool &result) throw();
+HRESULT Archive_IsItem_AltStream(IInArchive *arc, UInt32 index, bool &result) throw();
+HRESULT Archive_IsItem_Deleted(IInArchive *arc, UInt32 index, bool &deleted) throw();
-struct CArc
+/*
+struct COptionalOpenProperties
{
+ UString FormatName;
+ CObjectVector<CProperty> Props;
+};
+*/
+
+#ifdef _SFX
+#define OPEN_PROPS_DECL
+#else
+#define OPEN_PROPS_DECL const CObjectVector<CProperty> *props;
+// #define OPEN_PROPS_DECL , const CObjectVector<COptionalOpenProperties> *props
+#endif
+
+struct COpenSpecFlags
+{
+ // bool CanReturnFull;
+ bool CanReturnFrontal;
+ bool CanReturnTail;
+ bool CanReturnMid;
+
+ bool CanReturn_NonStart() const { return CanReturnTail || CanReturnMid; }
+
+ COpenSpecFlags():
+ // CanReturnFull(true),
+ CanReturnFrontal(false),
+ CanReturnTail(false),
+ CanReturnMid(false)
+ {}
+};
+
+struct COpenType
+{
+ int FormatIndex;
+
+ COpenSpecFlags SpecForcedType;
+ COpenSpecFlags SpecMainType;
+ COpenSpecFlags SpecWrongExt;
+ COpenSpecFlags SpecUnknownExt;
+
+ bool Recursive;
+
+ bool CanReturnArc;
+ bool CanReturnParser;
+ bool EachPos;
+
+ // bool SkipSfxStub;
+ // bool ExeAsUnknown;
+
+ bool ZerosTailIsAllowed;
+
+ bool MaxStartOffset_Defined;
+ UInt64 MaxStartOffset;
+
+ const COpenSpecFlags &GetSpec(bool isForced, bool isMain, bool isUnknown) const
+ {
+ return isForced ? SpecForcedType : (isMain ? SpecMainType : (isUnknown ? SpecUnknownExt : SpecWrongExt));
+ }
+
+ COpenType():
+ FormatIndex(-1),
+ Recursive(true),
+ CanReturnArc(true),
+ CanReturnParser(false),
+ EachPos(false),
+ // SkipSfxStub(true),
+ // ExeAsUnknown(true),
+ ZerosTailIsAllowed(false),
+ MaxStartOffset_Defined(false),
+ MaxStartOffset(0)
+ {
+ SpecForcedType.CanReturnFrontal = true;
+ SpecForcedType.CanReturnTail = true;
+ SpecForcedType.CanReturnMid = true;
+
+ SpecMainType.CanReturnFrontal = true;
+
+ SpecUnknownExt.CanReturnTail = true; // for sfx
+ SpecUnknownExt.CanReturnMid = true;
+ SpecUnknownExt.CanReturnFrontal = true; // for alt streams of sfx with pad
+
+ // ZerosTailIsAllowed = true;
+ }
+};
+
+struct COpenOptions
+{
+ CCodecs *codecs;
+ COpenType openType;
+ const CObjectVector<COpenType> *types;
+ const CIntVector *excludedFormats;
+
+ IInStream *stream;
+ ISequentialInStream *seqStream;
+ IArchiveOpenCallback *callback;
+ COpenCallbackImp *callbackSpec;
+ OPEN_PROPS_DECL
+ // bool openOnlySpecifiedByExtension,
+
+ bool stdInMode;
+ UString filePath;
+
+ COpenOptions():
+ codecs(NULL),
+ types(NULL),
+ excludedFormats(NULL),
+ stream(NULL),
+ seqStream(NULL),
+ callback(NULL),
+ callbackSpec(NULL),
+ stdInMode(false)
+ {}
+
+};
+
+UInt32 GetOpenArcErrorFlags(const NWindows::NCOM::CPropVariant &prop, bool *isDefinedProp = NULL);
+
+struct CArcErrorInfo
+{
+ bool ThereIsTail;
+ bool UnexpecedEnd;
+ bool IgnoreTail; // all are zeros
+ // bool NonZerosTail;
+ bool ErrorFlags_Defined;
+ UInt32 ErrorFlags;
+ UInt32 WarningFlags;
+ int ErrorFormatIndex; // - 1 means no Error.
+ // if FormatIndex == ErrorFormatIndex, the archive is open with offset
+ UInt64 TailSize;
+
+ /* if CArc is Open OK with some format:
+ - ErrorFormatIndex shows error format index, if extension is incorrect
+ - other variables show message and warnings of archive that is open */
+
+ UString ErrorMessage;
+ UString WarningMessage;
+
+ // call IsArc_After_NonOpen only if Open returns S_FALSE
+ bool IsArc_After_NonOpen() const
+ {
+ return (ErrorFlags_Defined && (ErrorFlags & kpv_ErrorFlags_IsNotArc) == 0);
+ }
+
+
+ CArcErrorInfo():
+ ThereIsTail(false),
+ UnexpecedEnd(false),
+ IgnoreTail(false),
+ // NonZerosTail(false),
+ ErrorFlags_Defined(false),
+ ErrorFlags(0),
+ WarningFlags(0),
+ ErrorFormatIndex(-1),
+ TailSize(0)
+ {}
+
+ void ClearErrors();
+
+ void ClearErrors_Full()
+ {
+ ErrorFormatIndex = -1;
+ ClearErrors();
+ }
+
+ bool IsThereErrorOrWarning() const
+ {
+ return ErrorFlags != 0
+ || WarningFlags != 0
+ || NeedTailWarning()
+ || UnexpecedEnd
+ || !ErrorMessage.IsEmpty()
+ || !WarningMessage.IsEmpty();
+ }
+
+ bool AreThereErrors() const { return ErrorFlags != 0 || UnexpecedEnd; }
+ bool AreThereWarnings() const { return WarningFlags != 0 || NeedTailWarning(); }
+
+ bool NeedTailWarning() const { return !IgnoreTail && ThereIsTail; }
+
+ UInt32 GetWarningFlags() const
+ {
+ UInt32 a = WarningFlags;
+ if (NeedTailWarning() && (ErrorFlags & kpv_ErrorFlags_DataAfterEnd) == 0)
+ a |= kpv_ErrorFlags_DataAfterEnd;
+ return a;
+ }
+
+ UInt32 GetErrorFlags() const
+ {
+ UInt32 a = ErrorFlags;
+ if (UnexpecedEnd)
+ a |= kpv_ErrorFlags_UnexpectedEnd;
+ return a;
+ }
+};
+
+class CArc
+{
+ HRESULT PrepareToOpen(const COpenOptions &op, unsigned formatIndex, CMyComPtr<IInArchive> &archive);
+ HRESULT CheckZerosTail(const COpenOptions &op, UInt64 offset);
+ HRESULT OpenStream2(const COpenOptions &options);
+
+public:
CMyComPtr<IInArchive> Archive;
+ CMyComPtr<IInStream> InStream;
+ // we use InStream in 2 cases (ArcStreamOffset != 0):
+ // 1) if we use additional cache stream
+ // 2) we reopen sfx archive with CTailInStream
+
+ CMyComPtr<IArchiveGetRawProps> GetRawProps;
+ CMyComPtr<IArchiveGetRootProps> GetRootProps;
+
+ CArcErrorInfo ErrorInfo; // for OK archives
+ CArcErrorInfo NonOpen_ErrorInfo; // ErrorInfo for mainArchive (false OPEN)
+
UString Path;
+ UString filePath;
UString DefaultName;
- int FormatIndex;
+ int FormatIndex; // - 1 means Parser.
int SubfileIndex;
FILETIME MTime;
bool MTimeDefined;
- UString ErrorMessage;
- CArc(): MTimeDefined(false) {}
+ Int64 Offset; // it's offset of start of archive inside stream that is open by Archive Handler
+ UInt64 PhySize;
+ // UInt64 OkPhySize;
+ bool PhySizeDefined;
+ // bool OkPhySize_Defined;
+ UInt64 FileSize;
+ UInt64 AvailPhySize; // PhySize, but it's reduced if exceed end of file
+ // bool offsetDefined;
+
+ UInt64 ArcStreamOffset; // offset of stream that is open by Archive Handler
+ Int64 GetGlobalOffset() const { return ArcStreamOffset + Offset; } // it's global offset of archive
+
+ // AString ErrorFlagsText;
+
+ bool IsParseArc;
+
+ bool IsTree;
+
+ bool Ask_Deleted;
+ bool Ask_AltStream;
+ bool Ask_Aux;
+ bool Ask_INode;
+
+ bool IgnoreSplit; // don't try split handler
+
+ // void Set_ErrorFlagsText();
+
+ CArc():
+ MTimeDefined(false),
+ IsTree(false),
+ Ask_Deleted(false),
+ Ask_AltStream(false),
+ Ask_Aux(false),
+ Ask_INode(false),
+ IgnoreSplit(false)
+ {}
+
+ HRESULT ReadBasicProps(IInArchive *archive, UInt64 startPos, HRESULT openRes);
+
+ // ~CArc();
+
+ HRESULT Close()
+ {
+ InStream.Release();
+ return Archive->Close();
+ }
+
+ // AltStream's name is concatenated with base file name in one string in parts.Back()
+ HRESULT GetItemPathToParent(UInt32 index, UInt32 parent, UStringVector &parts) const;
HRESULT GetItemPath(UInt32 index, UString &result) const;
+
+ // GetItemPath2 adds [DELETED] dir prefix for deleted items.
+ HRESULT GetItemPath2(UInt32 index, UString &result) const;
+
+ HRESULT GetItemSize(UInt32 index, UInt64 &size, bool &defined) const;
HRESULT GetItemMTime(UInt32 index, FILETIME &ft, bool &defined) const;
HRESULT IsItemAnti(UInt32 index, bool &result) const
- { return GetArchiveItemBoolProp(Archive, index, kpidIsAnti, result); }
-
- HRESULT OpenStream(
- CCodecs *codecs,
- int formatIndex,
- IInStream *stream,
- ISequentialInStream *seqStream,
- IArchiveOpenCallback *callback);
-
- HRESULT OpenStreamOrFile(
- CCodecs *codecs,
- int formatIndex,
- bool stdInMode,
- IInStream *stream,
- IArchiveOpenCallback *callback);
+ { return Archive_GetItemBoolProp(Archive, index, kpidIsAnti, result); }
+
+
+ HRESULT OpenStream(const COpenOptions &options);
+ HRESULT OpenStreamOrFile(COpenOptions &options);
+
+ HRESULT ReOpen(const COpenOptions &options);
+
+ HRESULT CreateNewTailStream(CMyComPtr<IInStream> &stream);
};
struct CArchiveLink
@@ -55,33 +315,32 @@ struct CArchiveLink
UInt64 VolumesSize;
bool IsOpen;
+ // int NonOpenErrorFormatIndex; // - 1 means no Error.
+ UString NonOpen_ArcPath;
+
+ CArcErrorInfo NonOpen_ErrorInfo;
+
+ // UString ErrorsText;
+ // void Set_ErrorsText();
+
CArchiveLink(): VolumesSize(0), IsOpen(false) {}
+ void KeepModeForNextOpen();
HRESULT Close();
void Release();
~CArchiveLink() { Release(); }
+ const CArc *GetArc() const { return &Arcs.Back(); }
IInArchive *GetArchive() const { return Arcs.Back().Archive; }
+ IArchiveGetRawProps *GetArchiveGetRawProps() const { return Arcs.Back().GetRawProps; }
+ IArchiveGetRootProps *GetArchiveGetRootProps() const { return Arcs.Back().GetRootProps; }
+
+ HRESULT Open(COpenOptions &options);
- HRESULT Open(
- CCodecs *codecs,
- const CIntVector &formatIndices,
- bool stdInMode,
- IInStream *stream,
- const UString &filePath,
- IArchiveOpenCallback *callback);
-
- HRESULT Open2(
- CCodecs *codecs,
- const CIntVector &formatIndices,
- bool stdInMode,
- IInStream *stream,
- const UString &filePath,
- IOpenCallbackUI *callbackUI);
-
- HRESULT ReOpen(
- CCodecs *codecs,
- const UString &filePath,
- IArchiveOpenCallback *callback);
+ HRESULT Open2(COpenOptions &options, IOpenCallbackUI *callbackUI);
+
+ HRESULT ReOpen(COpenOptions &options);
};
+bool ParseOpenTypes(CCodecs &codecs, const UString &s, CObjectVector<COpenType> &types);
+
#endif
diff --git a/src/libs/7zip/unix/CPP/7zip/UI/Common/PropIDUtils.cpp b/src/libs/7zip/unix/CPP/7zip/UI/Common/PropIDUtils.cpp
index dacaca5f9..5ba8c7a89 100644
--- a/src/libs/7zip/unix/CPP/7zip/UI/Common/PropIDUtils.cpp
+++ b/src/libs/7zip/unix/CPP/7zip/UI/Common/PropIDUtils.cpp
@@ -2,33 +2,29 @@
#include "StdAfx.h"
-#include "Common/IntToString.h"
+#include "../../../../C/CpuArch.h"
-#include "Windows/FileFind.h"
-#include "Windows/PropVariantConversions.h"
+#include "../../../Common/IntToString.h"
+#include "../../../Common/StringConvert.h"
+
+#include "../../../Windows/FileFind.h"
+#include "../../../Windows/FileIO.h"
+#include "../../../Windows/PropVariantConv.h"
#include "../../PropID.h"
#include "PropIDUtils.h"
-using namespace NWindows;
+#define Get16(x) GetUi16(x)
+#define Get32(x) GetUi32(x)
-void ConvertUInt32ToHex(UInt32 value, wchar_t *s)
-{
- for (int i = 0; i < 8; i++)
- {
- int t = value & 0xF;
- value >>= 4;
- s[7 - i] = (wchar_t)((t < 10) ? (L'0' + t) : (L'A' + (t - 10)));
- }
- s[8] = L'\0';
-}
+using namespace NWindows;
-static const char g_WinAttrib[17] = "RHS8DAdNTsrCOnE_";
+static const char g_WinAttribChars[16 + 1] = "RHS8DAdNTsLCOnE_";
/*
0 READONLY
1 HIDDEN
-3 SYSTEM
+2 SYSTEM
4 DIRECTORY
5 ARCHIVE
@@ -45,46 +41,45 @@ static const char g_WinAttrib[17] = "RHS8DAdNTsrCOnE_";
16 VIRTUAL
*/
+void ConvertWinAttribToString(char *s, UInt32 wa)
+{
+ for (int i = 0; i < 16; i++)
+ if ((wa & (1 << i)) && i != 7)
+ *s++ = g_WinAttribChars[i];
+ *s = 0;
+}
+
static const char kPosixTypes[16] = { '0', 'p', 'c', '3', 'd', '5', 'b', '7', '-', '9', 'l', 'B', 's', 'D', 'E', 'F' };
-#define MY_ATTR_CHAR(a, n, c) ((a )& (1 << (n))) ? c : L'-';
+#define MY_ATTR_CHAR(a, n, c) ((a) & (1 << (n))) ? c : '-';
-UString ConvertPropertyToString(const PROPVARIANT &prop, PROPID propID, bool full)
+void ConvertPropertyToShortString(char *dest, const PROPVARIANT &prop, PROPID propID, bool full) throw()
{
- switch(propID)
+ *dest = 0;
+ if (prop.vt == VT_FILETIME)
+ {
+ FILETIME localFileTime;
+ if ((prop.filetime.dwHighDateTime == 0 &&
+ prop.filetime.dwLowDateTime == 0) ||
+ !::FileTimeToLocalFileTime(&prop.filetime, &localFileTime))
+ return;
+ ConvertFileTimeToString(localFileTime, dest, true, full);
+ return;
+ }
+ switch (propID)
{
- case kpidCTime:
- case kpidATime:
- case kpidMTime:
- {
- if (prop.vt != VT_FILETIME)
- break;
- FILETIME localFileTime;
- if ((prop.filetime.dwHighDateTime == 0 &&
- prop.filetime.dwLowDateTime == 0) ||
- !::FileTimeToLocalFileTime(&prop.filetime, &localFileTime))
- return UString();
- return ConvertFileTimeToString(localFileTime, true, full);
- }
case kpidCRC:
{
if (prop.vt != VT_UI4)
break;
- wchar_t temp[12];
- ConvertUInt32ToHex(prop.ulVal, temp);
- return temp;
+ ConvertUInt32ToHex8Digits(prop.ulVal, dest);
+ return;
}
case kpidAttrib:
{
if (prop.vt != VT_UI4)
break;
- UInt32 a = prop.ulVal;
- wchar_t sz[32];
- int pos = 0;
- for (int i = 0; i < 16; i++)
- if (a & (1 << i) && i != 7)
- sz[pos++] = g_WinAttrib[i];
- sz[pos] = '\0';
- return sz;
+ ConvertWinAttribToString(dest, prop.ulVal);
+ return;
}
case kpidPosixAttrib:
{
@@ -92,29 +87,469 @@ UString ConvertPropertyToString(const PROPVARIANT &prop, PROPID propID, bool ful
break;
UString res;
UInt32 a = prop.ulVal;
- wchar_t temp[16];
- temp[0] = kPosixTypes[(a >> 12) & 0xF];
+ dest[0] = kPosixTypes[(a >> 12) & 0xF];
for (int i = 6; i >= 0; i -= 3)
{
- temp[7 - i] = MY_ATTR_CHAR(a, i + 2, L'r');
- temp[8 - i] = MY_ATTR_CHAR(a, i + 1, L'w');
- temp[9 - i] = MY_ATTR_CHAR(a, i + 0, L'x');
+ dest[7 - i] = MY_ATTR_CHAR(a, i + 2, 'r');
+ dest[8 - i] = MY_ATTR_CHAR(a, i + 1, 'w');
+ dest[9 - i] = MY_ATTR_CHAR(a, i + 0, 'x');
}
- if ((a & 0x800) != 0) temp[3] = ((a & (1 << 6)) ? 's' : 'S');
- if ((a & 0x400) != 0) temp[6] = ((a & (1 << 3)) ? 's' : 'S');
- if ((a & 0x200) != 0) temp[9] = ((a & (1 << 0)) ? 't' : 'T');
- temp[10] = 0;
- res = temp;
+ if ((a & 0x800) != 0) dest[3] = ((a & (1 << 6)) ? 's' : 'S');
+ if ((a & 0x400) != 0) dest[6] = ((a & (1 << 3)) ? 's' : 'S');
+ if ((a & 0x200) != 0) dest[9] = ((a & (1 << 0)) ? 't' : 'T');
+ dest[10] = 0;
a &= ~(UInt32)0xFFFF;
if (a != 0)
{
- ConvertUInt32ToHex(a, temp);
- res = UString(temp) + L' ' + res;
+ dest[10] = ' ';
+ ConvertUInt32ToHex8Digits(a, dest + 11);
+ }
+ return;
+ }
+ case kpidINode:
+ {
+ if (prop.vt != VT_UI8)
+ break;
+ ConvertUInt32ToString((UInt32)(prop.uhVal.QuadPart >> 48), dest);
+ dest += strlen(dest);
+ *dest++ = '-';
+ UInt64 low = prop.uhVal.QuadPart & (((UInt64)1 << 48) - 1);
+ ConvertUInt64ToString(low, dest);
+ return;
+ }
+ case kpidVa:
+ {
+ UInt64 v = 0;
+ if (ConvertPropVariantToUInt64(prop, v))
+ {
+ dest[0] = '0';
+ dest[1] = 'x';
+ ConvertUInt64ToHex(prop.ulVal, dest + 2);
+ return;
+ }
+ break;
+ }
+ }
+ ConvertPropVariantToShortString(prop, dest);
+}
+
+void ConvertPropertyToString(UString &dest, const PROPVARIANT &prop, PROPID propID, bool full)
+{
+ if (prop.vt == VT_BSTR)
+ {
+ dest = prop.bstrVal;
+ return;
+ }
+ char temp[64];
+ ConvertPropertyToShortString(temp, prop, propID, full);
+ int len = MyStringLen(temp);
+ wchar_t *str = dest.GetBuffer(len);
+ for (int i = 0; i < len; i++)
+ str[i] = temp[i];
+ dest.ReleaseBuffer(len);
+}
+
+static inline char GetHex(Byte value)
+{
+ return (char)((value < 10) ? ('0' + value) : ('A' + (value - 10)));
+}
+
+#ifndef _SFX
+
+static inline void AddHexToString(AString &res, Byte value)
+{
+ res += GetHex((Byte)(value >> 4));
+ res += GetHex((Byte)(value & 0xF));
+ res += ' ';
+}
+
+/*
+static AString Data_To_Hex(const Byte *data, size_t size)
+{
+ AString s;
+ for (size_t i = 0; i < size; i++)
+ AddHexToString(s, data[i]);
+ return s;
+}
+*/
+
+static const char *sidNames[] =
+{
+ "0",
+ "Dialup",
+ "Network",
+ "Batch",
+ "Interactive",
+ "Logon", // S-1-5-5-X-Y
+ "Service",
+ "Anonymous",
+ "Proxy",
+ "EnterpriseDC",
+ "Self",
+ "AuthenticatedUsers",
+ "RestrictedCode",
+ "TerminalServer",
+ "RemoteInteractiveLogon",
+ "ThisOrganization",
+ "16",
+ "IUserIIS",
+ "LocalSystem",
+ "LocalService",
+ "NetworkService",
+ "Domains"
+};
+
+struct CSecID2Name
+{
+ UInt32 n;
+ const char *sz;
+};
+
+const CSecID2Name sid_32_Names[] =
+{
+ { 544, "Administrators" },
+ { 545, "Users" },
+ { 546, "Guests" },
+ { 547, "PowerUsers" },
+ { 548, "AccountOperators" },
+ { 549, "ServerOperators" },
+ { 550, "PrintOperators" },
+ { 551, "BackupOperators" },
+ { 552, "Replicators" },
+ { 553, "Backup Operators" },
+ { 554, "PreWindows2000CompatibleAccess" },
+ { 555, "RemoteDesktopUsers" },
+ { 556, "NetworkConfigurationOperators" },
+ { 557, "IncomingForestTrustBuilders" },
+ { 558, "PerformanceMonitorUsers" },
+ { 559, "PerformanceLogUsers" },
+ { 560, "WindowsAuthorizationAccessGroup" },
+ { 561, "TerminalServerLicenseServers" },
+ { 562, "DistributedCOMUsers" },
+ { 569, "CryptographicOperators" },
+ { 573, "EventLogReaders" },
+ { 574, "CertificateServiceDCOMAccess" }
+};
+
+static const CSecID2Name sid_21_Names[] =
+{
+ { 500, "Administrator" },
+ { 501, "Guest" },
+ { 502, "KRBTGT" },
+ { 512, "DomainAdmins" },
+ { 513, "DomainUsers" },
+ { 515, "DomainComputers" },
+ { 516, "DomainControllers" },
+ { 517, "CertPublishers" },
+ { 518, "SchemaAdmins" },
+ { 519, "EnterpriseAdmins" },
+ { 520, "GroupPolicyCreatorOwners" },
+ { 553, "RASandIASServers" },
+ { 553, "RASandIASServers" },
+ { 571, "AllowedRODCPasswordReplicationGroup" },
+ { 572, "DeniedRODCPasswordReplicationGroup" }
+};
+
+struct CServicesToName
+{
+ UInt32 n[5];
+ const char *sz;
+};
+
+static const CServicesToName services_to_name[] =
+{
+ { { 0x38FB89B5, 0xCBC28419, 0x6D236C5C, 0x6E770057, 0x876402C0 } , "TrustedInstaller" }
+};
+
+static void ParseSid(AString &s, const Byte *p, UInt32 lim, UInt32 &sidSize)
+{
+ sidSize = 0;
+ if (lim < 8)
+ {
+ s += "ERROR";
+ return;
+ }
+ UInt32 rev = p[0];
+ if (rev != 1)
+ {
+ s += "UNSUPPORTED";
+ return;
+ }
+ UInt32 num = p[1];
+ if (8 + num * 4 > lim)
+ {
+ s += "ERROR";
+ return;
+ }
+ sidSize = 8 + num * 4;
+ UInt32 authority = GetBe32(p + 4);
+
+ if (p[2] == 0 && p[3] == 0 && authority == 5 && num >= 1)
+ {
+ UInt32 v0 = Get32(p + 8);
+ if (v0 < ARRAY_SIZE(sidNames))
+ {
+ s += sidNames[v0];
+ return;
+ }
+ if (v0 == 32 && num == 2)
+ {
+ UInt32 v1 = Get32(p + 12);
+ for (int i = 0; i < ARRAY_SIZE(sid_32_Names); i++)
+ if (sid_32_Names[i].n == v1)
+ {
+ s += sid_32_Names[i].sz;
+ return;
+ }
+ }
+ if (v0 == 21 && num == 5)
+ {
+ UInt32 v4 = Get32(p + 8 + 4 * 4);
+ for (int i = 0; i < ARRAY_SIZE(sid_21_Names); i++)
+ if (sid_21_Names[i].n == v4)
+ {
+ s += sid_21_Names[i].sz;
+ return;
+ }
+ }
+ if (v0 == 80 && num == 6)
+ {
+ for (int i = 0; i < ARRAY_SIZE(services_to_name); i++)
+ {
+ const CServicesToName &sn = services_to_name[i];
+ int j;
+ for (j = 0; j < 5 && sn.n[j] == Get32(p + 8 + 4 + j * 4); j++);
+ if (j == 5)
+ {
+ s += sn.sz;
+ return;
+ }
}
- return res;
}
}
- return ConvertPropVariantToString(prop);
+
+ char sz[16];
+ s += "S-1-";
+ if (p[2] == 0 && p[3] == 0)
+ {
+ ConvertUInt32ToString(authority, sz);
+ s += sz;
+ }
+ else
+ {
+ s += "0x";
+ for (int i = 2; i < 8; i++)
+ AddHexToString(s, p[i]);
+ }
+ for (UInt32 i = 0; i < num; i++)
+ {
+ s += '-';
+ ConvertUInt32ToString(Get32(p + 8 + i * 4), sz);
+ s += sz;
+ }
+}
+
+static void ParseOwner(AString &s, const Byte *p, UInt32 size, UInt32 pos)
+{
+ if (pos > size)
+ {
+ s += "ERROR";
+ return;
+ }
+ UInt32 sidSize = 0;
+ ParseSid(s, p + pos, size - pos, sidSize);
+}
+
+static void AddUInt32ToString(AString &s, UInt32 val)
+{
+ char sz[16];
+ ConvertUInt32ToString(val, sz);
+ s += sz;
+}
+
+static void ParseAcl(AString &s, const Byte *p, UInt32 size, const char *strName, UInt32 flags, UInt32 offset)
+{
+ UInt32 control = Get16(p + 2);
+ if ((flags & control) == 0)
+ return;
+ UInt32 pos = Get32(p + offset);
+ s += ' ';
+ s += strName;
+ if (pos >= size)
+ return;
+ p += pos;
+ size -= pos;
+ if (size < 8)
+ return;
+ if (Get16(p) != 2) // revision
+ return;
+ // UInt32 aclSize = Get16(p + 2);
+ UInt32 num = Get32(p + 4);
+ AddUInt32ToString(s, num);
+ /*
+ if (num >= (1 << 16))
+ return;
+ if (aclSize > size)
+ return;
+ size = aclSize;
+ size -= 8;
+ p += 8;
+ for (UInt32 i = 0 ; i < num; i++)
+ {
+ if (size <= 8)
+ return;
+ // Byte type = p[0];
+ // Byte flags = p[1];
+ // UInt32 aceSize = Get16(p + 2);
+ // UInt32 mask = Get32(p + 4);
+ p += 8;
+ size -= 8;
+
+ UInt32 sidSize = 0;
+ s += ' ';
+ s += ParseSid(p, size, sidSize);
+ if (sidSize == 0)
+ return;
+ p += sidSize;
+ size -= sidSize;
+ }
+ if (size != 0)
+ s += " ERROR";
+ */
+}
+
+#define MY_SE_OWNER_DEFAULTED (0x0001)
+#define MY_SE_GROUP_DEFAULTED (0x0002)
+#define MY_SE_DACL_PRESENT (0x0004)
+#define MY_SE_DACL_DEFAULTED (0x0008)
+#define MY_SE_SACL_PRESENT (0x0010)
+#define MY_SE_SACL_DEFAULTED (0x0020)
+#define MY_SE_DACL_AUTO_INHERIT_REQ (0x0100)
+#define MY_SE_SACL_AUTO_INHERIT_REQ (0x0200)
+#define MY_SE_DACL_AUTO_INHERITED (0x0400)
+#define MY_SE_SACL_AUTO_INHERITED (0x0800)
+#define MY_SE_DACL_PROTECTED (0x1000)
+#define MY_SE_SACL_PROTECTED (0x2000)
+#define MY_SE_RM_CONTROL_VALID (0x4000)
+#define MY_SE_SELF_RELATIVE (0x8000)
+
+void ConvertNtSecureToString(const Byte *data, UInt32 size, AString &s)
+{
+ s.Empty();
+ if (size < 20 || size > (1 << 18))
+ {
+ s += "ERROR";
+ return;
+ }
+ if (Get16(data) != 1) // revision
+ {
+ s += "UNSUPPORTED";
+ return;
+ }
+ ParseOwner(s, data, size, Get32(data + 4));
+ s += ' ';
+ ParseOwner(s, data, size, Get32(data + 8));
+ ParseAcl(s, data, size, "s:", MY_SE_SACL_PRESENT, 12);
+ ParseAcl(s, data, size, "d:", MY_SE_DACL_PRESENT, 16);
+ s += ' ';
+ AddUInt32ToString(s, size);
+ // s += '\n';
+ // s += Data_To_Hex(data, size);
+}
+
+#ifdef _WIN32
+
+static bool CheckSid(const Byte *data, UInt32 size, UInt32 pos)
+{
+ if (pos >= size)
+ return false;
+ size -= pos;
+ if (size < 8)
+ return false;
+ UInt32 rev = data[pos];
+ if (rev != 1)
+ return false;
+ UInt32 num = data[pos + 1];
+ return (8 + num * 4 <= size);
+}
+
+static bool CheckAcl(const Byte *p, UInt32 size, UInt32 flags, UInt32 offset)
+{
+ UInt32 control = Get16(p + 2);
+ if ((flags & control) == 0)
+ return true;
+ UInt32 pos = Get32(p + offset);
+ if (pos >= size)
+ return false;
+ p += pos;
+ size -= pos;
+ if (size < 8)
+ return false;
+ UInt32 aclSize = Get16(p + 2);
+ return (aclSize <= size);
+}
+
+bool CheckNtSecure(const Byte *data, UInt32 size)
+{
+ if (size < 20)
+ return false;
+ if (Get16(data) != 1) // revision
+ return true; // windows function can handle such error, so we allow it
+ if (size > (1 << 18))
+ return false;
+ if (!CheckSid(data, size, Get32(data + 4))) return false;
+ if (!CheckSid(data, size, Get32(data + 8))) return false;
+ if (!CheckAcl(data, size, MY_SE_SACL_PRESENT, 12)) return false;
+ if (!CheckAcl(data, size, MY_SE_DACL_PRESENT, 16)) return false;
+ return true;
+}
+
+#endif
+
+#ifdef _WIN32
+bool ConvertNtReparseToString(const Byte *data, UInt32 size, UString &s)
+{
+ s.Empty();
+ NFile::CReparseAttr attr;
+ if (attr.Parse(data, size))
+ {
+ if (!attr.IsSymLink())
+ s += L"Junction: ";
+ s += attr.GetPath();
+ if (!attr.IsOkNamePair())
+ {
+ s += L" : ";
+ s += attr.PrintName;
+ }
+ return true;
+ }
+
+ if (size < 8)
+ return false;
+ UInt32 tag = Get32(data);
+ UInt32 len = Get16(data + 4);
+ if (len + 8 > size)
+ return false;
+ if (Get16(data + 6) != 0) // padding
+ return false;
+
+ char hex[16];
+ ConvertUInt32ToHex8Digits(tag, hex);
+ s.AddAsciiStr(hex);
+ s += L' ';
+
+ data += 8;
+
+ for (UInt32 i = 0; i < len; i++)
+ {
+ Byte b = ((const Byte *)data)[i];
+ s += (wchar_t)GetHex((Byte)((b >> 4) & 0xF));
+ s += (wchar_t)GetHex((Byte)(b & 0xF));
+ }
+ return true;
}
+#endif
+
+#endif
diff --git a/src/libs/7zip/unix/CPP/7zip/UI/Common/PropIDUtils.h b/src/libs/7zip/unix/CPP/7zip/UI/Common/PropIDUtils.h
index ca14d091d..3ee2981de 100644
--- a/src/libs/7zip/unix/CPP/7zip/UI/Common/PropIDUtils.h
+++ b/src/libs/7zip/unix/CPP/7zip/UI/Common/PropIDUtils.h
@@ -3,10 +3,15 @@
#ifndef __PROPID_UTILS_H
#define __PROPID_UTILS_H
-#include "Common/MyString.h"
-#include "Common/Types.h"
+#include "../../../Common/MyString.h"
-void ConvertUInt32ToHex(UInt32 value, wchar_t *s);
-UString ConvertPropertyToString(const PROPVARIANT &propVariant, PROPID propID, bool full = true);
+// provide at least 64 bytes for buffer including zero-end
+void ConvertPropertyToShortString(char *dest, const PROPVARIANT &propVariant, PROPID propID, bool full = true) throw();
+void ConvertPropertyToString(UString &dest, const PROPVARIANT &propVariant, PROPID propID, bool full = true);
+
+bool ConvertNtReparseToString(const Byte *data, UInt32 size, UString &s);
+void ConvertNtSecureToString(const Byte *data, UInt32 size, AString &s);
+bool CheckNtSecure(const Byte *data, UInt32 size);
+void ConvertWinAttribToString(char *s, UInt32 wa);
#endif
diff --git a/src/libs/7zip/unix/CPP/7zip/UI/Common/Property.h b/src/libs/7zip/unix/CPP/7zip/UI/Common/Property.h
index 9fd340cbc..8b57a2a64 100644
--- a/src/libs/7zip/unix/CPP/7zip/UI/Common/Property.h
+++ b/src/libs/7zip/unix/CPP/7zip/UI/Common/Property.h
@@ -1,9 +1,9 @@
// Property.h
-#ifndef __PROPERTY_H
-#define __PROPERTY_H
+#ifndef __7Z_PROPERTY_H
+#define __7Z_PROPERTY_H
-#include "Common/MyString.h"
+#include "../../../Common/MyString.h"
struct CProperty
{
diff --git a/src/libs/7zip/unix/CPP/7zip/UI/Common/SetProperties.cpp b/src/libs/7zip/unix/CPP/7zip/UI/Common/SetProperties.cpp
index 4827f2a78..64b9d92a6 100644
--- a/src/libs/7zip/unix/CPP/7zip/UI/Common/SetProperties.cpp
+++ b/src/libs/7zip/unix/CPP/7zip/UI/Common/SetProperties.cpp
@@ -2,25 +2,26 @@
#include "StdAfx.h"
-#include "SetProperties.h"
+#include "../../../Common/MyCom.h"
+#include "../../../Common/MyString.h"
+#include "../../../Common/StringToInt.h"
-#include "Windows/PropVariant.h"
-#include "Common/MyString.h"
-#include "Common/StringToInt.h"
-#include "Common/MyCom.h"
+#include "../../../Windows/PropVariant.h"
#include "../../Archive/IArchive.h"
+#include "SetProperties.h"
+
using namespace NWindows;
using namespace NCOM;
static void ParseNumberString(const UString &s, NCOM::CPropVariant &prop)
{
- const wchar_t *endPtr;
- UInt64 result = ConvertStringToUInt64(s, &endPtr);
- if (endPtr - (const wchar_t *)s != s.Length())
+ const wchar_t *end;
+ UInt64 result = ConvertStringToUInt64(s, &end);
+ if (*end != 0 || s.IsEmpty())
prop = s;
- else if (result <= 0xFFFFFFFF)
+ else if (result <= (UInt32)0xFFFFFFFF)
prop = (UInt32)result;
else
prop = result;
@@ -39,8 +40,8 @@ HRESULT SetProperties(IUnknown *unknown, const CObjectVector<CProperty> &propert
CPropVariant *values = new CPropVariant[properties.Size()];
try
{
- int i;
- for(i = 0; i < properties.Size(); i++)
+ unsigned i;
+ for (i = 0; i < properties.Size(); i++)
{
const CProperty &property = properties[i];
NCOM::CPropVariant propVariant;
@@ -49,13 +50,13 @@ HRESULT SetProperties(IUnknown *unknown, const CObjectVector<CProperty> &propert
{
if (!name.IsEmpty())
{
- wchar_t c = name[name.Length() - 1];
+ wchar_t c = name.Back();
if (c == L'-')
propVariant = false;
else if (c == L'+')
propVariant = true;
if (propVariant.vt != VT_EMPTY)
- name = name.Left(name.Length() - 1);
+ name.DeleteBack();
}
}
else
@@ -64,9 +65,9 @@ HRESULT SetProperties(IUnknown *unknown, const CObjectVector<CProperty> &propert
values[i] = propVariant;
}
CRecordVector<const wchar_t *> names;
- for(i = 0; i < realNames.Size(); i++)
+ for (i = 0; i < realNames.Size(); i++)
names.Add((const wchar_t *)realNames[i]);
-
+
RINOK(setProperties->SetProperties(&names.Front(), values, names.Size()));
}
catch(...)
diff --git a/src/libs/7zip/unix/CPP/7zip/UI/Common/SortUtils.cpp b/src/libs/7zip/unix/CPP/7zip/UI/Common/SortUtils.cpp
index 061e77730..b7e422a29 100644
--- a/src/libs/7zip/unix/CPP/7zip/UI/Common/SortUtils.cpp
+++ b/src/libs/7zip/unix/CPP/7zip/UI/Common/SortUtils.cpp
@@ -2,21 +2,22 @@
#include "StdAfx.h"
+#include "../../../Common/Wildcard.h"
+
#include "SortUtils.h"
-#include "Common/Wildcard.h"
-static int CompareStrings(const int *p1, const int *p2, void *param)
+static int CompareStrings(const unsigned *p1, const unsigned *p2, void *param)
{
const UStringVector &strings = *(const UStringVector *)param;
return CompareFileNames(strings[*p1], strings[*p2]);
}
-void SortFileNames(const UStringVector &strings, CIntVector &indices)
+void SortFileNames(const UStringVector &strings, CUIntVector &indices)
{
- indices.Clear();
- int numItems = strings.Size();
- indices.Reserve(numItems);
- for(int i = 0; i < numItems; i++)
- indices.Add(i);
+ unsigned numItems = strings.Size();
+ indices.ClearAndSetSize(numItems);
+ unsigned *vals = &indices[0];
+ for (unsigned i = 0; i < numItems; i++)
+ vals[i] = i;
indices.Sort(CompareStrings, (void *)&strings);
}
diff --git a/src/libs/7zip/unix/CPP/7zip/UI/Common/SortUtils.h b/src/libs/7zip/unix/CPP/7zip/UI/Common/SortUtils.h
index e15224611..8e42e0682 100644
--- a/src/libs/7zip/unix/CPP/7zip/UI/Common/SortUtils.h
+++ b/src/libs/7zip/unix/CPP/7zip/UI/Common/SortUtils.h
@@ -1,10 +1,10 @@
// SortUtils.h
-#ifndef __SORTUTLS_H
-#define __SORTUTLS_H
+#ifndef __SORT_UTLS_H
+#define __SORT_UTLS_H
-#include "Common/MyString.h"
+#include "../../../Common/MyString.h"
-void SortFileNames(const UStringVector &strings, CIntVector &indices);
+void SortFileNames(const UStringVector &strings, CUIntVector &indices);
#endif
diff --git a/src/libs/7zip/unix/CPP/7zip/UI/Common/TempFiles.cpp b/src/libs/7zip/unix/CPP/7zip/UI/Common/TempFiles.cpp
index eeaec1802..0c13ae158 100644
--- a/src/libs/7zip/unix/CPP/7zip/UI/Common/TempFiles.cpp
+++ b/src/libs/7zip/unix/CPP/7zip/UI/Common/TempFiles.cpp
@@ -2,19 +2,18 @@
#include "StdAfx.h"
-#include "TempFiles.h"
+#include "../../../Windows/FileDir.h"
-#include "Windows/FileDir.h"
-#include "Windows/FileIO.h"
+#include "TempFiles.h"
using namespace NWindows;
using namespace NFile;
void CTempFiles::Clear()
{
- while(!Paths.IsEmpty())
+ while (!Paths.IsEmpty())
{
- NDirectory::DeleteFileAlways((LPCWSTR)Paths.Back());
+ NDir::DeleteFileAlways(Paths.Back());
Paths.DeleteBack();
}
}
diff --git a/src/libs/7zip/unix/CPP/7zip/UI/Common/TempFiles.h b/src/libs/7zip/unix/CPP/7zip/UI/Common/TempFiles.h
index eb474a760..4099e6558 100644
--- a/src/libs/7zip/unix/CPP/7zip/UI/Common/TempFiles.h
+++ b/src/libs/7zip/unix/CPP/7zip/UI/Common/TempFiles.h
@@ -1,15 +1,15 @@
// TempFiles.h
-#ifndef __TEMPFILES_H
-#define __TEMPFILES_H
+#ifndef __TEMP_FILES_H
+#define __TEMP_FILES_H
-#include "Common/MyString.h"
+#include "../../../Common/MyString.h"
class CTempFiles
{
void Clear();
public:
- UStringVector Paths;
+ FStringVector Paths;
~CTempFiles() { Clear(); }
};
diff --git a/src/libs/7zip/unix/CPP/7zip/UI/Common/Update.cpp b/src/libs/7zip/unix/CPP/7zip/UI/Common/Update.cpp
index a5db3c18e..4697dca46 100644
--- a/src/libs/7zip/unix/CPP/7zip/UI/Common/Update.cpp
+++ b/src/libs/7zip/unix/CPP/7zip/UI/Common/Update.cpp
@@ -4,21 +4,19 @@
#include "Update.h"
-#include "Common/IntToString.h"
-#include "Common/StringConvert.h"
+#include "../../../Common/IntToString.h"
+#include "../../../Common/StringConvert.h"
-#ifdef _WIN32
-#include "Windows/DLL.h"
-#endif
-
-#include "Windows/FileDir.h"
-#include "Windows/FileFind.h"
-#include "Windows/FileName.h"
-#include "Windows/PropVariant.h"
-#include "Windows/PropVariantConversions.h"
-#include "Windows/Time.h"
+#include "../../../Windows/DLL.h"
+#include "../../../Windows/FileDir.h"
+#include "../../../Windows/FileFind.h"
+#include "../../../Windows/FileName.h"
+#include "../../../Windows/PropVariant.h"
+#include "../../../Windows/PropVariantConv.h"
+#include "../../../Windows/TimeUtils.h"
#include "../../Common/FileStreams.h"
+#include "../../Common/LimitedStreams.h"
#include "../../Compress/CopyCoder.h"
@@ -38,36 +36,71 @@ static const char *kUpdateIsNotSupoorted =
using namespace NWindows;
using namespace NCOM;
using namespace NFile;
+using namespace NDir;
using namespace NName;
-#ifdef _WIN32
-static const wchar_t *kTempFolderPrefix = L"7zE";
+static CFSTR kTempFolderPrefix = FTEXT("7zE");
+
+#ifdef ENV_UNIX
+FString GetModuleDirPrefix()
+{
+ FString s;
+
+ const char *p7zip_home_dir = getenv("P7ZIP_HOME_DIR");
+ if (p7zip_home_dir) {
+ return MultiByteToUnicodeString(p7zip_home_dir,CP_ACP);
+ }
+
+ return FTEXT(".") FSTRING_PATH_SEPARATOR;
+}
#endif
+static bool DeleteEmptyFolderAndEmptySubFolders(const FString &path)
+{
+ NFind::CFileInfo fileInfo;
+ FString pathPrefix = path + FCHAR_PATH_SEPARATOR;
+ {
+ NFind::CEnumerator enumerator(pathPrefix + FCHAR_ANY_MASK);
+ while (enumerator.Next(fileInfo))
+ {
+ if (fileInfo.IsDir())
+ if (!DeleteEmptyFolderAndEmptySubFolders(pathPrefix + fileInfo.Name))
+ return false;
+ }
+ }
+ /*
+ // we don't need clear read-only for folders
+ if (!MySetFileAttributes(path, 0))
+ return false;
+ */
+ return RemoveDir(path);
+}
+
+
using namespace NUpdateArchive;
class COutMultiVolStream:
public IOutStream,
public CMyUnknownImp
{
- int _streamIndex; // required stream
+ unsigned _streamIndex; // required stream
UInt64 _offsetPos; // offset from start of _streamIndex index
UInt64 _absPos;
UInt64 _length;
- struct CSubStreamInfo
+ struct CAltStreamInfo
{
COutFileStream *StreamSpec;
CMyComPtr<IOutStream> Stream;
- UString Name;
+ FString Name;
UInt64 Pos;
UInt64 RealSize;
};
- CObjectVector<CSubStreamInfo> Streams;
+ CObjectVector<CAltStreamInfo> Streams;
public:
// CMyComPtr<IArchiveUpdateCallback2> VolumeCallback;
CRecordVector<UInt64> Sizes;
- UString Prefix;
+ FString Prefix;
CTempFiles *TempFiles;
void Init()
@@ -78,6 +111,7 @@ public:
_length = 0;
}
+ bool SetMTime(const FILETIME *mTime);
HRESULT Close();
MY_UNKNOWN_IMP1(IOutStream)
@@ -92,12 +126,12 @@ public:
HRESULT COutMultiVolStream::Close()
{
HRESULT res = S_OK;
- for (int i = 0; i < Streams.Size(); i++)
+ FOR_VECTOR (i, Streams)
{
- CSubStreamInfo &s = Streams[i];
- if (s.StreamSpec)
+ COutFileStream *s = Streams[i].StreamSpec;
+ if (s)
{
- HRESULT res2 = s.StreamSpec->Close();
+ HRESULT res2 = s->Close();
if (res2 != S_OK)
res = res2;
}
@@ -105,40 +139,53 @@ HRESULT COutMultiVolStream::Close()
return res;
}
+bool COutMultiVolStream::SetMTime(const FILETIME *mTime)
+{
+ bool res = true;
+ FOR_VECTOR (i, Streams)
+ {
+ COutFileStream *s = Streams[i].StreamSpec;
+ if (s)
+ if (!s->SetMTime(mTime))
+ res = false;
+ }
+ return res;
+}
+
STDMETHODIMP COutMultiVolStream::Write(const void *data, UInt32 size, UInt32 *processedSize)
{
if (processedSize != NULL)
*processedSize = 0;
- while(size > 0)
+ while (size > 0)
{
if (_streamIndex >= Streams.Size())
{
- CSubStreamInfo subStream;
+ CAltStreamInfo altStream;
- wchar_t temp[16];
+ FChar temp[16];
ConvertUInt32ToString(_streamIndex + 1, temp);
- UString res = temp;
- while (res.Length() < 3)
- res = UString(L'0') + res;
- UString name = Prefix + res;
- subStream.StreamSpec = new COutFileStream;
- subStream.Stream = subStream.StreamSpec;
- if (!subStream.StreamSpec->Create(name, false))
+ FString res = temp;
+ while (res.Len() < 3)
+ res = FString(FTEXT('0')) + res;
+ FString name = Prefix + res;
+ altStream.StreamSpec = new COutFileStream;
+ altStream.Stream = altStream.StreamSpec;
+ if (!altStream.StreamSpec->Create(name, false))
return ::GetLastError();
{
// NSynchronization::CCriticalSectionLock lock(g_TempPathsCS);
TempFiles->Paths.Add(name);
}
- subStream.Pos = 0;
- subStream.RealSize = 0;
- subStream.Name = name;
- Streams.Add(subStream);
+ altStream.Pos = 0;
+ altStream.RealSize = 0;
+ altStream.Name = name;
+ Streams.Add(altStream);
continue;
}
- CSubStreamInfo &subStream = Streams[_streamIndex];
+ CAltStreamInfo &altStream = Streams[_streamIndex];
- int index = _streamIndex;
+ unsigned index = _streamIndex;
if (index >= Sizes.Size())
index = Sizes.Size() - 1;
UInt64 volSize = Sizes[index];
@@ -149,29 +196,29 @@ STDMETHODIMP COutMultiVolStream::Write(const void *data, UInt32 size, UInt32 *pr
_streamIndex++;
continue;
}
- if (_offsetPos != subStream.Pos)
+ if (_offsetPos != altStream.Pos)
{
// CMyComPtr<IOutStream> outStream;
- // RINOK(subStream.Stream.QueryInterface(IID_IOutStream, &outStream));
- RINOK(subStream.Stream->Seek(_offsetPos, STREAM_SEEK_SET, NULL));
- subStream.Pos = _offsetPos;
+ // RINOK(altStream.Stream.QueryInterface(IID_IOutStream, &outStream));
+ RINOK(altStream.Stream->Seek(_offsetPos, STREAM_SEEK_SET, NULL));
+ altStream.Pos = _offsetPos;
}
- UInt32 curSize = (UInt32)MyMin((UInt64)size, volSize - subStream.Pos);
+ UInt32 curSize = (UInt32)MyMin((UInt64)size, volSize - altStream.Pos);
UInt32 realProcessed;
- RINOK(subStream.Stream->Write(data, curSize, &realProcessed));
+ RINOK(altStream.Stream->Write(data, curSize, &realProcessed));
data = (void *)((Byte *)data + realProcessed);
size -= realProcessed;
- subStream.Pos += realProcessed;
+ altStream.Pos += realProcessed;
_offsetPos += realProcessed;
_absPos += realProcessed;
if (_absPos > _length)
_length = _absPos;
- if (_offsetPos > subStream.RealSize)
- subStream.RealSize = _offsetPos;
+ if (_offsetPos > altStream.RealSize)
+ altStream.RealSize = _offsetPos;
if (processedSize != NULL)
*processedSize += realProcessed;
- if (subStream.Pos == volSize)
+ if (altStream.Pos == volSize)
{
_streamIndex++;
_offsetPos = 0;
@@ -187,17 +234,11 @@ STDMETHODIMP COutMultiVolStream::Seek(Int64 offset, UInt32 seekOrigin, UInt64 *n
{
if (seekOrigin >= 3)
return STG_E_INVALIDFUNCTION;
- switch(seekOrigin)
+ switch (seekOrigin)
{
- case STREAM_SEEK_SET:
- _absPos = offset;
- break;
- case STREAM_SEEK_CUR:
- _absPos += offset;
- break;
- case STREAM_SEEK_END:
- _absPos = _length + offset;
- break;
+ case STREAM_SEEK_SET: _absPos = offset; break;
+ case STREAM_SEEK_CUR: _absPos += offset; break;
+ case STREAM_SEEK_END: _absPos = _length + offset; break;
}
_offsetPos = _absPos;
if (newPosition != NULL)
@@ -210,24 +251,24 @@ STDMETHODIMP COutMultiVolStream::SetSize(UInt64 newSize)
{
if (newSize < 0)
return E_INVALIDARG;
- int i = 0;
+ unsigned i = 0;
while (i < Streams.Size())
{
- CSubStreamInfo &subStream = Streams[i++];
- if ((UInt64)newSize < subStream.RealSize)
+ CAltStreamInfo &altStream = Streams[i++];
+ if ((UInt64)newSize < altStream.RealSize)
{
- RINOK(subStream.Stream->SetSize(newSize));
- subStream.RealSize = newSize;
+ RINOK(altStream.Stream->SetSize(newSize));
+ altStream.RealSize = newSize;
break;
}
- newSize -= subStream.RealSize;
+ newSize -= altStream.RealSize;
}
while (i < Streams.Size())
{
{
- CSubStreamInfo &subStream = Streams.Back();
- subStream.Stream.Release();
- NDirectory::DeleteFileAlways(subStream.Name);
+ CAltStreamInfo &altStream = Streams.Back();
+ altStream.Stream.Release();
+ DeleteFileAlways(altStream.Name);
}
Streams.DeleteBack();
}
@@ -237,7 +278,67 @@ STDMETHODIMP COutMultiVolStream::SetSize(UInt64 newSize)
return S_OK;
}
-static const wchar_t *kDefaultArchiveType = L"7z";
+void CArchivePath::ParseFromPath(const UString &path, EArcNameMode mode)
+{
+ OriginalPath = path;
+
+ SplitPathToParts_2(path, Prefix, Name);
+
+ if (mode == k_ArcNameMode_Add)
+ return;
+ if (mode == k_ArcNameMode_Exact)
+ {
+ BaseExtension.Empty();
+ return;
+ }
+
+ int dotPos = Name.ReverseFind(L'.');
+ if (dotPos < 0)
+ return;
+ if ((unsigned)dotPos == Name.Len() - 1)
+ {
+ Name.DeleteBack();
+ BaseExtension.Empty();
+ return;
+ }
+ const UString ext = Name.Ptr(dotPos + 1);
+ if (BaseExtension.IsEqualToNoCase(ext))
+ {
+ BaseExtension = ext;
+ Name.DeleteFrom(dotPos);
+ }
+ else
+ BaseExtension.Empty();
+}
+
+UString CArchivePath::GetFinalPath() const
+{
+ UString path = GetPathWithoutExt();
+ if (!BaseExtension.IsEmpty())
+ path += UString(L'.') + BaseExtension;
+ return path;
+}
+
+UString CArchivePath::GetFinalVolPath() const
+{
+ UString path = GetPathWithoutExt();
+ if (!BaseExtension.IsEmpty())
+ path += UString(L'.') + VolExtension;
+ return path;
+}
+
+FString CArchivePath::GetTempPath() const
+{
+ FString path = TempPrefix + us2fs(Name);
+ if (!BaseExtension.IsEmpty())
+ path += FString(FTEXT('.')) + us2fs(BaseExtension);
+ path += FTEXT(".tmp");
+ path += TempPostfix;
+ return path;
+}
+
+static const wchar_t *kDefaultArcType = L"7z";
+static const wchar_t *kDefaultArcExt = L"7z";
static const wchar_t *kSFXExtension =
#ifdef _WIN32
L"exe";
@@ -245,40 +346,58 @@ static const wchar_t *kSFXExtension =
L"";
#endif
-bool CUpdateOptions::Init(const CCodecs *codecs, const CIntVector &formatIndices, const UString &arcPath)
+bool CUpdateOptions::InitFormatIndex(const CCodecs *codecs,
+ const CObjectVector<COpenType> &types, const UString &arcPath)
{
- if (formatIndices.Size() > 1)
+ if (types.Size() > 1)
return false;
- int arcTypeIndex = -1;
- if (formatIndices.Size() != 0)
- arcTypeIndex = formatIndices[0];
- if (arcTypeIndex >= 0)
- MethodMode.FormatIndex = arcTypeIndex;
+ // int arcTypeIndex = -1;
+ if (types.Size() != 0)
+ {
+ MethodMode.Type = types[0];
+ MethodMode.Type_Defined = true;
+ }
+ if (MethodMode.Type.FormatIndex < 0)
+ {
+ // MethodMode.Type = -1;
+ MethodMode.Type = COpenType();
+ if (ArcNameMode != k_ArcNameMode_Add)
+ {
+ MethodMode.Type.FormatIndex = codecs->FindFormatForArchiveName(arcPath);
+ if (MethodMode.Type.FormatIndex >= 0)
+ MethodMode.Type_Defined = true;
+ }
+ }
+ return true;
+}
+
+bool CUpdateOptions::SetArcPath(const CCodecs *codecs, const UString &arcPath)
+{
+ UString typeExt;
+ int formatIndex = MethodMode.Type.FormatIndex;
+ if (formatIndex < 0)
+ {
+ typeExt = kDefaultArcExt;
+ }
else
{
- MethodMode.FormatIndex = codecs->FindFormatForArchiveName(arcPath);
- // It works incorrectly for update command if archive has some non-default extension!
- if (MethodMode.FormatIndex < 0)
- MethodMode.FormatIndex = codecs->FindFormatForArchiveType(kDefaultArchiveType);
+ const CArcInfoEx &arcInfo = codecs->Formats[formatIndex];
+ if (!arcInfo.UpdateEnabled)
+ return false;
+ typeExt = arcInfo.GetMainExt();
}
- if (MethodMode.FormatIndex < 0)
- return false;
- const CArcInfoEx &arcInfo = codecs->Formats[MethodMode.FormatIndex];
- if (!arcInfo.UpdateEnabled)
- return false;
- UString typeExt = arcInfo.GetMainExt();
UString ext = typeExt;
if (SfxMode)
ext = kSFXExtension;
ArchivePath.BaseExtension = ext;
ArchivePath.VolExtension = typeExt;
- ArchivePath.ParseFromPath(arcPath);
- for (int i = 0; i < Commands.Size(); i++)
+ ArchivePath.ParseFromPath(arcPath, ArcNameMode);
+ FOR_VECTOR (i, Commands)
{
CUpdateArchiveCommand &uc = Commands[i];
uc.ArchivePath.BaseExtension = ext;
uc.ArchivePath.VolExtension = typeExt;
- uc.ArchivePath.ParseFromPath(uc.UserArchivePath);
+ uc.ArchivePath.ParseFromPath(uc.UserArchivePath, ArcNameMode);
}
return true;
}
@@ -288,7 +407,7 @@ struct CUpdateProduceCallbackImp: public IUpdateProduceCallback
{
const CObjectVector<CArcItem> *_arcItems;
IUpdateCallbackUI *_callback;
-
+
CUpdateProduceCallbackImp(const CObjectVector<CArcItem> *a,
IUpdateCallbackUI *callback): _arcItems(a), _callback(callback) {}
virtual HRESULT ShowDeleteFile(int arcIndex);
@@ -300,36 +419,98 @@ HRESULT CUpdateProduceCallbackImp::ShowDeleteFile(int arcIndex)
}
*/
+bool CRenamePair::Prepare()
+{
+ if (RecursedType != NRecursedType::kNonRecursed)
+ return false;
+ if (!WildcardParsing)
+ return true;
+ return !DoesNameContainWildcard(OldName);
+}
+
+extern bool g_CaseSensitive;
+
+static int CompareTwoNames(const wchar_t *s1, const wchar_t *s2)
+{
+ for (int i = 0;; i++)
+ {
+ wchar_t c1 = s1[i];
+ wchar_t c2 = s2[i];
+ if (c1 == 0 || c2 == 0)
+ return i;
+ if (c1 == c2)
+ continue;
+ if (!g_CaseSensitive && (MyCharUpper(c1) == MyCharUpper(c2)))
+ continue;
+ if (IsCharDirLimiter(c1) && IsCharDirLimiter(c2))
+ continue;
+ return i;
+ }
+}
+
+bool CRenamePair::GetNewPath(bool isFolder, const UString &src, UString &dest) const
+{
+ int num = CompareTwoNames(OldName, src);
+ if (OldName[num] == 0)
+ {
+ if (src[num] != 0 && !IsCharDirLimiter(src[num]) && num != 0 && !IsCharDirLimiter(src[num - 1]))
+ return false;
+ }
+ else
+ {
+ // OldName[num] != 0
+ // OldName = "1\1a.txt"
+ // src = "1"
+
+ if (!isFolder ||
+ src[num] != 0 ||
+ !IsCharDirLimiter(OldName[num]) ||
+ OldName[num + 1] != 0)
+ return false;
+ }
+ dest = NewName + src.Ptr(num);
+ return true;
+}
+
+static int GetReverseSlashPos(const UString &name)
+{
+ int slashPos = name.ReverseFind(L'/');
+ #ifdef _WIN32
+ int slash1Pos = name.ReverseFind(L'\\');
+ slashPos = MyMax(slashPos, slash1Pos);
+ #endif
+ return slashPos;
+}
+
static HRESULT Compress(
+ const CUpdateOptions &options,
CCodecs *codecs,
const CActionSet &actionSet,
- IInArchive *archive,
- const CCompressionMethodMode &compressionMethod,
+ const CArc *arc,
CArchivePath &archivePath,
const CObjectVector<CArcItem> &arcItems,
- bool shareForWrite,
- bool stdInMode,
- /* const UString & stdInFileName, */
- bool stdOutMode,
+ Byte *processedItemsStatuses,
const CDirItems &dirItems,
- bool sfxMode,
- const UString &sfxModule,
- const CRecordVector<UInt64> &volumesSizes,
+ const CDirItem *parentDirItem,
CTempFiles &tempFiles,
CUpdateErrorInfo &errorInfo,
IUpdateCallbackUI *callback)
{
CMyComPtr<IOutArchive> outArchive;
- if (archive != NULL)
+ int formatIndex = options.MethodMode.Type.FormatIndex;
+ if (arc)
{
- CMyComPtr<IInArchive> archive2 = archive;
+ formatIndex = arc->FormatIndex;
+ if (formatIndex < 0)
+ return E_NOTIMPL;
+ CMyComPtr<IInArchive> archive2 = arc->Archive;
HRESULT result = archive2.QueryInterface(IID_IOutArchive, &outArchive);
if (result != S_OK)
throw kUpdateIsNotSupoorted;
}
else
{
- RINOK(codecs->CreateOutArchive(compressionMethod.FormatIndex, outArchive));
+ RINOK(codecs->CreateOutArchive(formatIndex, outArchive));
#ifdef EXTERNAL_CODECS
{
@@ -344,12 +525,12 @@ static HRESULT Compress(
}
if (outArchive == 0)
throw kUpdateIsNotSupoorted;
-
+
NFileTimeType::EEnum fileTimeType;
UInt32 value;
RINOK(outArchive->GetFileTimeType(&value));
- switch(value)
+ switch (value)
{
case NFileTimeType::kWindows:
case NFileTimeType::kUnix:
@@ -360,8 +541,69 @@ static HRESULT Compress(
return E_FAIL;
}
+ {
+ const CArcInfoEx &arcInfo = codecs->Formats[formatIndex];
+ if (options.AltStreams.Val && !arcInfo.Flags_AltStreams())
+ return E_NOTIMPL;
+ if (options.NtSecurity.Val && !arcInfo.Flags_NtSecure())
+ return E_NOTIMPL;
+ }
+
CRecordVector<CUpdatePair2> updatePairs2;
+ UStringVector newNames;
+
+ if (options.RenamePairs.Size() != 0)
+ {
+ FOR_VECTOR (i, arcItems)
+ {
+ const CArcItem &ai = arcItems[i];
+ bool needRename = false;
+ UString dest;
+ if (ai.Censored)
+ {
+ FOR_VECTOR (j, options.RenamePairs)
+ {
+ const CRenamePair &rp = options.RenamePairs[j];
+ if (rp.GetNewPath(ai.IsDir, ai.Name, dest))
+ {
+ needRename = true;
+ break;
+ }
+ if (ai.IsAltStream)
+ {
+ int colonPos = ai.Name.ReverseFind(':');
+ int slashPosPos = GetReverseSlashPos(ai.Name);
+ if (colonPos > slashPosPos)
+ {
+ UString mainName = ai.Name.Left(colonPos);
+ /*
+ actually we must improve that code to support cases
+ with folder renaming like: rn arc dir1\ dir2\
+ */
+ if (rp.GetNewPath(false, mainName, dest))
+ {
+ needRename = true;
+ dest += ':';
+ dest += ai.Name.Ptr(colonPos + 1);
+ break;
+ }
+ }
+ }
+ }
+ }
+ CUpdatePair2 up2;
+ up2.SetAs_NoChangeArcItem(ai.IndexInServer);
+ if (needRename)
+ {
+ up2.NewProps = true;
+ RINOK(arc->IsItemAnti(i, up2.IsAnti));
+ up2.NewNameIndex = newNames.Add(dest);
+ }
+ updatePairs2.Add(up2);
+ }
+ }
+ else
{
CRecordVector<CUpdatePair> updatePairs;
GetUpdatePairInfoList(dirItems, arcItems, fileTimeType, updatePairs); // must be done only once!!!
@@ -370,61 +612,81 @@ static HRESULT Compress(
}
UInt32 numFiles = 0;
- for (int i = 0; i < updatePairs2.Size(); i++)
+ FOR_VECTOR (i, updatePairs2)
if (updatePairs2[i].NewData)
numFiles++;
-
+
RINOK(callback->SetNumFiles(numFiles));
-
CArchiveUpdateCallback *updateCallbackSpec = new CArchiveUpdateCallback;
CMyComPtr<IArchiveUpdateCallback> updateCallback(updateCallbackSpec);
-
- updateCallbackSpec->ShareForWrite = shareForWrite;
- updateCallbackSpec->StdInMode = stdInMode;
+
+ updateCallbackSpec->ShareForWrite = options.OpenShareForWrite;
+ updateCallbackSpec->StdInMode = options.StdInMode;
updateCallbackSpec->Callback = callback;
+
+ if (arc)
+ {
+ // we set Archive to allow to transfer GetProperty requests back to DLL.
+ updateCallbackSpec->Archive = arc->Archive;
+ updateCallbackSpec->GetRawProps = arc->GetRawProps;
+ updateCallbackSpec->GetRootProps = arc->GetRootProps;
+ }
+
updateCallbackSpec->DirItems = &dirItems;
+ updateCallbackSpec->ParentDirItem = parentDirItem;
+
+ updateCallbackSpec->StoreNtSecurity = options.NtSecurity.Val;
+ updateCallbackSpec->StoreHardLinks = options.HardLinks.Val;
+ updateCallbackSpec->StoreSymLinks = options.SymLinks.Val;
+
updateCallbackSpec->ArcItems = &arcItems;
updateCallbackSpec->UpdatePairs = &updatePairs2;
+ updateCallbackSpec->ProcessedItemsStatuses = processedItemsStatuses;
+
+ if (options.RenamePairs.Size() != 0)
+ updateCallbackSpec->NewNames = &newNames;
+
+ CMyComPtr<IOutStream> outSeekStream;
CMyComPtr<ISequentialOutStream> outStream;
- if (!stdOutMode)
+ if (!options.StdOutMode)
{
- UString resultPath;
- int pos;
- if (!NFile::NDirectory::MyGetFullPathName(archivePath.GetFinalPath(), resultPath, pos))
+ FString dirPrefix;
+ if (!GetOnlyDirPrefix(us2fs(archivePath.GetFinalPath()), dirPrefix))
throw 1417161;
- NFile::NDirectory::CreateComplexDirectory(resultPath.Left(pos));
+ CreateComplexDir(dirPrefix);
}
COutFileStream *outStreamSpec = NULL;
COutMultiVolStream *volStreamSpec = NULL;
- if (volumesSizes.Size() == 0)
+ if (options.VolumesSizes.Size() == 0)
{
- if (stdOutMode)
+ if (options.StdOutMode)
outStream = new CStdOutFileStream;
else
{
outStreamSpec = new COutFileStream;
- outStream = outStreamSpec;
+ outSeekStream = outStreamSpec;
+ outStream = outSeekStream;
bool isOK = false;
- UString realPath;
+ FString realPath;
for (int i = 0; i < (1 << 16); i++)
{
if (archivePath.Temp)
{
if (i > 0)
{
- wchar_t s[16];
+ FChar s[16];
ConvertUInt32ToString(i, s);
archivePath.TempPostfix = s;
}
realPath = archivePath.GetTempPath();
}
else
- realPath = archivePath.GetFinalPath();
+ realPath = us2fs(archivePath.GetFinalPath());
if (outStreamSpec->Create(realPath, false))
{
tempFiles.Paths.Add(realPath);
@@ -447,12 +709,16 @@ static HRESULT Compress(
}
else
{
- if (stdOutMode)
+ if (options.StdOutMode)
return E_FAIL;
+ if (arc && arc->GetGlobalOffset() > 0)
+ return E_NOTIMPL;
+
volStreamSpec = new COutMultiVolStream;
- outStream = volStreamSpec;
- volStreamSpec->Sizes = volumesSizes;
- volStreamSpec->Prefix = archivePath.GetFinalPath() + UString(L".");
+ outSeekStream = volStreamSpec;
+ outStream = outSeekStream;
+ volStreamSpec->Sizes = options.VolumesSizes;
+ volStreamSpec->Prefix = us2fs(archivePath.GetFinalVolPath() + L".");
volStreamSpec->TempFiles = &tempFiles;
volStreamSpec->Init();
@@ -464,29 +730,29 @@ static HRESULT Compress(
*/
}
- RINOK(SetProperties(outArchive, compressionMethod.Properties));
+ RINOK(SetProperties(outArchive, options.MethodMode.Properties));
- if (sfxMode)
+ if (options.SfxMode)
{
CInFileStream *sfxStreamSpec = new CInFileStream;
CMyComPtr<IInStream> sfxStream(sfxStreamSpec);
- if (!sfxStreamSpec->Open(sfxModule))
+ if (!sfxStreamSpec->Open(options.SfxModule))
{
errorInfo.SystemError = ::GetLastError();
errorInfo.Message = L"7-Zip cannot open SFX module";
- errorInfo.FileName = sfxModule;
+ errorInfo.FileName = options.SfxModule;
return E_FAIL;
}
CMyComPtr<ISequentialOutStream> sfxOutStream;
COutFileStream *outStreamSpec = NULL;
- if (volumesSizes.Size() == 0)
+ if (options.VolumesSizes.Size() == 0)
sfxOutStream = outStream;
else
{
outStreamSpec = new COutFileStream;
sfxOutStream = outStreamSpec;
- UString realPath = archivePath.GetFinalPath();
+ FString realPath = us2fs(archivePath.GetFinalPath());
if (!outStreamSpec->Create(realPath, false))
{
errorInfo.SystemError = ::GetLastError();
@@ -502,9 +768,61 @@ static HRESULT Compress(
}
}
- HRESULT result = outArchive->UpdateItems(outStream, updatePairs2.Size(), updateCallback);
+ CMyComPtr<ISequentialOutStream> tailStream;
+
+ if (options.SfxMode || !arc || arc->ArcStreamOffset == 0)
+ tailStream = outStream;
+ else
+ {
+ // Int64 globalOffset = arc->GetGlobalOffset();
+ RINOK(arc->InStream->Seek(0, STREAM_SEEK_SET, NULL));
+ RINOK(NCompress::CopyStream_ExactSize(arc->InStream, outStream, arc->ArcStreamOffset, NULL));
+ if (options.StdOutMode)
+ tailStream = outStream;
+ else
+ {
+ CTailOutStream *tailStreamSpec = new CTailOutStream;
+ tailStream = tailStreamSpec;
+ tailStreamSpec->Stream = outSeekStream;
+ tailStreamSpec->Offset = arc->ArcStreamOffset;
+ tailStreamSpec->Init();
+ }
+ }
+
+
+ HRESULT result = outArchive->UpdateItems(tailStream, updatePairs2.Size(), updateCallback);
callback->Finilize();
RINOK(result);
+
+
+ if (options.SetArcMTime)
+ {
+ FILETIME ft;
+ ft.dwLowDateTime = 0;
+ ft.dwHighDateTime = 0;
+ FOR_VECTOR (i, updatePairs2)
+ {
+ CUpdatePair2 &pair2 = updatePairs2[i];
+ const FILETIME *ft2 = NULL;
+ if (pair2.NewProps && pair2.DirIndex >= 0)
+ ft2 = &dirItems.Items[pair2.DirIndex].MTime;
+ else if (pair2.UseArcProps && pair2.ArcIndex >= 0)
+ ft2 = &arcItems[pair2.ArcIndex].MTime;
+ if (ft2)
+ {
+ if (::CompareFileTime(&ft, ft2) < 0)
+ ft = *ft2;
+ }
+ }
+ if (ft.dwLowDateTime != 0 || ft.dwHighDateTime != 0)
+ {
+ if (outStreamSpec)
+ outStreamSpec->SetMTime(&ft);
+ else if (volStreamSpec)
+ volStreamSpec->SetMTime(&ft);;
+ }
+ }
+
if (outStreamSpec)
result = outStreamSpec->Close();
else if (volStreamSpec)
@@ -512,7 +830,9 @@ static HRESULT Compress(
return result;
}
-HRESULT EnumerateInArchiveItems(const NWildcard::CCensor &censor,
+static HRESULT EnumerateInArchiveItems(
+ // bool storeStreamsMode,
+ const NWildcard::CCensor &censor,
const CArc &arc,
CObjectVector<CArcItem> &arcItems)
{
@@ -520,23 +840,21 @@ HRESULT EnumerateInArchiveItems(const NWildcard::CCensor &censor,
UInt32 numItems;
IInArchive *archive = arc.Archive;
RINOK(archive->GetNumberOfItems(&numItems));
- arcItems.Reserve(numItems);
+ arcItems.ClearAndReserve(numItems);
for (UInt32 i = 0; i < numItems; i++)
{
CArcItem ai;
RINOK(arc.GetItemPath(i, ai.Name));
- RINOK(IsArchiveItemFolder(archive, i, ai.IsDir));
- ai.Censored = censor.CheckPath(ai.Name, !ai.IsDir);
+ RINOK(Archive_IsItem_Folder(archive, i, ai.IsDir));
+ RINOK(Archive_IsItem_AltStream(archive, i, ai.IsAltStream));
+ /*
+ if (!storeStreamsMode && ai.IsAltStream)
+ continue;
+ */
+ ai.Censored = censor.CheckPath(ai.IsAltStream, ai.Name, !ai.IsDir);
RINOK(arc.GetItemMTime(i, ai.MTime, ai.MTimeDefined));
-
- {
- CPropVariant prop;
- RINOK(archive->GetProperty(i, kpidSize, &prop));
- ai.SizeDefined = (prop.vt != VT_EMPTY);
- if (ai.SizeDefined)
- ai.Size = ConvertPropVariantToUInt64(prop);
- }
+ RINOK(arc.GetItemSize(i, ai.Size, ai.SizeDefined));
{
CPropVariant prop;
@@ -544,7 +862,7 @@ HRESULT EnumerateInArchiveItems(const NWildcard::CCensor &censor,
if (prop.vt == VT_UI4)
{
ai.TimeType = (int)(NFileTimeType::EEnum)prop.ulVal;
- switch(ai.TimeType)
+ switch (ai.TimeType)
{
case NFileTimeType::kWindows:
case NFileTimeType::kUnix:
@@ -557,99 +875,102 @@ HRESULT EnumerateInArchiveItems(const NWildcard::CCensor &censor,
}
ai.IndexInServer = i;
- arcItems.Add(ai);
+ arcItems.AddInReserved(ai);
}
return S_OK;
}
-
-static HRESULT UpdateWithItemLists(
- CCodecs *codecs,
- CUpdateOptions &options,
- IInArchive *archive,
- const CObjectVector<CArcItem> &arcItems,
- CDirItems &dirItems,
- CTempFiles &tempFiles,
- CUpdateErrorInfo &errorInfo,
- IUpdateCallbackUI2 *callback)
+struct CEnumDirItemUpdateCallback: public IEnumDirItemCallback
{
- for(int i = 0; i < options.Commands.Size(); i++)
+ IUpdateCallbackUI2 *Callback;
+ HRESULT ScanProgress(UInt64 numFolders, UInt64 numFiles, UInt64 totalSize, const wchar_t *path, bool isDir)
{
- CUpdateArchiveCommand &command = options.Commands[i];
- if (options.StdOutMode)
- {
- RINOK(callback->StartArchive(L"stdout", archive != 0));
- }
- else
- {
- RINOK(callback->StartArchive(command.ArchivePath.GetFinalPath(),
- i == 0 && options.UpdateArchiveItself && archive != 0));
- }
-
- RINOK(Compress(
- codecs,
- command.ActionSet, archive,
- options.MethodMode,
- command.ArchivePath,
- arcItems,
- options.OpenShareForWrite,
- options.StdInMode,
- /* options.StdInFileName, */
- options.StdOutMode,
- dirItems,
- options.SfxMode, options.SfxModule,
- options.VolumesSizes,
- tempFiles,
- errorInfo, callback));
-
- RINOK(callback->FinishArchive());
+ return Callback->ScanProgress(numFolders, numFiles, totalSize, path, isDir);
}
- return S_OK;
-}
+};
#if defined(_WIN32) && !defined(UNDER_CE)
-class CCurrentDirRestorer
+
+#include <mapi.h>
+
+#endif
+
+struct CRefSortPair
{
- UString _path;
-public:
- CCurrentDirRestorer() { NFile::NDirectory::MyGetCurrentDirectory(_path); }
- ~CCurrentDirRestorer() { RestoreDirectory();}
- bool RestoreDirectory() { return BOOLToBool(NFile::NDirectory::MySetCurrentDirectory(_path)); }
+ int Len;
+ int Index;
};
-#endif
-struct CEnumDirItemUpdateCallback: public IEnumDirItemCallback
+#define RINOZ(x) { int __tt = (x); if (__tt != 0) return __tt; }
+
+static int CompareRefSortPair(const CRefSortPair *a1, const CRefSortPair *a2, void *)
{
- IUpdateCallbackUI2 *Callback;
- HRESULT ScanProgress(UInt64 numFolders, UInt64 numFiles, const wchar_t *path)
+ RINOZ(-MyCompare(a1->Len, a2->Len));
+ return MyCompare(a1->Index, a2->Index);
+}
+
+static int GetNumSlashes(const FChar *s)
+{
+ for (int numSlashes = 0;;)
{
- return Callback->ScanProgress(numFolders, numFiles, path);
+ FChar c = *s++;
+ if (c == 0)
+ return numSlashes;
+ if (
+ #ifdef _WIN32
+ c == FTEXT('\\') ||
+ #endif
+ c == FTEXT('/'))
+ numSlashes++;
}
-};
+}
#ifdef _WIN32
-typedef ULONG (FAR PASCAL MY_MAPISENDDOCUMENTS)(
- ULONG_PTR ulUIParam,
- LPSTR lpszDelimChar,
- LPSTR lpszFilePaths,
- LPSTR lpszFileNames,
- ULONG ulReserved
-);
-typedef MY_MAPISENDDOCUMENTS FAR *MY_LPMAPISENDDOCUMENTS;
+void ConvertToLongNames(NWildcard::CCensor &censor);
#endif
HRESULT UpdateArchive(
CCodecs *codecs,
- const NWildcard::CCensor &censor,
+ const CObjectVector<COpenType> &types,
+ const UString &cmdArcPath2,
+ NWildcard::CCensor &censor,
CUpdateOptions &options,
CUpdateErrorInfo &errorInfo,
IOpenCallbackUI *openCallback,
- IUpdateCallbackUI2 *callback)
+ IUpdateCallbackUI2 *callback,
+ bool needSetPath)
{
if (options.StdOutMode && options.EMailMode)
return E_FAIL;
- if (options.VolumesSizes.Size() > 0 && (options.EMailMode || options.SfxMode))
+ if (types.Size() > 1)
+ return E_NOTIMPL;
+
+ bool renameMode = !options.RenamePairs.IsEmpty();
+ if (renameMode)
+ {
+ if (options.Commands.Size() != 1)
+ return E_FAIL;
+ }
+
+ if (options.DeleteAfterCompressing)
+ {
+ if (options.Commands.Size() != 1)
+ return E_NOTIMPL;
+ const CActionSet &as = options.Commands[0].ActionSet;
+ for (int i = 2; i < NPairState::kNumValues; i++)
+ if (as.StateActions[i] != NPairAction::kCompress)
+ return E_NOTIMPL;
+ }
+
+ censor.AddPathsToCensor(options.PathMode);
+ #ifdef _WIN32
+ ConvertToLongNames(censor);
+ #endif
+ censor.ExtendExclude();
+
+
+ if (options.VolumesSizes.Size() > 0 && (options.EMailMode /* || options.SfxMode */))
return E_NOTIMPL;
if (options.SfxMode)
@@ -663,40 +984,96 @@ HRESULT UpdateArchive(
errorInfo.Message = L"SFX file is not specified";
return E_FAIL;
}
- UString name = options.SfxModule;
- #ifdef UNDER_CE
- if (!NFind::DoesFileExist(name))
- #else
- if (!NDirectory::MySearchPath(NULL, name, NULL, options.SfxModule))
- #endif
+ bool found = false;
+ if (options.SfxModule.Find(FCHAR_PATH_SEPARATOR) < 0)
{
- errorInfo.SystemError = ::GetLastError();
- errorInfo.Message = L"7-Zip cannot find specified SFX module";
- errorInfo.FileName = name;
- return E_FAIL;
+ const FString fullName = ::GetModuleDirPrefix() + options.SfxModule;
+ if (NFind::DoesFileExist(fullName))
+ {
+ options.SfxModule = fullName;
+ found = true;
+ }
+ }
+ if (!found)
+ {
+ if (!NFind::DoesFileExist(options.SfxModule))
+ {
+ errorInfo.SystemError = ::GetLastError();
+ errorInfo.Message = L"7-Zip cannot find specified SFX module";
+ errorInfo.FileName = options.SfxModule;
+ return E_FAIL;
+ }
}
}
-
CArchiveLink arcLink;
- const UString arcPath = options.ArchivePath.GetFinalPath();
- if (!options.ArchivePath.OriginalPath.IsEmpty())
+
+ if (needSetPath)
{
- NFind::CFileInfoW fi;
- if (fi.Find(arcPath))
+ if (!options.InitFormatIndex(codecs, types, cmdArcPath2) ||
+ !options.SetArcPath(codecs, cmdArcPath2))
+ return E_NOTIMPL;
+ }
+ UString arcPath = options.ArchivePath.GetFinalPath();
+
+ if (cmdArcPath2.IsEmpty())
+ {
+ if (options.MethodMode.Type.FormatIndex < 0)
+ throw "type of archive is not specified";
+ }
+ else
+ {
+ NFind::CFileInfo fi;
+ if (!fi.Find(us2fs(arcPath)))
+ {
+ if (renameMode)
+ throw "can't find archive";;
+ if (options.MethodMode.Type.FormatIndex < 0)
+ {
+ if (!options.SetArcPath(codecs, cmdArcPath2))
+ return E_NOTIMPL;
+ }
+ }
+ else
{
if (fi.IsDir())
throw "there is no such archive";
+ if (fi.IsDevice)
+ return E_NOTIMPL;
if (options.VolumesSizes.Size() > 0)
return E_NOTIMPL;
- CIntVector formatIndices;
- if (options.MethodMode.FormatIndex >= 0)
- formatIndices.Add(options.MethodMode.FormatIndex);
- HRESULT result = arcLink.Open2(codecs, formatIndices, false, NULL, arcPath, openCallback);
+ CObjectVector<COpenType> types;
+ // change it.
+ if (options.MethodMode.Type_Defined)
+ types.Add(options.MethodMode.Type);
+ // We need to set Properties to open archive only in some cases (WIM archives).
+
+ CIntVector excl;
+ COpenOptions op;
+ #ifndef _SFX
+ op.props = &options.MethodMode.Properties;
+ #endif
+ op.codecs = codecs;
+ op.types = &types;
+ op.excludedFormats = &excl;
+ op.stdInMode = false;
+ op.stream = NULL;
+ op.filePath = arcPath;
+
+ HRESULT result = arcLink.Open2(op, openCallback);
+
if (result == E_ABORT)
return result;
- RINOK(callback->OpenResult(arcPath, result));
+
+ const wchar_t *errorArcType = NULL;
+ if (arcLink.NonOpen_ErrorInfo.ErrorFormatIndex > 0)
+ errorArcType = codecs->Formats[arcLink.NonOpen_ErrorInfo.ErrorFormatIndex].Name;
+ RINOK(callback->OpenResult(arcPath, result, errorArcType));
+ /*
+ if (result == S_FALSE)
+ return E_FAIL;
+ */
RINOK(result);
if (arcLink.VolumePaths.Size() > 1)
{
@@ -704,21 +1081,48 @@ HRESULT UpdateArchive(
errorInfo.Message = L"Updating for multivolume archives is not implemented";
return E_NOTIMPL;
}
-
+
CArc &arc = arcLink.Arcs.Back();
arc.MTimeDefined = !fi.IsDevice;
arc.MTime = fi.MTime;
+
+ if (arc.ErrorInfo.ThereIsTail)
+ {
+ errorInfo.SystemError = (DWORD)E_NOTIMPL;
+ errorInfo.Message = L"There is some data block after the end of the archive";
+ return E_NOTIMPL;
+ }
+ if (options.MethodMode.Type.FormatIndex < 0)
+ {
+ options.MethodMode.Type.FormatIndex = arcLink.GetArc()->FormatIndex;
+ if (!options.SetArcPath(codecs, cmdArcPath2))
+ return E_NOTIMPL;
+ }
}
}
- else
+
+ if (options.MethodMode.Type.FormatIndex < 0)
{
- /*
- if (archiveType.IsEmpty())
- throw "type of archive is not specified";
- */
+ options.MethodMode.Type.FormatIndex = codecs->FindFormatForArchiveType(kDefaultArcType);
+ if (options.MethodMode.Type.FormatIndex < 0)
+ return E_NOTIMPL;
}
+ bool thereIsInArchive = arcLink.IsOpen;
+ if (!thereIsInArchive && renameMode)
+ return E_FAIL;
+
CDirItems dirItems;
+ CDirItem parentDirItem;
+ CDirItem *parentDirItem_Ptr = NULL;
+
+ /*
+ FStringVector requestedPaths;
+ FStringVector *requestedPaths_Ptr = NULL;
+ if (options.DeleteAfterCompressing)
+ requestedPaths_Ptr = &requestedPaths;
+ */
+
if (options.StdInMode)
{
CDirItem di;
@@ -732,7 +1136,8 @@ HRESULT UpdateArchive(
else
{
bool needScanning = false;
- for(int i = 0; i < options.Commands.Size(); i++)
+ if (!renameMode)
+ FOR_VECTOR (i, options.Commands)
if (options.Commands[i].ActionSet.NeedScanning())
needScanning = true;
if (needScanning)
@@ -740,12 +1145,21 @@ HRESULT UpdateArchive(
CEnumDirItemUpdateCallback enumCallback;
enumCallback.Callback = callback;
RINOK(callback->StartScanning());
- UStringVector errorPaths;
- CRecordVector<DWORD> errorCodes;
- HRESULT res = EnumerateItems(censor, dirItems, &enumCallback, errorPaths, errorCodes);
- for (int i = 0; i < errorPaths.Size(); i++)
+
+ dirItems.SymLinks = options.SymLinks.Val;
+
+ #if defined(_WIN32) && !defined(UNDER_CE)
+ dirItems.ReadSecure = options.NtSecurity.Val;
+ #endif
+
+ dirItems.ScanAltStreams = options.AltStreams.Val;
+ HRESULT res = EnumerateItems(censor,
+ options.PathMode,
+ options.AddPathPrefix,
+ dirItems, &enumCallback);
+ FOR_VECTOR (i, dirItems.ErrorPaths)
{
- RINOK(callback->CanNotFindError(errorPaths[i], errorCodes[i]));
+ RINOK(callback->CanNotFindError(fs2us(dirItems.ErrorPaths[i]), dirItems.ErrorCodes[i]));
}
if (res != S_OK)
{
@@ -754,14 +1168,46 @@ HRESULT UpdateArchive(
return res;
}
RINOK(callback->FinishScanning());
+
+ if (censor.Pairs.Size() == 1)
+ {
+ NFind::CFileInfo fi;
+ FString prefix = us2fs(censor.Pairs[0].Prefix) + FTEXT(".");
+ // UString prefix = censor.Pairs[0].Prefix;
+ /*
+ if (prefix.Back() == WCHAR_PATH_SEPARATOR)
+ {
+ prefix.DeleteBack();
+ }
+ */
+ if (fi.Find(prefix))
+ if (fi.IsDir())
+ {
+ parentDirItem.Size = fi.Size;
+ parentDirItem.CTime = fi.CTime;
+ parentDirItem.ATime = fi.ATime;
+ parentDirItem.MTime = fi.MTime;
+ parentDirItem.Attrib = fi.Attrib;
+ parentDirItem_Ptr = &parentDirItem;
+
+ int secureIndex = -1;
+ #if defined(_WIN32) && !defined(UNDER_CE)
+ if (options.NtSecurity.Val)
+ dirItems.AddSecurityItem(prefix, secureIndex);
+ #endif
+ parentDirItem.SecureIndex = secureIndex;
+
+ parentDirItem_Ptr = &parentDirItem;
+ }
+ }
}
}
- UString tempDirPrefix;
+ FString tempDirPrefix;
bool usesTempDir = false;
-
+
#ifdef _WIN32
- NDirectory::CTempDirectoryW tempDirectory;
+ CTempDir tempDirectory;
if (options.EMailMode && options.EMailRemoveAfter)
{
tempDirectory.Create(kTempFolderPrefix);
@@ -775,8 +1221,6 @@ HRESULT UpdateArchive(
bool createTempFile = false;
- bool thereIsInArchive = arcLink.IsOpen;
-
if (!options.StdOutMode && options.UpdateArchiveItself)
{
CArchivePath &ap = options.Commands[0].ArchivePath;
@@ -787,27 +1231,28 @@ HRESULT UpdateArchive(
createTempFile = true;
ap.Temp = true;
if (!options.WorkingDir.IsEmpty())
- {
ap.TempPrefix = options.WorkingDir;
- NormalizeDirPathPrefix(ap.TempPrefix);
- }
+ else
+ ap.TempPrefix = us2fs(ap.Prefix);
+ NormalizeDirPathPrefix(ap.TempPrefix);
}
}
- for(int i = 0; i < options.Commands.Size(); i++)
+ unsigned i;
+ for (i = 0; i < options.Commands.Size(); i++)
{
CArchivePath &ap = options.Commands[i].ArchivePath;
if (usesTempDir)
{
// Check it
- ap.Prefix = tempDirPrefix;
+ ap.Prefix = fs2us(tempDirPrefix);
// ap.Temp = true;
// ap.TempPrefix = tempDirPrefix;
}
if (!options.StdOutMode &&
(i > 0 || !createTempFile))
{
- const UString &path = ap.GetFinalPath();
+ const FString path = us2fs(ap.GetFinalPath());
if (NFind::DoesFileOrDirExist(path))
{
errorInfo.SystemError = 0;
@@ -821,13 +1266,64 @@ HRESULT UpdateArchive(
CObjectVector<CArcItem> arcItems;
if (thereIsInArchive)
{
- RINOK(EnumerateInArchiveItems(censor, arcLink.Arcs.Back(), arcItems));
+ RINOK(EnumerateInArchiveItems(
+ // options.StoreAltStreams,
+ censor, arcLink.Arcs.Back(), arcItems));
+ }
+
+ /*
+ FStringVector processedFilePaths;
+ FStringVector *processedFilePaths_Ptr = NULL;
+ if (options.DeleteAfterCompressing)
+ processedFilePaths_Ptr = &processedFilePaths;
+ */
+
+ CByteBuffer processedItems;
+ if (options.DeleteAfterCompressing)
+ {
+ unsigned num = dirItems.Items.Size();
+ processedItems.Alloc(num);
+ for (i = 0; i < num; i++)
+ processedItems[i] = 0;
+ }
+
+ for (i = 0; i < options.Commands.Size(); i++)
+ {
+ const CArc *arc = thereIsInArchive ? arcLink.GetArc() : 0;
+ // IInArchiveExtra *archiveExtra = thereIsInArchive ? arcLink.GetArchiveExtra() : 0;
+ // IArchiveGetRootProps *archiveGetRootProps = thereIsInArchive ? arcLink.GetArchiveGetRootProps() : 0;
+ CUpdateArchiveCommand &command = options.Commands[i];
+ UString name;
+ bool isUpdating;
+ if (options.StdOutMode)
+ {
+ name = L"stdout";
+ isUpdating = arc != 0;
+ }
+ else
+ {
+ name = command.ArchivePath.GetFinalPath();
+ isUpdating = (i == 0 && options.UpdateArchiveItself && arc != 0);
+ }
+ RINOK(callback->StartArchive(name, isUpdating))
+
+ RINOK(Compress(options,
+ codecs,
+ command.ActionSet,
+ arc,
+ command.ArchivePath,
+ arcItems,
+ options.DeleteAfterCompressing ? (Byte *)processedItems : NULL,
+
+ dirItems,
+ parentDirItem_Ptr,
+
+ tempFiles,
+ errorInfo, callback));
+
+ RINOK(callback->FinishArchive());
}
- RINOK(UpdateWithItemLists(codecs, options,
- thereIsInArchive ? arcLink.GetArchive() : 0,
- arcItems, dirItems,
- tempFiles, errorInfo, callback));
if (thereIsInArchive)
{
@@ -841,21 +1337,21 @@ HRESULT UpdateArchive(
try
{
CArchivePath &ap = options.Commands[0].ArchivePath;
- const UString &tempPath = ap.GetTempPath();
+ const FString &tempPath = ap.GetTempPath();
if (thereIsInArchive)
- if (!NDirectory::DeleteFileAlways(arcPath))
+ if (!DeleteFileAlways(us2fs(arcPath)))
{
errorInfo.SystemError = ::GetLastError();
errorInfo.Message = L"7-Zip cannot delete the file";
- errorInfo.FileName = arcPath;
+ errorInfo.FileName = us2fs(arcPath);
return E_FAIL;
}
- if (!NDirectory::MyMoveFile(tempPath, arcPath))
+ if (!MyMoveFile(tempPath, us2fs(arcPath)))
{
errorInfo.SystemError = ::GetLastError();
errorInfo.Message = L"7-Zip cannot move the file";
errorInfo.FileName = tempPath;
- errorInfo.FileName2 = arcPath;
+ errorInfo.FileName2 = us2fs(arcPath);
return E_FAIL;
}
}
@@ -865,30 +1361,42 @@ HRESULT UpdateArchive(
}
}
+
#if defined(_WIN32) && !defined(UNDER_CE)
if (options.EMailMode)
{
NDLL::CLibrary mapiLib;
- if (!mapiLib.Load(TEXT("Mapi32.dll")))
+ if (!mapiLib.Load(FTEXT("Mapi32.dll")))
{
errorInfo.SystemError = ::GetLastError();
errorInfo.Message = L"7-Zip cannot load Mapi32.dll";
return E_FAIL;
}
- MY_LPMAPISENDDOCUMENTS fnSend = (MY_LPMAPISENDDOCUMENTS)mapiLib.GetProc("MAPISendDocuments");
+
+ /*
+ LPMAPISENDDOCUMENTS fnSend = (LPMAPISENDDOCUMENTS)mapiLib.GetProc("MAPISendDocuments");
if (fnSend == 0)
{
errorInfo.SystemError = ::GetLastError();
errorInfo.Message = L"7-Zip cannot find MAPISendDocuments function";
return E_FAIL;
}
- UStringVector fullPaths;
- int i;
- for(i = 0; i < options.Commands.Size(); i++)
+ */
+ LPMAPISENDMAIL sendMail = (LPMAPISENDMAIL)mapiLib.GetProc("MAPISendMail");
+ if (sendMail == 0)
+ {
+ errorInfo.SystemError = ::GetLastError();
+ errorInfo.Message = L"7-Zip cannot find MAPISendMail function";
+ return E_FAIL;
+ }
+
+ FStringVector fullPaths;
+ unsigned i;
+ for (i = 0; i < options.Commands.Size(); i++)
{
CArchivePath &ap = options.Commands[i].ArchivePath;
- UString arcPath;
- if (!NFile::NDirectory::MyGetFullPathName(ap.GetFinalPath(), arcPath))
+ FString arcPath;
+ if (!MyGetFullPathName(us2fs(ap.GetFinalPath()), arcPath))
{
errorInfo.SystemError = ::GetLastError();
errorInfo.Message = L"GetFullPathName error";
@@ -897,16 +1405,86 @@ HRESULT UpdateArchive(
fullPaths.Add(arcPath);
}
CCurrentDirRestorer curDirRestorer;
- for(i = 0; i < fullPaths.Size(); i++)
+ for (i = 0; i < fullPaths.Size(); i++)
{
- UString arcPath = fullPaths[i];
+ UString arcPath = fs2us(fullPaths[i]);
UString fileName = ExtractFileNameFromPath(arcPath);
AString path = GetAnsiString(arcPath);
AString name = GetAnsiString(fileName);
// Warning!!! MAPISendDocuments function changes Current directory
- fnSend(0, ";", (LPSTR)(LPCSTR)path, (LPSTR)(LPCSTR)name, 0);
+ // fnSend(0, ";", (LPSTR)(LPCSTR)path, (LPSTR)(LPCSTR)name, 0);
+
+ MapiFileDesc f;
+ memset(&f, 0, sizeof(f));
+ f.nPosition = 0xFFFFFFFF;
+ f.lpszPathName = (char *)(const char *)path;
+ f.lpszFileName = (char *)(const char *)name;
+
+ MapiMessage m;
+ memset(&m, 0, sizeof(m));
+ m.nFileCount = 1;
+ m.lpFiles = &f;
+
+ const AString addr = GetAnsiString(options.EMailAddress);
+ MapiRecipDesc rec;
+ if (!addr.IsEmpty())
+ {
+ memset(&rec, 0, sizeof(rec));
+ rec.ulRecipClass = MAPI_TO;
+ rec.lpszAddress = (char *)(const char *)addr;
+ m.nRecipCount = 1;
+ m.lpRecips = &rec;
+ }
+
+ sendMail((LHANDLE)0, 0, &m, MAPI_DIALOG, 0);
}
}
#endif
+
+ if (options.DeleteAfterCompressing)
+ {
+ CRecordVector<CRefSortPair> pairs;
+ FStringVector foldersNames;
+ for (i = 0; i < dirItems.Items.Size(); i++)
+ {
+ const CDirItem &dirItem = dirItems.Items[i];
+ FString phyPath = us2fs(dirItems.GetPhyPath(i));
+ if (dirItem.IsDir())
+ {
+ CRefSortPair pair;
+ pair.Index = i;
+ pair.Len = GetNumSlashes(phyPath);
+ pairs.Add(pair);
+ }
+ else
+ {
+ if (processedItems[i] != 0 || dirItem.Size == 0)
+ {
+ DeleteFileAlways(phyPath);
+ }
+ else
+ {
+ // file was skipped
+ /*
+ errorInfo.SystemError = 0;
+ errorInfo.Message = L"file was not processed";
+ errorInfo.FileName = phyPath;
+ return E_FAIL;
+ */
+ }
+ }
+ }
+
+ pairs.Sort(CompareRefSortPair, NULL);
+ for (i = 0; i < pairs.Size(); i++)
+ {
+ FString phyPath = us2fs(dirItems.GetPhyPath(pairs[i].Index));
+ if (NFind::DoesDirExist(phyPath))
+ {
+ // printf("delete %S\n", phyPath);
+ RemoveDir(phyPath);
+ }
+ }
+ }
return S_OK;
}
diff --git a/src/libs/7zip/unix/CPP/7zip/UI/Common/Update.h b/src/libs/7zip/unix/CPP/7zip/UI/Common/Update.h
index ade001303..b2fdb4647 100644
--- a/src/libs/7zip/unix/CPP/7zip/UI/Common/Update.h
+++ b/src/libs/7zip/unix/CPP/7zip/UI/Common/Update.h
@@ -3,14 +3,22 @@
#ifndef __COMMON_UPDATE_H
#define __COMMON_UPDATE_H
-#include "Common/Wildcard.h"
+#include "../../../Common/Wildcard.h"
#include "ArchiveOpenCallback.h"
#include "LoadCodecs.h"
+#include "OpenArchive.h"
#include "Property.h"
#include "UpdateAction.h"
#include "UpdateCallback.h"
+enum EArcNameMode
+{
+ k_ArcNameMode_Smart,
+ k_ArcNameMode_Exact,
+ k_ArcNameMode_Add,
+};
+
struct CArchivePath
{
UString OriginalPath;
@@ -21,57 +29,16 @@ struct CArchivePath
UString VolExtension; // archive type extension for volumes
bool Temp;
- UString TempPrefix; // path(folder) for temp location
- UString TempPostfix;
+ FString TempPrefix; // path(folder) for temp location
+ FString TempPostfix;
CArchivePath(): Temp(false) {};
-
- void ParseFromPath(const UString &path)
- {
- OriginalPath = path;
-
- SplitPathToParts(path, Prefix, Name);
- int dotPos = Name.ReverseFind(L'.');
- if (dotPos < 0)
- return;
- if (dotPos == Name.Length() - 1)
- {
- Name = Name.Left(dotPos);
- BaseExtension.Empty();
- return;
- }
- if (BaseExtension.CompareNoCase(Name.Mid(dotPos + 1)) == 0)
- {
- BaseExtension = Name.Mid(dotPos + 1);
- Name = Name.Left(dotPos);
- }
- else
- BaseExtension.Empty();
- }
-
- UString GetPathWithoutExt() const
- {
- return Prefix + Name;
- }
- UString GetFinalPath() const
- {
- UString path = GetPathWithoutExt();
- if (!BaseExtension.IsEmpty())
- path += UString(L'.') + BaseExtension;
- return path;
- }
-
-
- UString GetTempPath() const
- {
- UString path = TempPrefix + Name;
- if (!BaseExtension.IsEmpty())
- path += UString(L'.') + BaseExtension;
- path += L".tmp";
- path += TempPostfix;
- return path;
- }
+ void ParseFromPath(const UString &path, EArcNameMode mode);
+ UString GetPathWithoutExt() const { return Prefix + Name; }
+ UString GetFinalPath() const;
+ UString GetFinalVolPath() const;
+ FString GetTempPath() const;
};
struct CUpdateArchiveCommand
@@ -83,9 +50,31 @@ struct CUpdateArchiveCommand
struct CCompressionMethodMode
{
- int FormatIndex;
+ bool Type_Defined;
+ COpenType Type;
CObjectVector<CProperty> Properties;
- CCompressionMethodMode(): FormatIndex(-1) {}
+
+ CCompressionMethodMode(): Type_Defined(false) {}
+};
+
+namespace NRecursedType { enum EEnum
+{
+ kRecursed,
+ kWildcardOnlyRecursed,
+ kNonRecursed
+};}
+
+struct CRenamePair
+{
+ UString OldName;
+ UString NewName;
+ bool WildcardParsing;
+ NRecursedType::EEnum RecursedType;
+
+ CRenamePair(): WildcardParsing(true), RecursedType(NRecursedType::kNonRecursed) {}
+
+ bool Prepare();
+ bool GetNewPath(bool isFolder, const UString &src, UString &dest) const;
};
struct CUpdateOptions
@@ -95,39 +84,60 @@ struct CUpdateOptions
CObjectVector<CUpdateArchiveCommand> Commands;
bool UpdateArchiveItself;
CArchivePath ArchivePath;
-
+ EArcNameMode ArcNameMode;
+
bool SfxMode;
- UString SfxModule;
-
+ FString SfxModule;
+
bool OpenShareForWrite;
bool StdInMode;
UString StdInFileName;
bool StdOutMode;
-
+
bool EMailMode;
bool EMailRemoveAfter;
UString EMailAddress;
- UString WorkingDir;
+ FString WorkingDir;
+ NWildcard::ECensorPathMode PathMode;
+ UString AddPathPrefix;
+
+ CBoolPair NtSecurity;
+ CBoolPair AltStreams;
+ CBoolPair HardLinks;
+ CBoolPair SymLinks;
+
+ bool DeleteAfterCompressing;
+
+ bool SetArcMTime;
- bool Init(const CCodecs *codecs, const CIntVector &formatIndices, const UString &arcPath);
+ CObjectVector<CRenamePair> RenamePairs;
+
+ bool InitFormatIndex(const CCodecs *codecs, const CObjectVector<COpenType> &types, const UString &arcPath);
+ bool SetArcPath(const CCodecs *codecs, const UString &arcPath);
CUpdateOptions():
UpdateArchiveItself(true),
+ ArcNameMode(k_ArcNameMode_Smart),
SfxMode(false),
OpenShareForWrite(false),
StdInMode(false),
StdOutMode(false),
EMailMode(false),
- EMailRemoveAfter(false)
+ EMailRemoveAfter(false),
+ PathMode(NWildcard::k_RelatPath),
+
+ DeleteAfterCompressing(false),
+ SetArcMTime(false)
+
{};
- void SetAddActionCommand()
+ void SetActionCommand_Add()
{
Commands.Clear();
CUpdateArchiveCommand c;
- c.ActionSet = NUpdateArchive::kAddActionSet;
+ c.ActionSet = NUpdateArchive::k_ActionSet_Add;
Commands.Add(c);
}
@@ -137,8 +147,8 @@ struct CUpdateOptions
struct CErrorInfo
{
DWORD SystemError;
- UString FileName;
- UString FileName2;
+ FString FileName;
+ FString FileName2;
UString Message;
// UStringVector ErrorPaths;
// CRecordVector<DWORD> ErrorCodes;
@@ -151,9 +161,9 @@ struct CUpdateErrorInfo: public CErrorInfo
#define INTERFACE_IUpdateCallbackUI2(x) \
INTERFACE_IUpdateCallbackUI(x) \
- virtual HRESULT OpenResult(const wchar_t *name, HRESULT result) x; \
+ virtual HRESULT OpenResult(const wchar_t *name, HRESULT result, const wchar_t *errorArcType) x; \
virtual HRESULT StartScanning() x; \
- virtual HRESULT ScanProgress(UInt64 numFolders, UInt64 numFiles, const wchar_t *path) x; \
+ virtual HRESULT ScanProgress(UInt64 numFolders, UInt64 numFiles, UInt64 totalSize, const wchar_t *path, bool isDir) x; \
virtual HRESULT CanNotFindError(const wchar_t *name, DWORD systemError) x; \
virtual HRESULT FinishScanning() x; \
virtual HRESULT StartArchive(const wchar_t *name, bool updating) x; \
@@ -166,10 +176,13 @@ struct IUpdateCallbackUI2: public IUpdateCallbackUI
HRESULT UpdateArchive(
CCodecs *codecs,
- const NWildcard::CCensor &censor,
+ const CObjectVector<COpenType> &types,
+ const UString &cmdArcPath2,
+ NWildcard::CCensor &censor,
CUpdateOptions &options,
CUpdateErrorInfo &errorInfo,
IOpenCallbackUI *openCallback,
- IUpdateCallbackUI2 *callback);
+ IUpdateCallbackUI2 *callback,
+ bool needSetPath);
#endif
diff --git a/src/libs/7zip/unix/CPP/7zip/UI/Common/UpdateAction.cpp b/src/libs/7zip/unix/CPP/7zip/UI/Common/UpdateAction.cpp
index 879a49c57..a80db7212 100644
--- a/src/libs/7zip/unix/CPP/7zip/UI/Common/UpdateAction.cpp
+++ b/src/libs/7zip/unix/CPP/7zip/UI/Common/UpdateAction.cpp
@@ -6,7 +6,7 @@
namespace NUpdateArchive {
-const CActionSet kAddActionSet =
+const CActionSet k_ActionSet_Add =
{{
NPairAction::kCopy,
NPairAction::kCopy,
@@ -17,7 +17,7 @@ const CActionSet kAddActionSet =
NPairAction::kCompress
}};
-const CActionSet kUpdateActionSet =
+const CActionSet k_ActionSet_Update =
{{
NPairAction::kCopy,
NPairAction::kCopy,
@@ -28,7 +28,7 @@ const CActionSet kUpdateActionSet =
NPairAction::kCompress
}};
-const CActionSet kFreshActionSet =
+const CActionSet k_ActionSet_Fresh =
{{
NPairAction::kCopy,
NPairAction::kCopy,
@@ -39,7 +39,7 @@ const CActionSet kFreshActionSet =
NPairAction::kCompress
}};
-const CActionSet kSynchronizeActionSet =
+const CActionSet k_ActionSet_Sync =
{{
NPairAction::kCopy,
NPairAction::kIgnore,
@@ -50,7 +50,7 @@ const CActionSet kSynchronizeActionSet =
NPairAction::kCompress,
}};
-const CActionSet kDeleteActionSet =
+const CActionSet k_ActionSet_Delete =
{{
NPairAction::kCopy,
NPairAction::kIgnore,
diff --git a/src/libs/7zip/unix/CPP/7zip/UI/Common/UpdateAction.h b/src/libs/7zip/unix/CPP/7zip/UI/Common/UpdateAction.h
index 0ac1c1080..b6645cbdd 100644
--- a/src/libs/7zip/unix/CPP/7zip/UI/Common/UpdateAction.h
+++ b/src/libs/7zip/unix/CPP/7zip/UI/Common/UpdateAction.h
@@ -7,7 +7,7 @@ namespace NUpdateArchive {
namespace NPairState
{
- const int kNumValues = 7;
+ const unsigned kNumValues = 7;
enum EEnum
{
kNotMasked = 0,
@@ -19,7 +19,7 @@ namespace NUpdateArchive {
kUnknowNewerFiles
};
}
-
+
namespace NPairAction
{
enum EEnum
@@ -30,13 +30,22 @@ namespace NUpdateArchive {
kCompressAsAnti
};
}
-
+
struct CActionSet
{
NPairAction::EEnum StateActions[NPairState::kNumValues];
+
+ bool IsEqualTo(const CActionSet &a) const
+ {
+ for (unsigned i = 0; i < NPairState::kNumValues; i++)
+ if (StateActions[i] != a.StateActions[i])
+ return false;
+ return true;
+ }
+
bool NeedScanning() const
{
- int i;
+ unsigned i;
for (i = 0; i < NPairState::kNumValues; i++)
if (StateActions[i] == NPairAction::kCompress)
return true;
@@ -46,12 +55,12 @@ namespace NUpdateArchive {
return false;
}
};
-
- extern const CActionSet kAddActionSet;
- extern const CActionSet kUpdateActionSet;
- extern const CActionSet kFreshActionSet;
- extern const CActionSet kSynchronizeActionSet;
- extern const CActionSet kDeleteActionSet;
+
+ extern const CActionSet k_ActionSet_Add;
+ extern const CActionSet k_ActionSet_Update;
+ extern const CActionSet k_ActionSet_Fresh;
+ extern const CActionSet k_ActionSet_Sync;
+ extern const CActionSet k_ActionSet_Delete;
}
#endif
diff --git a/src/libs/7zip/unix/CPP/7zip/UI/Common/UpdateCallback.cpp b/src/libs/7zip/unix/CPP/7zip/UI/Common/UpdateCallback.cpp
index 0f229058c..609ece856 100644
--- a/src/libs/7zip/unix/CPP/7zip/UI/Common/UpdateCallback.cpp
+++ b/src/libs/7zip/unix/CPP/7zip/UI/Common/UpdateCallback.cpp
@@ -2,18 +2,32 @@
#include "StdAfx.h"
-#include "Common/ComTry.h"
-#include "Common/Defs.h"
-#include "Common/IntToString.h"
-#include "Common/StringConvert.h"
+#include "../../../Common/ComTry.h"
+#include "../../../Common/IntToString.h"
+#include "../../../Common/StringConvert.h"
+#include "../../../Common/Wildcard.h"
-#include "Windows/PropVariant.h"
+#include "../../../Windows/FileDir.h"
+#include "../../../Windows/FileName.h"
+#include "../../../Windows/PropVariant.h"
+#include "../../../Windows/Synchronization.h"
#include "../../Common/FileStreams.h"
+#include "../../Common/StreamObjects.h"
#include "UpdateCallback.h"
+#if defined(_WIN32) && !defined(UNDER_CE)
+#define _USE_SECURITY_CODE
+#include "../../../Windows/SecurityUtils.h"
+#endif
+
using namespace NWindows;
+using namespace NFile;
+
+#ifdef _USE_SECURITY_CODE
+bool InitLocalPrivileges();
+#endif
CArchiveUpdateCallback::CArchiveUpdateCallback():
Callback(0),
@@ -22,8 +36,19 @@ CArchiveUpdateCallback::CArchiveUpdateCallback():
DirItems(0),
ArcItems(0),
UpdatePairs(0),
- NewNames(0)
- {}
+ NewNames(0),
+ KeepOriginalItemNames(false),
+ ProcessedItemsStatuses(NULL),
+ ParentDirItem(NULL),
+ StoreNtSecurity(false),
+ StoreHardLinks(false),
+ StoreSymLinks(false),
+ _hardIndex_From((UInt32)(Int32)-1)
+{
+ #ifdef _USE_SECURITY_CODE
+ _saclEnabled = InitLocalPrivileges();
+ #endif
+}
STDMETHODIMP CArchiveUpdateCallback::SetTotal(UInt64 size)
@@ -49,7 +74,7 @@ STDMETHODIMP CArchiveUpdateCallback::SetRatioInfo(const UInt64 *inSize, const UI
/*
-STATPROPSTG kProperties[] =
+static const STATPROPSTG kProps[] =
{
{ NULL, kpidPath, VT_BSTR},
{ NULL, kpidIsDir, VT_BOOL},
@@ -63,7 +88,7 @@ STATPROPSTG kProperties[] =
STDMETHODIMP CArchiveUpdateCallback::EnumProperties(IEnumSTATPROPSTG **)
{
- return CStatPropEnumerator::CreateEnumerator(kProperties, sizeof(kProperties) / sizeof(kProperties[0]), enumerator);
+ return CStatPropEnumerator::CreateEnumerator(kProps, ARRAY_SIZE(kProps), enumerator);
}
*/
@@ -73,11 +98,11 @@ STDMETHODIMP CArchiveUpdateCallback::GetUpdateItemInfo(UInt32 index,
COM_TRY_BEGIN
RINOK(Callback->CheckBreak());
const CUpdatePair2 &up = (*UpdatePairs)[index];
- if (newData != NULL) *newData = BoolToInt(up.NewData);
- if (newProps != NULL) *newProps = BoolToInt(up.NewProps);
- if (indexInArchive != NULL)
+ if (newData) *newData = BoolToInt(up.NewData);
+ if (newProps) *newProps = BoolToInt(up.NewProps);
+ if (indexInArchive)
{
- *indexInArchive = (UInt32)-1;
+ *indexInArchive = (UInt32)(Int32)-1;
if (up.ExistInArchive())
*indexInArchive = (ArcItems == 0) ? up.ArcIndex : (*ArcItems)[up.ArcIndex].IndexInServer;
}
@@ -85,40 +110,289 @@ STDMETHODIMP CArchiveUpdateCallback::GetUpdateItemInfo(UInt32 index,
COM_TRY_END
}
-STDMETHODIMP CArchiveUpdateCallback::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *value)
+STDMETHODIMP CArchiveUpdateCallback::GetRootProp(PROPID propID, PROPVARIANT *value)
{
- COM_TRY_BEGIN
- const CUpdatePair2 &up = (*UpdatePairs)[index];
- NWindows::NCOM::CPropVariant prop;
-
- if (propID == kpidIsAnti)
+ NCOM::CPropVariant prop;
+ switch (propID)
{
- prop = up.IsAnti;
- prop.Detach(value);
+ case kpidIsDir: prop = true; break;
+ case kpidAttrib: if (ParentDirItem) prop = ParentDirItem->Attrib; break;
+ case kpidCTime: if (ParentDirItem) prop = ParentDirItem->CTime; break;
+ case kpidATime: if (ParentDirItem) prop = ParentDirItem->ATime; break;
+ case kpidMTime: if (ParentDirItem) prop = ParentDirItem->MTime; break;
+ }
+ prop.Detach(value);
+ return S_OK;
+}
+
+STDMETHODIMP CArchiveUpdateCallback::GetParent(UInt32 /* index */, UInt32 *parent, UInt32 *parentType)
+{
+ *parentType = NParentType::kDir;
+ *parent = (UInt32)(Int32)-1;
+ return S_OK;
+}
+
+STDMETHODIMP CArchiveUpdateCallback::GetNumRawProps(UInt32 *numProps)
+{
+ *numProps = 0;
+ if (StoreNtSecurity)
+ *numProps = 1;
+ return S_OK;
+}
+
+STDMETHODIMP CArchiveUpdateCallback::GetRawPropInfo(UInt32 /* index */, BSTR *name, PROPID *propID)
+{
+ *name = NULL;
+ *propID = kpidNtSecure;
+ return S_OK;
+}
+
+STDMETHODIMP CArchiveUpdateCallback::GetRootRawProp(PROPID
+ #ifdef _USE_SECURITY_CODE
+ propID
+ #endif
+ , const void **data, UInt32 *dataSize, UInt32 *propType)
+{
+ *data = 0;
+ *dataSize = 0;
+ *propType = 0;
+ if (!StoreNtSecurity)
return S_OK;
+ #ifdef _USE_SECURITY_CODE
+ if (propID == kpidNtSecure)
+ {
+ if (StdInMode)
+ return S_OK;
+
+ if (ParentDirItem)
+ {
+ if (ParentDirItem->SecureIndex < 0)
+ return S_OK;
+ const CByteBuffer &buf = DirItems->SecureBlocks.Bufs[ParentDirItem->SecureIndex];
+ *data = buf;
+ *dataSize = (UInt32)buf.Size();
+ *propType = NPropDataType::kRaw;
+ return S_OK;
+ }
+
+ if (GetRootProps)
+ return GetRootProps->GetRootRawProp(propID, data, dataSize, propType);
}
+ #endif
+ return S_OK;
+}
- if (up.IsAnti)
+// #ifdef _USE_SECURITY_CODE
+// #endif
+
+STDMETHODIMP CArchiveUpdateCallback::GetRawProp(UInt32 index, PROPID propID, const void **data, UInt32 *dataSize, UInt32 *propType)
+{
+ *data = 0;
+ *dataSize = 0;
+ *propType = 0;
+
+ if (propID == kpidNtSecure ||
+ propID == kpidNtReparse)
{
- switch(propID)
+ if (StdInMode)
+ return S_OK;
+
+ const CUpdatePair2 &up = (*UpdatePairs)[index];
+ if (up.UseArcProps && up.ExistInArchive() && GetRawProps)
+ return GetRawProps->GetRawProp(
+ ArcItems ? (*ArcItems)[up.ArcIndex].IndexInServer : up.ArcIndex,
+ propID, data, dataSize, propType);
+
{
- case kpidIsDir:
- case kpidPath:
- break;
- case kpidSize:
- prop = (UInt64)0;
+ const CUpdatePair2 &up = (*UpdatePairs)[index];
+ /*
+ if (!up.NewData)
+ return E_FAIL;
+ */
+ if (up.IsAnti)
+ return S_OK;
+
+ #ifndef UNDER_CE
+ const CDirItem &di = DirItems->Items[up.DirIndex];
+ #endif
+
+ #ifdef _USE_SECURITY_CODE
+ if (propID == kpidNtSecure)
+ {
+ if (!StoreNtSecurity)
+ return S_OK;
+ if (di.SecureIndex < 0)
+ return S_OK;
+ const CByteBuffer &buf = DirItems->SecureBlocks.Bufs[di.SecureIndex];
+ *data = buf;
+ *dataSize = (UInt32)buf.Size();
+ *propType = NPropDataType::kRaw;
+ }
+ else
+ #endif
+ {
+ // propID == kpidNtReparse
+ if (!StoreSymLinks)
+ return S_OK;
+ #if 0 // #ifndef UNDER_CE
+ const CByteBuffer *buf = &di.ReparseData2;
+ if (buf->Size() == 0)
+ buf = &di.ReparseData;
+ if (buf->Size() != 0)
+ {
+ *data = *buf;
+ *dataSize = (UInt32)buf->Size();
+ *propType = NPropDataType::kRaw;
+ }
+ #endif
+ }
+
+ return S_OK;
+ }
+ }
+
+ return S_OK;
+}
+
+#ifndef UNDER_CE
+
+static UString GetRelativePath(const UString &to, const UString &from)
+{
+ UStringVector partsTo, partsFrom;
+ SplitPathToParts(to, partsTo);
+ SplitPathToParts(from, partsFrom);
+
+ unsigned i;
+ for (i = 0;; i++)
+ {
+ if (i + 1 >= partsFrom.Size() ||
+ i + 1 >= partsTo.Size())
+ break;
+ if (CompareFileNames(partsFrom[i], partsTo[i]) != 0)
+ break;
+ }
+
+ if (i == 0)
+ {
+ #ifdef _WIN32
+ if (NName::IsDrivePath(to) ||
+ NName::IsDrivePath(from))
+ return to;
+ #endif
+ }
+
+ UString s;
+ unsigned k;
+
+ for (k = i + 1; k < partsFrom.Size(); k++)
+ s += L".." WSTRING_PATH_SEPARATOR;
+
+ for (k = i; k < partsTo.Size(); k++)
+ {
+ if (k != i)
+ s += WCHAR_PATH_SEPARATOR;
+ s += partsTo[k];
+ }
+
+ return s;
+}
+
+#endif
+
+STDMETHODIMP CArchiveUpdateCallback::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *value)
+{
+ COM_TRY_BEGIN
+ const CUpdatePair2 &up = (*UpdatePairs)[index];
+ NCOM::CPropVariant prop;
+
+ if (up.NewData)
+ {
+ /*
+ if (propID == kpidIsHardLink)
+ {
+ prop = _isHardLink;
+ prop.Detach(value);
+ return S_OK;
+ }
+ */
+ if (propID == kpidSymLink)
+ {
+ if (index == _hardIndex_From)
+ {
+ prop.Detach(value);
+ return S_OK;
+ }
+ if (up.DirIndex >= 0)
+ {
+ #if 0 // #ifndef UNDER_CE
+ const CDirItem &di = DirItems->Items[up.DirIndex];
+ // if (di.IsDir())
+ {
+ CReparseAttr attr;
+ if (attr.Parse(di.ReparseData, di.ReparseData.Size()))
+ {
+ UString simpleName = attr.GetPath();
+ if (attr.IsRelative())
+ prop = simpleName;
+ else
+ {
+ const UString phyPath = DirItems->GetPhyPath(up.DirIndex);
+ FString fullPath;
+ if (NDir::MyGetFullPathName(us2fs(phyPath), fullPath))
+ {
+ prop = GetRelativePath(simpleName, fs2us(fullPath));
+ }
+ }
+ prop.Detach(value);
+ return S_OK;
+ }
+ }
+ #endif
+ }
+ }
+ else if (propID == kpidHardLink)
+ {
+ if (index == _hardIndex_From)
+ {
+ const CKeyKeyValPair &pair = _map[_hardIndex_To];
+ const CUpdatePair2 &up2 = (*UpdatePairs)[pair.Value];
+ prop = DirItems->GetLogPath(up2.DirIndex);
prop.Detach(value);
return S_OK;
- default:
+ }
+ if (up.DirIndex >= 0)
+ {
prop.Detach(value);
return S_OK;
+ }
}
}
-
- if (up.ExistOnDisk())
+
+ if (up.IsAnti
+ && propID != kpidIsDir
+ && propID != kpidPath
+ && propID != kpidIsAltStream)
+ {
+ switch (propID)
+ {
+ case kpidSize: prop = (UInt64)0; break;
+ case kpidIsAnti: prop = true; break;
+ }
+ }
+ else if (propID == kpidPath && up.NewNameIndex >= 0)
+ prop = (*NewNames)[up.NewNameIndex];
+ else if (propID == kpidShortName && up.NewNameIndex >= 0 && up.IsMainRenameItem)
+ {
+ // we can generate new ShortName here;
+ }
+ else if ((up.UseArcProps
+ || (KeepOriginalItemNames && (propID == kpidPath || propID == kpidIsAltStream)))
+ && up.ExistInArchive() && Archive)
+ return Archive->GetProperty(ArcItems ? (*ArcItems)[up.ArcIndex].IndexInServer : up.ArcIndex, propID, value);
+ else if (up.ExistOnDisk())
{
const CDirItem &di = DirItems->Items[up.DirIndex];
- switch(propID)
+ switch (propID)
{
case kpidPath: prop = DirItems->GetLogPath(up.DirIndex); break;
case kpidIsDir: prop = di.IsDir(); break;
@@ -127,27 +401,10 @@ STDMETHODIMP CArchiveUpdateCallback::GetProperty(UInt32 index, PROPID propID, PR
case kpidCTime: prop = di.CTime; break;
case kpidATime: prop = di.ATime; break;
case kpidMTime: prop = di.MTime; break;
- }
- }
- else
- {
- if (propID == kpidPath)
- {
- if (up.NewNameIndex >= 0)
- {
- prop = (*NewNames)[up.NewNameIndex];
- prop.Detach(value);
- return S_OK;
- }
- }
- if (up.ExistInArchive() && Archive)
- {
- UInt32 indexInArchive;
- if (ArcItems == 0)
- indexInArchive = up.ArcIndex;
- else
- indexInArchive = (*ArcItems)[up.ArcIndex].IndexInServer;
- return Archive->GetProperty(indexInArchive, propID, value);
+ case kpidIsAltStream: prop = di.IsAltStream; break;
+ #if defined(_WIN32) && !defined(UNDER_CE)
+ // case kpidShortName: prop = di.ShortName; break;
+ #endif
}
}
prop.Detach(value);
@@ -155,24 +412,46 @@ STDMETHODIMP CArchiveUpdateCallback::GetProperty(UInt32 index, PROPID propID, PR
COM_TRY_END
}
+static NSynchronization::CCriticalSection CS;
+
STDMETHODIMP CArchiveUpdateCallback::GetStream(UInt32 index, ISequentialInStream **inStream)
{
COM_TRY_BEGIN
+ *inStream = NULL;
const CUpdatePair2 &up = (*UpdatePairs)[index];
if (!up.NewData)
return E_FAIL;
-
+
RINOK(Callback->CheckBreak());
RINOK(Callback->Finilize());
+ bool isDir = IsDir(up);
+
if (up.IsAnti)
{
- return Callback->GetStream((*ArcItems)[up.ArcIndex].Name, true);
+ UString name;
+ if (up.ArcIndex >= 0)
+ name = (*ArcItems)[up.ArcIndex].Name;
+ else if (up.DirIndex >= 0)
+ name = DirItems->GetLogPath(up.DirIndex);
+ RINOK(Callback->GetStream(name, true));
+
+ /* 9.33: fixed. Handlers expect real stream object for files, even for anti-file.
+ so we return empty stream */
+
+ if (!isDir)
+ {
+ CBufInStream *inStreamSpec = new CBufInStream();
+ CMyComPtr<ISequentialInStream> inStreamLoc = inStreamSpec;
+ inStreamSpec->Init(NULL, 0);
+ *inStream = inStreamLoc.Detach();
+ }
+ return S_OK;
}
- const CDirItem &di = DirItems->Items[up.DirIndex];
+
RINOK(Callback->GetStream(DirItems->GetLogPath(up.DirIndex), false));
-
- if (di.IsDir())
+
+ if (isDir)
return S_OK;
if (StdInMode)
@@ -185,13 +464,61 @@ STDMETHODIMP CArchiveUpdateCallback::GetStream(UInt32 index, ISequentialInStream
{
CInFileStream *inStreamSpec = new CInFileStream;
CMyComPtr<ISequentialInStream> inStreamLoc(inStreamSpec);
+
+ inStreamSpec->SupportHardLinks = StoreHardLinks;
+
const UString path = DirItems->GetPhyPath(up.DirIndex);
- if (!inStreamSpec->OpenShared(path, ShareForWrite))
+
+ #if defined(_WIN32) && !defined(UNDER_CE)
+ if (DirItems->Items[up.DirIndex].AreReparseData())
+ {
+ if (!inStreamSpec->File.OpenReparse(us2fs(path)))
+ {
+ return Callback->OpenFileError(path, ::GetLastError());
+ }
+ }
+ else
+ #endif
+ if (!inStreamSpec->OpenShared(us2fs(path), ShareForWrite))
{
return Callback->OpenFileError(path, ::GetLastError());
}
+
+#if 0 // FIXME
+ if (StoreHardLinks)
+ {
+ CStreamFileProps props;
+ if (inStreamSpec->GetProps2(&props) == S_OK)
+ {
+ if (props.NumLinks > 1)
+ {
+ CKeyKeyValPair pair;
+ pair.Key1 = props.VolID;
+ pair.Key2 = props.FileID_Low;
+ pair.Value = index;
+ unsigned numItems = _map.Size();
+ unsigned pairIndex = _map.AddToUniqueSorted2(pair);
+ if (numItems == _map.Size())
+ {
+ // const CKeyKeyValPair &pair2 = _map.Pairs[pairIndex];
+ _hardIndex_From = index;
+ _hardIndex_To = pairIndex;
+ // we could return NULL as stream, but it's better to return real stream
+ // return S_OK;
+ }
+ }
+ }
+ }
+#endif
+
+ if (ProcessedItemsStatuses)
+ {
+ NSynchronization::CCriticalSectionLock lock(CS);
+ ProcessedItemsStatuses[up.DirIndex] = 1;
+ }
*inStream = inStreamLoc.Detach();
}
+
return S_OK;
COM_TRY_END
}
@@ -216,12 +543,12 @@ STDMETHODIMP CArchiveUpdateCallback::GetVolumeSize(UInt32 index, UInt64 *size)
STDMETHODIMP CArchiveUpdateCallback::GetVolumeStream(UInt32 index, ISequentialOutStream **volumeStream)
{
COM_TRY_BEGIN
- wchar_t temp[16];
+ FChar temp[16];
ConvertUInt32ToString(index + 1, temp);
- UString res = temp;
- while (res.Length() < 2)
- res = UString(L'0') + res;
- UString fileName = VolName;
+ FString res = temp;
+ while (res.Len() < 2)
+ res.InsertAtFront(FTEXT('0'));
+ FString fileName = VolName;
fileName += L'.';
fileName += res;
fileName += VolExt;
diff --git a/src/libs/7zip/unix/CPP/7zip/UI/Common/UpdateCallback.h b/src/libs/7zip/unix/CPP/7zip/UI/Common/UpdateCallback.h
index 9a20c3159..81982e61d 100644
--- a/src/libs/7zip/unix/CPP/7zip/UI/Common/UpdateCallback.h
+++ b/src/libs/7zip/unix/CPP/7zip/UI/Common/UpdateCallback.h
@@ -1,10 +1,9 @@
// UpdateCallback.h
-#ifndef __UPDATECALLBACK_H
-#define __UPDATECALLBACK_H
+#ifndef __UPDATE_CALLBACK_H
+#define __UPDATE_CALLBACK_H
-#include "Common/MyCom.h"
-#include "Common/MyString.h"
+#include "../../../Common/MyCom.h"
#include "../../IPassword.h"
#include "../../ICoder.h"
@@ -32,16 +31,43 @@ struct IUpdateCallbackUI
INTERFACE_IUpdateCallbackUI(=0)
};
+struct CKeyKeyValPair
+{
+ UInt64 Key1;
+ UInt64 Key2;
+ unsigned Value;
+
+ int Compare(const CKeyKeyValPair &a) const
+ {
+ if (Key1 < a.Key1) return -1;
+ if (Key1 > a.Key1) return 1;
+ return MyCompare(Key2, a.Key2);
+ }
+};
+
+
class CArchiveUpdateCallback:
public IArchiveUpdateCallback2,
+ public IArchiveGetRawProps,
+ public IArchiveGetRootProps,
public ICryptoGetTextPassword2,
public ICryptoGetTextPassword,
public ICompressProgressInfo,
public CMyUnknownImp
{
+ #if defined(_WIN32) && !defined(UNDER_CE)
+ bool _saclEnabled;
+ #endif
+ CRecordVector<CKeyKeyValPair> _map;
+
+ UInt32 _hardIndex_From;
+ UInt32 _hardIndex_To;
+
public:
- MY_UNKNOWN_IMP4(
+ MY_UNKNOWN_IMP6(
IArchiveUpdateCallback2,
+ IArchiveGetRawProps,
+ IArchiveGetRootProps,
ICryptoGetTextPassword2,
ICryptoGetTextPassword,
ICompressProgressInfo)
@@ -49,26 +75,48 @@ public:
STDMETHOD(SetRatioInfo)(const UInt64 *inSize, const UInt64 *outSize);
INTERFACE_IArchiveUpdateCallback2(;)
+ INTERFACE_IArchiveGetRawProps(;)
+ INTERFACE_IArchiveGetRootProps(;)
STDMETHOD(CryptoGetTextPassword2)(Int32 *passwordIsDefined, BSTR *password);
STDMETHOD(CryptoGetTextPassword)(BSTR *password);
-public:
CRecordVector<UInt64> VolumesSizes;
- UString VolName;
- UString VolExt;
+ FString VolName;
+ FString VolExt;
IUpdateCallbackUI *Callback;
bool ShareForWrite;
bool StdInMode;
+
const CDirItems *DirItems;
+ const CDirItem *ParentDirItem;
+
const CObjectVector<CArcItem> *ArcItems;
const CRecordVector<CUpdatePair2> *UpdatePairs;
const UStringVector *NewNames;
CMyComPtr<IInArchive> Archive;
+ CMyComPtr<IArchiveGetRawProps> GetRawProps;
+ CMyComPtr<IArchiveGetRootProps> GetRootProps;
+
+ bool KeepOriginalItemNames;
+ bool StoreNtSecurity;
+ bool StoreHardLinks;
+ bool StoreSymLinks;
+
+ Byte *ProcessedItemsStatuses;
CArchiveUpdateCallback();
+
+ bool IsDir(const CUpdatePair2 &up) const
+ {
+ if (up.DirIndex >= 0)
+ return DirItems->Items[up.DirIndex].IsDir();
+ else if (up.ArcIndex >= 0)
+ return (*ArcItems)[up.ArcIndex].IsDir;
+ return false;
+ }
};
#endif
diff --git a/src/libs/7zip/unix/CPP/7zip/UI/Common/UpdatePair.cpp b/src/libs/7zip/unix/CPP/7zip/UI/Common/UpdatePair.cpp
index d9396a583..95afdd694 100644
--- a/src/libs/7zip/unix/CPP/7zip/UI/Common/UpdatePair.cpp
+++ b/src/libs/7zip/unix/CPP/7zip/UI/Common/UpdatePair.cpp
@@ -4,10 +4,9 @@
#include <time.h>
-#include "Common/Defs.h"
-#include "Common/Wildcard.h"
+#include "../../../Common/Wildcard.h"
-#include "Windows/Time.h"
+#include "../../../Windows/TimeUtils.h"
#include "SortUtils.h"
#include "UpdatePair.h"
@@ -17,7 +16,7 @@ using namespace NTime;
static int MyCompareTime(NFileTimeType::EEnum fileTimeType, const FILETIME &time1, const FILETIME &time2)
{
- switch(fileTimeType)
+ switch (fileTimeType)
{
case NFileTimeType::kWindows:
return ::CompareFileTime(&time1, &time2);
@@ -28,28 +27,49 @@ static int MyCompareTime(NFileTimeType::EEnum fileTimeType, const FILETIME &time
FileTimeToUnixTime(time2, unixTime2);
return MyCompare(unixTime1, unixTime2);
}
+ case NFileTimeType::kDOS:
+ {
+ UInt32 dosTime1, dosTime2;
+ FileTimeToDosTime(time1, dosTime1);
+ FileTimeToDosTime(time2, dosTime2);
+ return MyCompare(dosTime1, dosTime2);
+ }
}
throw 4191618;
}
-static const wchar_t *kDuplicateFileNameMessage = L"Duplicate filename:";
-static const wchar_t *kNotCensoredCollisionMessaged = L"Internal file name collision (file on disk, file in archive):";
+static const char *k_Duplicate_inArc_Message = "Duplicate filename in archive:";
+static const char *k_Duplicate_inDir_Message = "Duplicate filename on disk:";
+static const char *k_NotCensoredCollision_Message = "Internal file name collision (file on disk, file in archive):";
-static void ThrowError(const UString &message, const UString &s1, const UString &s2)
+static void ThrowError(const char *message, const UString &s1, const UString &s2)
{
- UString m = message;
- m += L'\n';
- m += s1;
- m += L'\n';
- m += s2;
+ UString m;
+ m.SetFromAscii(message);
+ m += L'\n'; m += s1;
+ m += L'\n'; m += s2;
throw m;
}
-static void TestDuplicateString(const UStringVector &strings, const CIntVector &indices)
+static int CompareArcItemsBase(const CArcItem &ai1, const CArcItem &ai2)
{
- for(int i = 0; i + 1 < indices.Size(); i++)
- if (CompareFileNames(strings[indices[i]], strings[indices[i + 1]]) == 0)
- ThrowError(kDuplicateFileNameMessage, strings[indices[i]], strings[indices[i + 1]]);
+ int res = CompareFileNames(ai1.Name, ai2.Name);
+ if (res != 0)
+ return res;
+ if (ai1.IsDir != ai2.IsDir)
+ return ai1.IsDir ? -1 : 1;
+ return 0;
+}
+
+static int CompareArcItems(const unsigned *p1, const unsigned *p2, void *param)
+{
+ unsigned i1 = *p1;
+ unsigned i2 = *p2;
+ const CObjectVector<CArcItem> &arcItems = *(const CObjectVector<CArcItem> *)param;
+ int res = CompareArcItemsBase(arcItems[i1], arcItems[i2]);
+ if (res != 0)
+ return res;
+ return MyCompare(i1, i2);
}
void GetUpdatePairInfoList(
@@ -58,48 +78,103 @@ void GetUpdatePairInfoList(
NFileTimeType::EEnum fileTimeType,
CRecordVector<CUpdatePair> &updatePairs)
{
- CIntVector dirIndices, arcIndices;
-
- int numDirItems = dirItems.Items.Size();
- int numArcItems = arcItems.Size();
-
-
+ CUIntVector dirIndices, arcIndices;
+
+ unsigned numDirItems = dirItems.Items.Size();
+ unsigned numArcItems = arcItems.Size();
+
+ CIntArr duplicatedArcItem(numArcItems);
{
- UStringVector arcNames;
- arcNames.Reserve(numArcItems);
- for (int i = 0; i < numArcItems; i++)
- arcNames.Add(arcItems[i].Name);
- SortFileNames(arcNames, arcIndices);
- TestDuplicateString(arcNames, arcIndices);
+ int *vals = &duplicatedArcItem[0];
+ for (unsigned i = 0; i < numArcItems; i++)
+ vals[i] = 0;
+ }
+
+ {
+ arcIndices.ClearAndSetSize(numArcItems);
+ {
+ unsigned *vals = &arcIndices[0];
+ for (unsigned i = 0; i < numArcItems; i++)
+ vals[i] = i;
+ }
+ arcIndices.Sort(CompareArcItems, (void *)&arcItems);
+ for (unsigned i = 0; i + 1 < numArcItems; i++)
+ if (CompareArcItemsBase(
+ arcItems[arcIndices[i]],
+ arcItems[arcIndices[i + 1]]) == 0)
+ {
+ duplicatedArcItem[i] = 1;
+ duplicatedArcItem[i + 1] = -1;
+ }
}
UStringVector dirNames;
{
- dirNames.Reserve(numDirItems);
- for (int i = 0; i < numDirItems; i++)
- dirNames.Add(dirItems.GetLogPath(i));
+ dirNames.ClearAndReserve(numDirItems);
+ unsigned i;
+ for (i = 0; i < numDirItems; i++)
+ dirNames.AddInReserved(dirItems.GetLogPath(i));
SortFileNames(dirNames, dirIndices);
- TestDuplicateString(dirNames, dirIndices);
+ for (i = 0; i + 1 < numDirItems; i++)
+ {
+ const UString &s1 = dirNames[dirIndices[i]];
+ const UString &s2 = dirNames[dirIndices[i + 1]];
+ if (CompareFileNames(s1, s2) == 0)
+ ThrowError(k_Duplicate_inDir_Message, s1, s2);
+ }
}
-
- int dirIndex = 0, arcIndex = 0;
- while (dirIndex < numDirItems && arcIndex < numArcItems)
+
+ unsigned dirIndex = 0;
+ unsigned arcIndex = 0;
+
+ int prevHostFile = -1;
+ const UString *prevHostName = NULL;
+
+ while (dirIndex < numDirItems || arcIndex < numArcItems)
{
CUpdatePair pair;
- int dirIndex2 = dirIndices[dirIndex];
- int arcIndex2 = arcIndices[arcIndex];
- const CDirItem &di = dirItems.Items[dirIndex2];
- const CArcItem &ai = arcItems[arcIndex2];
- int compareResult = CompareFileNames(dirNames[dirIndex2], ai.Name);
+
+ int dirIndex2 = -1;
+ int arcIndex2 = -1;
+ const CDirItem *di = NULL;
+ const CArcItem *ai = NULL;
+
+ int compareResult = -1;
+ const UString *name = NULL;
+
+ if (dirIndex < numDirItems)
+ {
+ dirIndex2 = dirIndices[dirIndex];
+ di = &dirItems.Items[dirIndex2];
+ }
+
+ if (arcIndex < numArcItems)
+ {
+ arcIndex2 = arcIndices[arcIndex];
+ ai = &arcItems[arcIndex2];
+ compareResult = 1;
+ if (dirIndex < numDirItems)
+ {
+ compareResult = CompareFileNames(dirNames[dirIndex2], ai->Name);
+ if (compareResult == 0)
+ {
+ if (di->IsDir() != ai->IsDir)
+ compareResult = (ai->IsDir ? 1 : -1);
+ }
+ }
+ }
+
if (compareResult < 0)
{
+ name = &dirNames[dirIndex2];
pair.State = NUpdateArchive::NPairState::kOnlyOnDisk;
pair.DirIndex = dirIndex2;
dirIndex++;
}
else if (compareResult > 0)
{
- pair.State = ai.Censored ?
+ name = &ai->Name;
+ pair.State = ai->Censored ?
NUpdateArchive::NPairState::kOnlyInArchive:
NUpdateArchive::NPairState::kNotMasked;
pair.ArcIndex = arcIndex2;
@@ -107,43 +182,50 @@ void GetUpdatePairInfoList(
}
else
{
- if (!ai.Censored)
- ThrowError(kNotCensoredCollisionMessaged, dirNames[dirIndex2], ai.Name);
+ int dupl = duplicatedArcItem[arcIndex];
+ if (dupl != 0)
+ ThrowError(k_Duplicate_inArc_Message, ai->Name, arcItems[arcIndices[arcIndex + dupl]].Name);
+
+ name = &dirNames[dirIndex2];
+ if (!ai->Censored)
+ ThrowError(k_NotCensoredCollision_Message, *name, ai->Name);
+
pair.DirIndex = dirIndex2;
pair.ArcIndex = arcIndex2;
- switch (ai.MTimeDefined ? MyCompareTime(
- ai.TimeType != - 1 ? (NFileTimeType::EEnum)ai.TimeType : fileTimeType,
- di.MTime, ai.MTime): 0)
+
+ switch (ai->MTimeDefined ? MyCompareTime(
+ ai->TimeType != - 1 ? (NFileTimeType::EEnum)ai->TimeType : fileTimeType,
+ di->MTime, ai->MTime): 0)
{
case -1: pair.State = NUpdateArchive::NPairState::kNewInArchive; break;
- case 1: pair.State = NUpdateArchive::NPairState::kOldInArchive; break;
+ case 1: pair.State = NUpdateArchive::NPairState::kOldInArchive; break;
default:
- pair.State = (ai.SizeDefined && di.Size == ai.Size) ?
+ pair.State = (ai->SizeDefined && di->Size == ai->Size) ?
NUpdateArchive::NPairState::kSameFiles :
NUpdateArchive::NPairState::kUnknowNewerFiles;
}
+
dirIndex++;
arcIndex++;
}
- updatePairs.Add(pair);
- }
- for (; dirIndex < numDirItems; dirIndex++)
- {
- CUpdatePair pair;
- pair.State = NUpdateArchive::NPairState::kOnlyOnDisk;
- pair.DirIndex = dirIndices[dirIndex];
- updatePairs.Add(pair);
- }
-
- for (; arcIndex < numArcItems; arcIndex++)
- {
- CUpdatePair pair;
- int arcIndex2 = arcIndices[arcIndex];
- pair.State = arcItems[arcIndex2].Censored ?
- NUpdateArchive::NPairState::kOnlyInArchive:
- NUpdateArchive::NPairState::kNotMasked;
- pair.ArcIndex = arcIndex2;
+ if ((di && di->IsAltStream) ||
+ (ai && ai->IsAltStream))
+ {
+ if (prevHostName)
+ {
+ unsigned hostLen = prevHostName->Len();
+ if (name->Len() > hostLen)
+ if ((*name)[hostLen] == ':' && CompareFileNames(*prevHostName, name->Left(hostLen)) == 0)
+ pair.HostIndex = prevHostFile;
+ }
+ }
+ else
+ {
+ prevHostFile = updatePairs.Size();
+ prevHostName = name;
+ }
+
updatePairs.Add(pair);
}
diff --git a/src/libs/7zip/unix/CPP/7zip/UI/Common/UpdatePair.h b/src/libs/7zip/unix/CPP/7zip/UI/Common/UpdatePair.h
index 3a332649c..296d3b097 100644
--- a/src/libs/7zip/unix/CPP/7zip/UI/Common/UpdatePair.h
+++ b/src/libs/7zip/unix/CPP/7zip/UI/Common/UpdatePair.h
@@ -13,7 +13,9 @@ struct CUpdatePair
NUpdateArchive::NPairState::EEnum State;
int ArcIndex;
int DirIndex;
- CUpdatePair(): ArcIndex(-1), DirIndex(-1) {}
+ int HostIndex; // >= 0 for alt streams only, contains index of host pair
+
+ CUpdatePair(): ArcIndex(-1), DirIndex(-1), HostIndex(-1) {}
};
void GetUpdatePairInfoList(
diff --git a/src/libs/7zip/unix/CPP/7zip/UI/Common/UpdateProduce.cpp b/src/libs/7zip/unix/CPP/7zip/UI/Common/UpdateProduce.cpp
index c21db3b2a..2c4c28583 100644
--- a/src/libs/7zip/unix/CPP/7zip/UI/Common/UpdateProduce.cpp
+++ b/src/libs/7zip/unix/CPP/7zip/UI/Common/UpdateProduce.cpp
@@ -14,17 +14,17 @@ void UpdateProduce(
CRecordVector<CUpdatePair2> &operationChain,
IUpdateProduceCallback *callback)
{
- for (int i = 0; i < updatePairs.Size(); i++)
+ FOR_VECTOR (i, updatePairs)
{
const CUpdatePair &pair = updatePairs[i];
CUpdatePair2 up2;
- up2.IsAnti = false;
up2.DirIndex = pair.DirIndex;
up2.ArcIndex = pair.ArcIndex;
up2.NewData = up2.NewProps = true;
-
- switch(actionSet.StateActions[pair.State])
+ up2.UseArcProps = false;
+
+ switch (actionSet.StateActions[pair.State])
{
case NPairAction::kIgnore:
/*
@@ -39,17 +39,32 @@ void UpdateProduce(
case NPairAction::kCopy:
if (pair.State == NPairState::kOnlyOnDisk)
throw kUpdateActionSetCollision;
+ if (pair.State == NPairState::kOnlyInArchive)
+ {
+ if (pair.HostIndex >= 0)
+ {
+ /*
+ ignore alt stream if
+ 1) no such alt stream in Disk
+ 2) there is Host file in disk
+ */
+ if (updatePairs[pair.HostIndex].DirIndex >= 0)
+ continue;
+ }
+ }
up2.NewData = up2.NewProps = false;
+ up2.UseArcProps = true;
break;
-
+
case NPairAction::kCompress:
if (pair.State == NPairState::kOnlyInArchive ||
pair.State == NPairState::kNotMasked)
throw kUpdateActionSetCollision;
break;
-
+
case NPairAction::kCompressAsAnti:
up2.IsAnti = true;
+ up2.UseArcProps = (pair.ArcIndex >= 0);
break;
}
operationChain.Add(up2);
diff --git a/src/libs/7zip/unix/CPP/7zip/UI/Common/UpdateProduce.h b/src/libs/7zip/unix/CPP/7zip/UI/Common/UpdateProduce.h
index e18648cd9..ef7b0f7a3 100644
--- a/src/libs/7zip/unix/CPP/7zip/UI/Common/UpdateProduce.h
+++ b/src/libs/7zip/unix/CPP/7zip/UI/Common/UpdateProduce.h
@@ -9,16 +9,36 @@ struct CUpdatePair2
{
bool NewData;
bool NewProps;
- bool IsAnti;
-
+ bool UseArcProps; // if (UseArcProps && NewProps), we want to change only some properties.
+ bool IsAnti; // if (!IsAnti) we use other ways to detect Anti status
+
int DirIndex;
int ArcIndex;
int NewNameIndex;
+ bool IsMainRenameItem;
+
+ void SetAs_NoChangeArcItem(int arcIndex)
+ {
+ NewData = NewProps = false;
+ UseArcProps = true;
+ IsAnti = false;
+ ArcIndex = arcIndex;
+ }
+
bool ExistOnDisk() const { return DirIndex != -1; }
bool ExistInArchive() const { return ArcIndex != -1; }
- CUpdatePair2(): IsAnti(false), DirIndex(-1), ArcIndex(-1), NewNameIndex(-1) {}
+ CUpdatePair2():
+ NewData(false),
+ NewProps(false),
+ UseArcProps(false),
+ IsAnti(false),
+ DirIndex(-1),
+ ArcIndex(-1),
+ NewNameIndex(-1),
+ IsMainRenameItem(false)
+ {}
};
struct IUpdateProduceCallback
diff --git a/src/libs/7zip/unix/CPP/7zip/UI/Common/WorkDir.cpp b/src/libs/7zip/unix/CPP/7zip/UI/Common/WorkDir.cpp
deleted file mode 100644
index 28d36df9e..000000000
--- a/src/libs/7zip/unix/CPP/7zip/UI/Common/WorkDir.cpp
+++ /dev/null
@@ -1,59 +0,0 @@
-// WorkDir.cpp
-
-#include "StdAfx.h"
-
-#include "Common/StringConvert.h"
-#include "Common/Wildcard.h"
-
-#include "Windows/FileDir.h"
-#include "Windows/FileName.h"
-
-#include "WorkDir.h"
-
-using namespace NWindows;
-using namespace NFile;
-
-UString GetWorkDir(const NWorkDir::CInfo &workDirInfo, const UString &path)
-{
- NWorkDir::NMode::EEnum mode = workDirInfo.Mode;
- #if !defined(UNDER_CE) && defined(_WIN32)
- if (workDirInfo.ForRemovableOnly)
- {
- mode = NWorkDir::NMode::kCurrent;
- UString prefix = path.Left(3);
- if (prefix[1] == L':' && prefix[2] == L'\\')
- {
- UINT driveType = GetDriveType(GetSystemString(prefix, ::AreFileApisANSI() ? CP_ACP : CP_OEMCP));
- if (driveType == DRIVE_CDROM || driveType == DRIVE_REMOVABLE)
- mode = workDirInfo.Mode;
- }
- /*
- CParsedPath parsedPath;
- parsedPath.ParsePath(archiveName);
- UINT driveType = GetDriveType(parsedPath.Prefix);
- if ((driveType != DRIVE_CDROM) && (driveType != DRIVE_REMOVABLE))
- mode = NZipSettings::NWorkDir::NMode::kCurrent;
- */
- }
- #endif
- switch(mode)
- {
- case NWorkDir::NMode::kCurrent:
- {
- return ExtractDirPrefixFromPath(path);
- }
- case NWorkDir::NMode::kSpecified:
- {
- UString tempDir = workDirInfo.Path;
- NName::NormalizeDirPathPrefix(tempDir);
- return tempDir;
- }
- default:
- {
- UString tempDir;
- if (!NDirectory::MyGetTempPath(tempDir))
- throw 141717;
- return tempDir;
- }
- }
-}
diff --git a/src/libs/7zip/unix/CPP/7zip/UI/Common/WorkDir.h b/src/libs/7zip/unix/CPP/7zip/UI/Common/WorkDir.h
deleted file mode 100644
index 0643d67a4..000000000
--- a/src/libs/7zip/unix/CPP/7zip/UI/Common/WorkDir.h
+++ /dev/null
@@ -1,10 +0,0 @@
-// WorkDir.h
-
-#ifndef __WORKDIR_H
-#define __WORKDIR_H
-
-#include "ZipRegistry.h"
-
-UString GetWorkDir(const NWorkDir::CInfo &workDirInfo, const UString &path);
-
-#endif
diff --git a/src/libs/7zip/unix/CPP/7zip/UI/Common/ZipRegistry.h b/src/libs/7zip/unix/CPP/7zip/UI/Common/ZipRegistry.h
deleted file mode 100644
index 378353868..000000000
--- a/src/libs/7zip/unix/CPP/7zip/UI/Common/ZipRegistry.h
+++ /dev/null
@@ -1,105 +0,0 @@
-// ZipRegistry.h
-
-#ifndef __ZIP_REGISTRY_H
-#define __ZIP_REGISTRY_H
-
-#include "Common/MyString.h"
-#include "Common/Types.h"
-
-#include "ExtractMode.h"
-
-namespace NExtract
-{
- struct CInfo
- {
- NPathMode::EEnum PathMode;
- NOverwriteMode::EEnum OverwriteMode;
- bool ShowPassword;
- UStringVector Paths;
-
- void Save() const;
- void Load();
- };
-}
-
-namespace NCompression
-{
- struct CFormatOptions
- {
- UInt32 Level;
- UInt32 Dictionary;
- UInt32 Order;
- UInt32 BlockLogSize;
- UInt32 NumThreads;
-
- CSysString FormatID;
- UString Method;
- UString Options;
- UString EncryptionMethod;
-
- void ResetForLevelChange()
- {
- BlockLogSize = NumThreads = Level = Dictionary = Order = UInt32(-1);
- Method.Empty();
- // Options.Empty();
- // EncryptionMethod.Empty();
- }
- CFormatOptions() { ResetForLevelChange(); }
- };
-
- struct CInfo
- {
- UInt32 Level;
- bool ShowPassword;
- bool EncryptHeaders;
- UString ArcType;
- UStringVector ArcPaths;
-
- CObjectVector<CFormatOptions> Formats;
-
- void Save() const;
- void Load();
- };
-}
-
-namespace NWorkDir
-{
- namespace NMode
- {
- enum EEnum
- {
- kSystem,
- kCurrent,
- kSpecified
- };
- }
- struct CInfo
- {
- NMode::EEnum Mode;
- UString Path;
- bool ForRemovableOnly;
-
- void SetForRemovableOnlyDefault() { ForRemovableOnly = true; }
- void SetDefault()
- {
- Mode = NMode::kSystem;
- Path.Empty();
- SetForRemovableOnlyDefault();
- }
-
- void Save() const;
- void Load();
- };
-}
-
-
-struct CContextMenuInfo
-{
- bool Cascaded;
- UInt32 Flags;
-
- void Save() const;
- void Load();
-};
-
-#endif
diff --git a/src/libs/7zip/unix/CPP/7zip/UI/Console/BenchCon.cpp b/src/libs/7zip/unix/CPP/7zip/UI/Console/BenchCon.cpp
deleted file mode 100644
index 35e868c9b..000000000
--- a/src/libs/7zip/unix/CPP/7zip/UI/Console/BenchCon.cpp
+++ /dev/null
@@ -1,297 +0,0 @@
-// BenchCon.cpp
-
-#include "StdAfx.h"
-
-#include "../../../Common/IntToString.h"
-#include "../../../Common/MyCom.h"
-
-#if !defined(_7ZIP_ST) || defined(_WIN32)
-#include "../../../Windows/System.h"
-#endif
-
-#include "../Common/Bench.h"
-
-#include "BenchCon.h"
-#include "ConsoleClose.h"
-
-struct CTotalBenchRes
-{
- UInt64 NumIterations;
- UInt64 Rating;
- UInt64 Usage;
- UInt64 RPU;
- void Init() { NumIterations = 0; Rating = 0; Usage = 0; RPU = 0; }
- void Normalize()
- {
- if (NumIterations == 0)
- return;
- Rating /= NumIterations;
- Usage /= NumIterations;
- RPU /= NumIterations;
- NumIterations = 1;
- }
- void SetMid(const CTotalBenchRes &r1, const CTotalBenchRes &r2)
- {
- Rating = (r1.Rating + r2.Rating) / 2;
- Usage = (r1.Usage + r2.Usage) / 2;
- RPU = (r1.RPU + r2.RPU) / 2;
- NumIterations = (r1.NumIterations + r2.NumIterations) / 2;
- }
-};
-
-struct CBenchCallback: public IBenchCallback
-{
- CTotalBenchRes EncodeRes;
- CTotalBenchRes DecodeRes;
- FILE *f;
- void Init() { EncodeRes.Init(); DecodeRes.Init(); }
- void Normalize() { EncodeRes.Normalize(); DecodeRes.Normalize(); }
- UInt32 dictionarySize;
- HRESULT SetEncodeResult(const CBenchInfo &info, bool final);
- HRESULT SetDecodeResult(const CBenchInfo &info, bool final);
-};
-
-static void NormalizeVals(UInt64 &v1, UInt64 &v2)
-{
- while (v1 > 1000000)
- {
- v1 >>= 1;
- v2 >>= 1;
- }
-}
-
-static UInt64 MyMultDiv64(UInt64 value, UInt64 elapsedTime, UInt64 freq)
-{
- UInt64 elTime = elapsedTime;
- NormalizeVals(freq, elTime);
- if (elTime == 0)
- elTime = 1;
- return value * freq / elTime;
-}
-
-static void PrintNumber(FILE *f, UInt64 value, int size)
-{
- char s[32];
- ConvertUInt64ToString(value, s);
- fprintf(f, " ");
- for (int len = (int)strlen(s); len < size; len++)
- fprintf(f, " ");
- fputs(s, f);
-}
-
-static void PrintRating(FILE *f, UInt64 rating)
-{
- PrintNumber(f, rating / 1000000, 6);
-}
-
-static void PrintResults(FILE *f, UInt64 usage, UInt64 rpu, UInt64 rating)
-{
- PrintNumber(f, (usage + 5000) / 10000, 5);
- PrintRating(f, rpu);
- PrintRating(f, rating);
-}
-
-
-static void PrintResults(FILE *f, const CBenchInfo &info, UInt64 rating, CTotalBenchRes &res)
-{
- UInt64 speed = MyMultDiv64(info.UnpackSize, info.GlobalTime, info.GlobalFreq);
- PrintNumber(f, speed / 1024, 7);
- UInt64 usage = GetUsage(info);
- UInt64 rpu = GetRatingPerUsage(info, rating);
- PrintResults(f, usage, rpu, rating);
- res.NumIterations++;
- res.RPU += rpu;
- res.Rating += rating;
- res.Usage += usage;
-}
-
-static void PrintTotals(FILE *f, const CTotalBenchRes &res)
-{
- fprintf(f, " ");
- PrintResults(f, res.Usage, res.RPU, res.Rating);
-}
-
-
-HRESULT CBenchCallback::SetEncodeResult(const CBenchInfo &info, bool final)
-{
- if (NConsoleClose::TestBreakSignal())
- return E_ABORT;
- if (final)
- {
- UInt64 rating = GetCompressRating(dictionarySize, info.GlobalTime, info.GlobalFreq, info.UnpackSize);
- PrintResults(f, info, rating, EncodeRes);
- }
- return S_OK;
-}
-
-static const char *kSep = " | ";
-
-
-HRESULT CBenchCallback::SetDecodeResult(const CBenchInfo &info, bool final)
-{
- if (NConsoleClose::TestBreakSignal())
- return E_ABORT;
- if (final)
- {
- UInt64 rating = GetDecompressRating(info.GlobalTime, info.GlobalFreq, info.UnpackSize, info.PackSize, info.NumIterations);
- fputs(kSep, f);
- CBenchInfo info2 = info;
- info2.UnpackSize *= info2.NumIterations;
- info2.PackSize *= info2.NumIterations;
- info2.NumIterations = 1;
- PrintResults(f, info2, rating, DecodeRes);
- }
- return S_OK;
-}
-
-static void PrintRequirements(FILE *f, const char *sizeString, UInt64 size, const char *threadsString, UInt32 numThreads)
-{
- fprintf(f, "\nRAM %s ", sizeString);
- PrintNumber(f, (size >> 20), 5);
- fprintf(f, " MB, # %s %3d", threadsString, (unsigned int)numThreads);
-}
-
-HRESULT LzmaBenchCon(
- DECL_EXTERNAL_CODECS_LOC_VARS
- FILE *f, UInt32 numIterations, UInt32 numThreads, UInt32 dictionary)
-{
- if (!CrcInternalTest())
- return S_FALSE;
- #ifndef _7ZIP_ST
- UInt64 ramSize = NWindows::NSystem::GetRamSize(); //
- UInt32 numCPUs = NWindows::NSystem::GetNumberOfProcessors();
- PrintRequirements(f, "size: ", ramSize, "CPU hardware threads:", numCPUs);
- if (numThreads == (UInt32)-1)
- numThreads = numCPUs;
- if (numThreads > 1)
- numThreads &= ~1;
- if (dictionary == (UInt32)-1)
- {
- int dicSizeLog;
- for (dicSizeLog = 25; dicSizeLog > kBenchMinDicLogSize; dicSizeLog--)
- if (GetBenchMemoryUsage(numThreads, ((UInt32)1 << dicSizeLog)) + (8 << 20) <= ramSize)
- break;
- dictionary = (1 << dicSizeLog);
- }
- #else
- if (dictionary == (UInt32)-1)
- dictionary = (1 << 22);
- numThreads = 1;
- #endif
-
- PrintRequirements(f, "usage:", GetBenchMemoryUsage(numThreads, dictionary), "Benchmark threads: ", numThreads);
-
- CBenchCallback callback;
- callback.Init();
- callback.f = f;
-
- fprintf(f, "\n\nDict Compressing | Decompressing\n ");
- int j;
- for (j = 0; j < 2; j++)
- {
- fprintf(f, " Speed Usage R/U Rating");
- if (j == 0)
- fputs(kSep, f);
- }
- fprintf(f, "\n ");
- for (j = 0; j < 2; j++)
- {
- fprintf(f, " KB/s %% MIPS MIPS");
- if (j == 0)
- fputs(kSep, f);
- }
- fprintf(f, "\n\n");
- for (UInt32 i = 0; i < numIterations; i++)
- {
- const int kStartDicLog = 22;
- int pow = (dictionary < ((UInt32)1 << kStartDicLog)) ? kBenchMinDicLogSize : kStartDicLog;
- while (((UInt32)1 << pow) > dictionary)
- pow--;
- for (; ((UInt32)1 << pow) <= dictionary; pow++)
- {
- fprintf(f, "%2d:", pow);
- callback.dictionarySize = (UInt32)1 << pow;
- HRESULT res = LzmaBench(
- EXTERNAL_CODECS_LOC_VARS
- numThreads, callback.dictionarySize, &callback);
- fprintf(f, "\n");
- RINOK(res);
- }
- }
- callback.Normalize();
- fprintf(f, "----------------------------------------------------------------\nAvr:");
- PrintTotals(f, callback.EncodeRes);
- fprintf(f, " ");
- PrintTotals(f, callback.DecodeRes);
- fprintf(f, "\nTot:");
- CTotalBenchRes midRes;
- midRes.SetMid(callback.EncodeRes, callback.DecodeRes);
- PrintTotals(f, midRes);
- fprintf(f, "\n");
- return S_OK;
-}
-
-struct CTempValues
-{
- UInt64 *Values;
- CTempValues(UInt32 num) { Values = new UInt64[num]; }
- ~CTempValues() { delete []Values; }
-};
-
-HRESULT CrcBenchCon(FILE *f, UInt32 numIterations, UInt32 numThreads, UInt32 dictionary)
-{
- if (!CrcInternalTest())
- return S_FALSE;
-
- #ifndef _7ZIP_ST
- UInt64 ramSize = NWindows::NSystem::GetRamSize();
- UInt32 numCPUs = NWindows::NSystem::GetNumberOfProcessors();
- PrintRequirements(f, "size: ", ramSize, "CPU hardware threads:", numCPUs);
- if (numThreads == (UInt32)-1)
- numThreads = numCPUs;
- #else
- numThreads = 1;
- #endif
- if (dictionary == (UInt32)-1)
- dictionary = (1 << 24);
-
- CTempValues speedTotals(numThreads);
- fprintf(f, "\n\nSize");
- for (UInt32 ti = 0; ti < numThreads; ti++)
- {
- fprintf(f, " %5d", ti + 1);
- speedTotals.Values[ti] = 0;
- }
- fprintf(f, "\n\n");
-
- UInt64 numSteps = 0;
- for (UInt32 i = 0; i < numIterations; i++)
- {
- for (int pow = 10; pow < 32; pow++)
- {
- UInt32 bufSize = (UInt32)1 << pow;
- if (bufSize > dictionary)
- break;
- fprintf(f, "%2d: ", pow);
- UInt64 speed;
- for (UInt32 ti = 0; ti < numThreads; ti++)
- {
- if (NConsoleClose::TestBreakSignal())
- return E_ABORT;
- RINOK(CrcBench(ti + 1, bufSize, speed));
- PrintNumber(f, (speed >> 20), 5);
- speedTotals.Values[ti] += speed;
- }
- fprintf(f, "\n");
- numSteps++;
- }
- }
- if (numSteps != 0)
- {
- fprintf(f, "\nAvg:");
- for (UInt32 ti = 0; ti < numThreads; ti++)
- PrintNumber(f, ((speedTotals.Values[ti] / numSteps) >> 20), 5);
- fprintf(f, "\n");
- }
- return S_OK;
-}
diff --git a/src/libs/7zip/unix/CPP/7zip/UI/Console/BenchCon.h b/src/libs/7zip/unix/CPP/7zip/UI/Console/BenchCon.h
deleted file mode 100644
index 966a83a6a..000000000
--- a/src/libs/7zip/unix/CPP/7zip/UI/Console/BenchCon.h
+++ /dev/null
@@ -1,16 +0,0 @@
-// BenchCon.h
-
-#ifndef __BENCH_CON_H
-#define __BENCH_CON_H
-
-#include <stdio.h>
-
-#include "../../Common/CreateCoder.h"
-
-HRESULT LzmaBenchCon(
- DECL_EXTERNAL_CODECS_LOC_VARS
- FILE *f, UInt32 numIterations, UInt32 numThreads, UInt32 dictionary);
-
-HRESULT CrcBenchCon(FILE *f, UInt32 numIterations, UInt32 numThreads, UInt32 dictionary);
-
-#endif
diff --git a/src/libs/7zip/unix/CPP/7zip/UI/Console/Console.pri b/src/libs/7zip/unix/CPP/7zip/UI/Console/Console.pri
new file mode 100644
index 000000000..cdb025475
--- /dev/null
+++ b/src/libs/7zip/unix/CPP/7zip/UI/Console/Console.pri
@@ -0,0 +1,2 @@
+HEADERS += $$7ZIP_BASE/CPP/7zip/UI/Console/PercentPrinter.h
+SOURCES += $$7ZIP_BASE/CPP/7zip/UI/Console/PercentPrinter.cpp
diff --git a/src/libs/7zip/unix/CPP/7zip/UI/Console/ConsoleClose.cpp b/src/libs/7zip/unix/CPP/7zip/UI/Console/ConsoleClose.cpp
deleted file mode 100644
index 9bb2082bf..000000000
--- a/src/libs/7zip/unix/CPP/7zip/UI/Console/ConsoleClose.cpp
+++ /dev/null
@@ -1,49 +0,0 @@
-// ConsoleClose.cpp
-
-#include "StdAfx.h"
-
-#include "ConsoleClose.h"
-
-#include <signal.h>
-
-static int g_BreakCounter = 0;
-static const int kBreakAbortThreshold = 2;
-
-namespace NConsoleClose {
-
-static void HandlerRoutine(int)
-{
- g_BreakCounter++;
- if (g_BreakCounter < kBreakAbortThreshold)
- return ;
- exit(EXIT_FAILURE);
-}
-
-bool TestBreakSignal()
-{
- return (g_BreakCounter > 0);
-}
-
-void CheckCtrlBreak()
-{
- if (TestBreakSignal())
- throw CCtrlBreakException();
-}
-
-CCtrlHandlerSetter::CCtrlHandlerSetter()
-{
- memo_sig_int = signal(SIGINT,HandlerRoutine); // CTRL-C
- if (memo_sig_int == SIG_ERR)
- throw "SetConsoleCtrlHandler fails (SIGINT)";
- memo_sig_term = signal(SIGTERM,HandlerRoutine); // for kill -15 (before "kill -9")
- if (memo_sig_term == SIG_ERR)
- throw "SetConsoleCtrlHandler fails (SIGTERM)";
-}
-
-CCtrlHandlerSetter::~CCtrlHandlerSetter()
-{
- signal(SIGINT,memo_sig_int); // CTRL-C
- signal(SIGTERM,memo_sig_term); // kill {pid}
-}
-
-}
diff --git a/src/libs/7zip/unix/CPP/7zip/UI/Console/ConsoleClose.h b/src/libs/7zip/unix/CPP/7zip/UI/Console/ConsoleClose.h
deleted file mode 100644
index 042aaf2d6..000000000
--- a/src/libs/7zip/unix/CPP/7zip/UI/Console/ConsoleClose.h
+++ /dev/null
@@ -1,26 +0,0 @@
-// ConsoleCloseUtils.h
-
-#ifndef __CONSOLECLOSEUTILS_H
-#define __CONSOLECLOSEUTILS_H
-
-namespace NConsoleClose {
-
-bool TestBreakSignal();
-
-class CCtrlHandlerSetter
-{
- void (*memo_sig_int)(int);
- void (*memo_sig_term)(int);
-public:
- CCtrlHandlerSetter();
- virtual ~CCtrlHandlerSetter();
-};
-
-class CCtrlBreakException
-{};
-
-void CheckCtrlBreak();
-
-}
-
-#endif
diff --git a/src/libs/7zip/unix/CPP/7zip/UI/Console/ExtractCallbackConsole.cpp b/src/libs/7zip/unix/CPP/7zip/UI/Console/ExtractCallbackConsole.cpp
deleted file mode 100644
index af65739c3..000000000
--- a/src/libs/7zip/unix/CPP/7zip/UI/Console/ExtractCallbackConsole.cpp
+++ /dev/null
@@ -1,228 +0,0 @@
-// ExtractCallbackConsole.h
-
-#include "StdAfx.h"
-
-#include "ExtractCallbackConsole.h"
-#include "UserInputUtils.h"
-#include "ConsoleClose.h"
-
-#include "Common/Wildcard.h"
-
-#include "Windows/FileDir.h"
-#include "Windows/FileFind.h"
-#include "Windows/Time.h"
-#include "Windows/Defs.h"
-#include "Windows/PropVariant.h"
-#include "Windows/Error.h"
-#include "Windows/PropVariantConversions.h"
-
-#include "../../Common/FilePathAutoRename.h"
-
-#include "../Common/ExtractingFilePath.h"
-
-using namespace NWindows;
-using namespace NFile;
-using namespace NDirectory;
-
-static const char *kTestString = "Testing ";
-static const char *kExtractString = "Extracting ";
-static const char *kSkipString = "Skipping ";
-
-// static const char *kCantAutoRename = "can not create file with auto name\n";
-// static const char *kCantRenameFile = "can not rename existing file\n";
-// static const char *kCantDeleteOutputFile = "can not delete output file ";
-static const char *kError = "ERROR: ";
-static const char *kMemoryExceptionMessage = "Can't allocate required memory!";
-
-static const char *kProcessing = "Processing archive: ";
-static const char *kEverythingIsOk = "Everything is Ok";
-static const char *kNoFiles = "No files to process";
-
-static const char *kUnsupportedMethod = "Unsupported Method";
-static const char *kCrcFailed = "CRC Failed";
-static const char *kCrcFailedEncrypted = "CRC Failed in encrypted file. Wrong password?";
-static const char *kDataError = "Data Error";
-static const char *kDataErrorEncrypted = "Data Error in encrypted file. Wrong password?";
-static const char *kUnknownError = "Unknown Error";
-
-STDMETHODIMP CExtractCallbackConsole::SetTotal(UInt64)
-{
- if (NConsoleClose::TestBreakSignal())
- return E_ABORT;
- return S_OK;
-}
-
-STDMETHODIMP CExtractCallbackConsole::SetCompleted(const UInt64 *)
-{
- if (NConsoleClose::TestBreakSignal())
- return E_ABORT;
- return S_OK;
-}
-
-STDMETHODIMP CExtractCallbackConsole::AskOverwrite(
- const wchar_t *existName, const FILETIME *, const UInt64 *,
- const wchar_t *newName, const FILETIME *, const UInt64 *,
- Int32 *answer)
-{
- (*OutStream) << "file " << existName <<
- "\nalready exists. Overwrite with " << endl;
- (*OutStream) << newName;
-
- NUserAnswerMode::EEnum overwriteAnswer = ScanUserYesNoAllQuit(OutStream);
-
- switch(overwriteAnswer)
- {
- case NUserAnswerMode::kQuit: return E_ABORT;
- case NUserAnswerMode::kNo: *answer = NOverwriteAnswer::kNo; break;
- case NUserAnswerMode::kNoAll: *answer = NOverwriteAnswer::kNoToAll; break;
- case NUserAnswerMode::kYesAll: *answer = NOverwriteAnswer::kYesToAll; break;
- case NUserAnswerMode::kYes: *answer = NOverwriteAnswer::kYes; break;
- case NUserAnswerMode::kAutoRenameAll: *answer = NOverwriteAnswer::kAutoRename; break;
- default: return E_FAIL;
- }
- return S_OK;
-}
-
-STDMETHODIMP CExtractCallbackConsole::PrepareOperation(const wchar_t *name, bool /* isFolder */, Int32 askExtractMode, const UInt64 *position)
-{
- switch (askExtractMode)
- {
- case NArchive::NExtract::NAskMode::kExtract: (*OutStream) << kExtractString; break;
- case NArchive::NExtract::NAskMode::kTest: (*OutStream) << kTestString; break;
- case NArchive::NExtract::NAskMode::kSkip: (*OutStream) << kSkipString; break;
- };
- (*OutStream) << name;
- if (position != 0)
- (*OutStream) << " <" << *position << ">";
- return S_OK;
-}
-
-STDMETHODIMP CExtractCallbackConsole::MessageError(const wchar_t *message)
-{
- (*OutStream) << message << endl;
- NumFileErrorsInCurrentArchive++;
- NumFileErrors++;
- return S_OK;
-}
-
-STDMETHODIMP CExtractCallbackConsole::SetOperationResult(Int32 operationResult, bool encrypted)
-{
- switch(operationResult)
- {
- case NArchive::NExtract::NOperationResult::kOK:
- break;
- default:
- {
- NumFileErrorsInCurrentArchive++;
- NumFileErrors++;
- (*OutStream) << " ";
- switch(operationResult)
- {
- case NArchive::NExtract::NOperationResult::kUnSupportedMethod:
- (*OutStream) << kUnsupportedMethod;
- break;
- case NArchive::NExtract::NOperationResult::kCRCError:
- (*OutStream) << (encrypted ? kCrcFailedEncrypted: kCrcFailed);
- break;
- case NArchive::NExtract::NOperationResult::kDataError:
- (*OutStream) << (encrypted ? kDataErrorEncrypted : kDataError);
- break;
- default:
- (*OutStream) << kUnknownError;
- }
- }
- }
- (*OutStream) << endl;
- return S_OK;
-}
-
-#ifndef _NO_CRYPTO
-
-HRESULT CExtractCallbackConsole::SetPassword(const UString &password)
-{
- PasswordIsDefined = true;
- Password = password;
- return S_OK;
-}
-
-STDMETHODIMP CExtractCallbackConsole::CryptoGetTextPassword(BSTR *password)
-{
- if (!PasswordIsDefined)
- {
- Password = GetPassword(OutStream);
- PasswordIsDefined = true;
- }
- return StringToBstr(Password, password);
-}
-
-#endif
-
-HRESULT CExtractCallbackConsole::BeforeOpen(const wchar_t *name)
-{
- NumArchives++;
- NumFileErrorsInCurrentArchive = 0;
- (*OutStream) << endl << kProcessing << name << endl;
- return S_OK;
-}
-
-HRESULT CExtractCallbackConsole::OpenResult(const wchar_t * /* name */, HRESULT result, bool encrypted)
-{
- (*OutStream) << endl;
- if (result != S_OK)
- {
- (*OutStream) << "Error: ";
- if (result == S_FALSE)
- {
- (*OutStream) << (encrypted ?
- "Can not open encrypted archive. Wrong password?" :
- "Can not open file as archive");
- }
- else
- {
- if (result == E_OUTOFMEMORY)
- (*OutStream) << "Can't allocate required memory";
- else
- (*OutStream) << NError::MyFormatMessage(result);
- }
- (*OutStream) << endl;
- NumArchiveErrors++;
- }
- return S_OK;
-}
-
-HRESULT CExtractCallbackConsole::ThereAreNoFiles()
-{
- (*OutStream) << endl << kNoFiles << endl;
- return S_OK;
-}
-
-HRESULT CExtractCallbackConsole::ExtractResult(HRESULT result)
-{
- if (result == S_OK)
- {
- (*OutStream) << endl;
- if (NumFileErrorsInCurrentArchive == 0)
- (*OutStream) << kEverythingIsOk << endl;
- else
- {
- NumArchiveErrors++;
- (*OutStream) << "Sub items Errors: " << NumFileErrorsInCurrentArchive << endl;
- }
- }
- if (result == S_OK)
- return result;
- NumArchiveErrors++;
- if (result == E_ABORT || result == ERROR_DISK_FULL)
- return result;
- (*OutStream) << endl << kError;
- if (result == E_OUTOFMEMORY)
- (*OutStream) << kMemoryExceptionMessage;
- else
- {
- UString message;
- NError::MyFormatMessage(result, message);
- (*OutStream) << message;
- }
- (*OutStream) << endl;
- return S_OK;
-}
diff --git a/src/libs/7zip/unix/CPP/7zip/UI/Console/ExtractCallbackConsole.h b/src/libs/7zip/unix/CPP/7zip/UI/Console/ExtractCallbackConsole.h
deleted file mode 100644
index e42ca6f40..000000000
--- a/src/libs/7zip/unix/CPP/7zip/UI/Console/ExtractCallbackConsole.h
+++ /dev/null
@@ -1,73 +0,0 @@
-// ExtractCallbackConsole.h
-
-#ifndef __EXTRACTCALLBACKCONSOLE_H
-#define __EXTRACTCALLBACKCONSOLE_H
-
-#include "Common/MyString.h"
-#include "Common/StdOutStream.h"
-#include "../../Common/FileStreams.h"
-#include "../../IPassword.h"
-#include "../../Archive/IArchive.h"
-#include "../Common/ArchiveExtractCallback.h"
-
-class CExtractCallbackConsole:
- public IExtractCallbackUI,
- #ifndef _NO_CRYPTO
- public ICryptoGetTextPassword,
- #endif
- public CMyUnknownImp
-{
-public:
- MY_QUERYINTERFACE_BEGIN2(IFolderArchiveExtractCallback)
- #ifndef _NO_CRYPTO
- MY_QUERYINTERFACE_ENTRY(ICryptoGetTextPassword)
- #endif
- MY_QUERYINTERFACE_END
- MY_ADDREF_RELEASE
-
- STDMETHOD(SetTotal)(UInt64 total);
- STDMETHOD(SetCompleted)(const UInt64 *completeValue);
-
- // IFolderArchiveExtractCallback
- STDMETHOD(AskOverwrite)(
- const wchar_t *existName, const FILETIME *existTime, const UInt64 *existSize,
- const wchar_t *newName, const FILETIME *newTime, const UInt64 *newSize,
- Int32 *answer);
- STDMETHOD (PrepareOperation)(const wchar_t *name, bool isFolder, Int32 askExtractMode, const UInt64 *position);
-
- STDMETHOD(MessageError)(const wchar_t *message);
- STDMETHOD(SetOperationResult)(Int32 operationResult, bool encrypted);
-
- HRESULT BeforeOpen(const wchar_t *name);
- HRESULT OpenResult(const wchar_t *name, HRESULT result, bool encrypted);
- HRESULT ThereAreNoFiles();
- HRESULT ExtractResult(HRESULT result);
-
-
- #ifndef _NO_CRYPTO
- HRESULT SetPassword(const UString &password);
- STDMETHOD(CryptoGetTextPassword)(BSTR *password);
-
- bool PasswordIsDefined;
- UString Password;
-
- #endif
-
- UInt64 NumArchives;
- UInt64 NumArchiveErrors;
- UInt64 NumFileErrors;
- UInt64 NumFileErrorsInCurrentArchive;
-
- CStdOutStream *OutStream;
-
- void Init()
- {
- NumArchives = 0;
- NumArchiveErrors = 0;
- NumFileErrors = 0;
- NumFileErrorsInCurrentArchive = 0;
- }
-
-};
-
-#endif
diff --git a/src/libs/7zip/unix/CPP/7zip/UI/Console/List.cpp b/src/libs/7zip/unix/CPP/7zip/UI/Console/List.cpp
deleted file mode 100644
index f747cfda8..000000000
--- a/src/libs/7zip/unix/CPP/7zip/UI/Console/List.cpp
+++ /dev/null
@@ -1,654 +0,0 @@
-// List.cpp
-
-#include "StdAfx.h"
-
-#include "Common/IntToString.h"
-#include "Common/MyCom.h"
-#include "Common/StdOutStream.h"
-#include "Common/StringConvert.h"
-
-#include "Windows/Error.h"
-#include "Windows/FileDir.h"
-#include "Windows/PropVariant.h"
-#include "Windows/PropVariantConversions.h"
-
-#include "../../Archive/IArchive.h"
-
-#include "../Common/OpenArchive.h"
-#include "../Common/PropIDUtils.h"
-
-#include "ConsoleClose.h"
-#include "List.h"
-#include "OpenCallbackConsole.h"
-
-using namespace NWindows;
-
-struct CPropIdToName
-{
- PROPID PropID;
- const wchar_t *Name;
-};
-
-static const CPropIdToName kPropIdToName[] =
-{
- { kpidPath, L"Path" },
- { kpidName, L"Name" },
- { kpidIsDir, L"Folder" },
- { kpidSize, L"Size" },
- { kpidPackSize, L"Packed Size" },
- { kpidAttrib, L"Attributes" },
- { kpidCTime, L"Created" },
- { kpidATime, L"Accessed" },
- { kpidMTime, L"Modified" },
- { kpidSolid, L"Solid" },
- { kpidCommented, L"Commented" },
- { kpidEncrypted, L"Encrypted" },
- { kpidSplitBefore, L"Split Before" },
- { kpidSplitAfter, L"Split After" },
- { kpidDictionarySize, L"Dictionary Size" },
- { kpidCRC, L"CRC" },
- { kpidType, L"Type" },
- { kpidIsAnti, L"Anti" },
- { kpidMethod, L"Method" },
- { kpidHostOS, L"Host OS" },
- { kpidFileSystem, L"File System" },
- { kpidUser, L"User" },
- { kpidGroup, L"Group" },
- { kpidBlock, L"Block" },
- { kpidComment, L"Comment" },
- { kpidPosition, L"Position" },
- { kpidPrefix, L"Prefix" },
- { kpidNumSubDirs, L"Folders" },
- { kpidNumSubFiles, L"Files" },
- { kpidUnpackVer, L"Version" },
- { kpidVolume, L"Volume" },
- { kpidIsVolume, L"Multivolume" },
- { kpidOffset, L"Offset" },
- { kpidLinks, L"Links" },
- { kpidNumBlocks, L"Blocks" },
- { kpidNumVolumes, L"Volumes" },
-
- { kpidBit64, L"64-bit" },
- { kpidBigEndian, L"Big-endian" },
- { kpidCpu, L"CPU" },
- { kpidPhySize, L"Physical Size" },
- { kpidHeadersSize, L"Headers Size" },
- { kpidChecksum, L"Checksum" },
- { kpidCharacts, L"Characteristics" },
- { kpidVa, L"Virtual Address" },
- { kpidId, L"ID" },
- { kpidShortName, L"Short Name" },
- { kpidCreatorApp, L"Creator Application"},
- { kpidSectorSize, L"Sector Size" },
- { kpidPosixAttrib, L"Mode" },
- { kpidLink, L"Link" },
- { kpidError, L"Error" },
-
- { kpidTotalSize, L"Total Size" },
- { kpidFreeSpace, L"Free Space" },
- { kpidClusterSize, L"Cluster Size" },
- { kpidVolumeName, L"Label" }
-};
-
-static const char kEmptyAttribChar = '.';
-
-static const char *kListing = "Listing archive: ";
-static const wchar_t *kFilesMessage = L"files";
-static const wchar_t *kDirsMessage = L"folders";
-
-static void GetAttribString(DWORD wa, bool isDir, char *s)
-{
- s[0] = ((wa & FILE_ATTRIBUTE_DIRECTORY) != 0 || isDir) ? 'D' : kEmptyAttribChar;
- s[1] = ((wa & FILE_ATTRIBUTE_READONLY) != 0) ? 'R': kEmptyAttribChar;
- s[2] = ((wa & FILE_ATTRIBUTE_HIDDEN) != 0) ? 'H': kEmptyAttribChar;
- s[3] = ((wa & FILE_ATTRIBUTE_SYSTEM) != 0) ? 'S': kEmptyAttribChar;
- s[4] = ((wa & FILE_ATTRIBUTE_ARCHIVE) != 0) ? 'A': kEmptyAttribChar;
- s[5] = '\0';
-}
-
-enum EAdjustment
-{
- kLeft,
- kCenter,
- kRight
-};
-
-struct CFieldInfo
-{
- PROPID PropID;
- UString Name;
- EAdjustment TitleAdjustment;
- EAdjustment TextAdjustment;
- int PrefixSpacesWidth;
- int Width;
-};
-
-struct CFieldInfoInit
-{
- PROPID PropID;
- const wchar_t *Name;
- EAdjustment TitleAdjustment;
- EAdjustment TextAdjustment;
- int PrefixSpacesWidth;
- int Width;
-};
-
-static CFieldInfoInit kStandardFieldTable[] =
-{
- { kpidMTime, L" Date Time", kLeft, kLeft, 0, 19 },
- { kpidAttrib, L"Attr", kRight, kCenter, 1, 5 },
- { kpidSize, L"Size", kRight, kRight, 1, 12 },
- { kpidPackSize, L"Compressed", kRight, kRight, 1, 12 },
- { kpidPath, L"Name", kLeft, kLeft, 2, 24 }
-};
-
-static void PrintSpaces(int numSpaces)
-{
- for (int i = 0; i < numSpaces; i++)
- g_StdOut << ' ';
-}
-
-static void PrintString(EAdjustment adjustment, int width, const UString &textString)
-{
- const int numSpaces = width - textString.Length();
- int numLeftSpaces = 0;
- switch (adjustment)
- {
- case kLeft:
- numLeftSpaces = 0;
- break;
- case kCenter:
- numLeftSpaces = numSpaces / 2;
- break;
- case kRight:
- numLeftSpaces = numSpaces;
- break;
- }
- PrintSpaces(numLeftSpaces);
- g_StdOut << textString;
- PrintSpaces(numSpaces - numLeftSpaces);
-}
-
-class CFieldPrinter
-{
- CObjectVector<CFieldInfo> _fields;
-public:
- void Clear() { _fields.Clear(); }
- void Init(const CFieldInfoInit *standardFieldTable, int numItems);
- HRESULT Init(IInArchive *archive);
- void PrintTitle();
- void PrintTitleLines();
- HRESULT PrintItemInfo(const CArc &arc, UInt32 index, bool techMode);
- HRESULT PrintSummaryInfo(UInt64 numFiles, UInt64 numDirs,
- const UInt64 *size, const UInt64 *compressedSize);
-};
-
-void CFieldPrinter::Init(const CFieldInfoInit *standardFieldTable, int numItems)
-{
- Clear();
- for (int i = 0; i < numItems; i++)
- {
- CFieldInfo fieldInfo;
- const CFieldInfoInit &fieldInfoInit = standardFieldTable[i];
- fieldInfo.PropID = fieldInfoInit.PropID;
- fieldInfo.Name = fieldInfoInit.Name;
- fieldInfo.TitleAdjustment = fieldInfoInit.TitleAdjustment;
- fieldInfo.TextAdjustment = fieldInfoInit.TextAdjustment;
- fieldInfo.PrefixSpacesWidth = fieldInfoInit.PrefixSpacesWidth;
- fieldInfo.Width = fieldInfoInit.Width;
- _fields.Add(fieldInfo);
- }
-}
-
-static UString GetPropName(PROPID propID, BSTR name)
-{
- for (int i = 0; i < sizeof(kPropIdToName) / sizeof(kPropIdToName[0]); i++)
- {
- const CPropIdToName &propIdToName = kPropIdToName[i];
- if (propIdToName.PropID == propID)
- return propIdToName.Name;
- }
- if (name)
- return name;
- wchar_t s[16];
- ConvertUInt32ToString(propID, s);
- return s;
-}
-
-HRESULT CFieldPrinter::Init(IInArchive *archive)
-{
- Clear();
- UInt32 numProps;
- RINOK(archive->GetNumberOfProperties(&numProps));
- for (UInt32 i = 0; i < numProps; i++)
- {
- CMyComBSTR name;
- PROPID propID;
- VARTYPE vt;
- RINOK(archive->GetPropertyInfo(i, &name, &propID, &vt));
- CFieldInfo fieldInfo;
- fieldInfo.PropID = propID;
- fieldInfo.Name = GetPropName(propID, name);
- _fields.Add(fieldInfo);
- }
- return S_OK;
-}
-
-void CFieldPrinter::PrintTitle()
-{
- for (int i = 0; i < _fields.Size(); i++)
- {
- const CFieldInfo &fieldInfo = _fields[i];
- PrintSpaces(fieldInfo.PrefixSpacesWidth);
- PrintString(fieldInfo.TitleAdjustment,
- ((fieldInfo.PropID == kpidPath) ? 0: fieldInfo.Width), fieldInfo.Name);
- }
-}
-
-void CFieldPrinter::PrintTitleLines()
-{
- for (int i = 0; i < _fields.Size(); i++)
- {
- const CFieldInfo &fieldInfo = _fields[i];
- PrintSpaces(fieldInfo.PrefixSpacesWidth);
- for (int i = 0; i < fieldInfo.Width; i++)
- g_StdOut << '-';
- }
-}
-
-
-static BOOL IsFileTimeZero(CONST FILETIME *lpFileTime)
-{
- return (lpFileTime->dwLowDateTime == 0) && (lpFileTime->dwHighDateTime == 0);
-}
-
-static const char *kEmptyTimeString = " ";
-static void PrintTime(const NCOM::CPropVariant &prop)
-{
- if (prop.vt != VT_FILETIME)
- throw "incorrect item";
- if (IsFileTimeZero(&prop.filetime))
- g_StdOut << kEmptyTimeString;
- else
- {
- FILETIME localFileTime;
- if (!FileTimeToLocalFileTime(&prop.filetime, &localFileTime))
- throw "FileTimeToLocalFileTime error";
- char s[32];
- if (ConvertFileTimeToString(localFileTime, s, true, true))
- g_StdOut << s;
- else
- g_StdOut << kEmptyTimeString;
- }
-}
-
-HRESULT CFieldPrinter::PrintItemInfo(const CArc &arc, UInt32 index, bool techMode)
-{
- /*
- if (techMode)
- {
- g_StdOut << "Index = ";
- g_StdOut << (UInt64)index;
- g_StdOut << endl;
- }
- */
- for (int i = 0; i < _fields.Size(); i++)
- {
- const CFieldInfo &fieldInfo = _fields[i];
- if (!techMode)
- PrintSpaces(fieldInfo.PrefixSpacesWidth);
-
- NCOM::CPropVariant prop;
- if (fieldInfo.PropID == kpidPath)
- {
- UString s;
- RINOK(arc.GetItemPath(index, s));
- prop = s;
- }
- else
- {
- RINOK(arc.Archive->GetProperty(index, fieldInfo.PropID, &prop));
- }
- if (techMode)
- {
- g_StdOut << fieldInfo.Name << " = ";
- }
- int width = (fieldInfo.PropID == kpidPath) ? 0: fieldInfo.Width;
- if (fieldInfo.PropID == kpidAttrib && (prop.vt == VT_EMPTY || prop.vt == VT_UI4))
- {
- UInt32 attrib = (prop.vt == VT_EMPTY) ? 0 : prop.ulVal;
- bool isFolder;
- RINOK(IsArchiveItemFolder(arc.Archive, index, isFolder));
- char s[8];
- GetAttribString(attrib, isFolder, s);
- g_StdOut << s;
- }
- else if (prop.vt == VT_EMPTY)
- {
- if (!techMode)
- PrintSpaces(width);
- }
- else if (fieldInfo.PropID == kpidMTime)
- {
- PrintTime(prop);
- }
- else if (prop.vt == VT_BSTR)
- {
- if (techMode)
- g_StdOut << prop.bstrVal;
- else
- PrintString(fieldInfo.TextAdjustment, width, prop.bstrVal);
- }
- else
- {
- UString s = ConvertPropertyToString(prop, fieldInfo.PropID);
- s.Replace(wchar_t(0xA), L' ');
- s.Replace(wchar_t(0xD), L' ');
-
- if (techMode)
- g_StdOut << s;
- else
- PrintString(fieldInfo.TextAdjustment, width, s);
- }
- if (techMode)
- g_StdOut << endl;
- }
- return S_OK;
-}
-
-static void PrintNumberString(EAdjustment adjustment, int width, const UInt64 *value)
-{
- wchar_t textString[32] = { 0 };
- if (value != NULL)
- ConvertUInt64ToString(*value, textString);
- PrintString(adjustment, width, textString);
-}
-
-
-HRESULT CFieldPrinter::PrintSummaryInfo(UInt64 numFiles, UInt64 numDirs,
- const UInt64 *size, const UInt64 *compressedSize)
-{
- for (int i = 0; i < _fields.Size(); i++)
- {
- const CFieldInfo &fieldInfo = _fields[i];
- PrintSpaces(fieldInfo.PrefixSpacesWidth);
- NCOM::CPropVariant prop;
- if (fieldInfo.PropID == kpidSize)
- PrintNumberString(fieldInfo.TextAdjustment, fieldInfo.Width, size);
- else if (fieldInfo.PropID == kpidPackSize)
- PrintNumberString(fieldInfo.TextAdjustment, fieldInfo.Width, compressedSize);
- else if (fieldInfo.PropID == kpidPath)
- {
- wchar_t textString[32];
- ConvertUInt64ToString(numFiles, textString);
- UString temp = textString;
- temp += L" ";
- temp += kFilesMessage;
- temp += L", ";
- ConvertUInt64ToString(numDirs, textString);
- temp += textString;
- temp += L" ";
- temp += kDirsMessage;
- PrintString(fieldInfo.TextAdjustment, 0, temp);
- }
- else
- PrintString(fieldInfo.TextAdjustment, fieldInfo.Width, L"");
- }
- return S_OK;
-}
-
-bool GetUInt64Value(IInArchive *archive, UInt32 index, PROPID propID, UInt64 &value)
-{
- NCOM::CPropVariant prop;
- if (archive->GetProperty(index, propID, &prop) != S_OK)
- throw "GetPropertyValue error";
- if (prop.vt == VT_EMPTY)
- return false;
- value = ConvertPropVariantToUInt64(prop);
- return true;
-}
-
-static void PrintPropPair(const wchar_t *name, const wchar_t *value)
-{
- g_StdOut << name << " = " << value << endl;
-}
-
-HRESULT ListArchives(CCodecs *codecs, const CIntVector &formatIndices,
- bool stdInMode,
- UStringVector &arcPaths, UStringVector &arcPathsFull,
- const NWildcard::CCensorNode &wildcardCensor,
- bool enableHeaders, bool techMode,
- #ifndef _NO_CRYPTO
- bool &passwordEnabled, UString &password,
- #endif
- UInt64 &numErrors)
-{
- numErrors = 0;
- CFieldPrinter fieldPrinter;
- if (!techMode)
- fieldPrinter.Init(kStandardFieldTable, sizeof(kStandardFieldTable) / sizeof(kStandardFieldTable[0]));
-
- UInt64 numFiles2 = 0, numDirs2 = 0, totalPackSize2 = 0, totalUnPackSize2 = 0;
- UInt64 *totalPackSizePointer2 = 0, *totalUnPackSizePointer2 = 0;
- int numArcs = /* stdInMode ? 1 : */ arcPaths.Size();
- for (int i = 0; i < numArcs; i++)
- {
- const UString &archiveName = arcPaths[i];
- UInt64 arcPackSize = 0;
- if (!stdInMode)
- {
- NFile::NFind::CFileInfoW fi;
- if (!fi.Find(archiveName) || fi.IsDir())
- {
- g_StdOut << endl << "Error: " << archiveName << " is not file" << endl;
- numErrors++;
- continue;
- }
- arcPackSize = fi.Size;
- }
-
- CArchiveLink archiveLink;
-
- COpenCallbackConsole openCallback;
- openCallback.OutStream = &g_StdOut;
-
- #ifndef _NO_CRYPTO
-
- openCallback.PasswordIsDefined = passwordEnabled;
- openCallback.Password = password;
-
- #endif
-
- HRESULT result = archiveLink.Open2(codecs, formatIndices, stdInMode, NULL, archiveName, &openCallback);
- if (result != S_OK)
- {
- if (result == E_ABORT)
- return result;
- g_StdOut << endl << "Error: " << archiveName << ": ";
- if (result == S_FALSE)
- {
- #ifndef _NO_CRYPTO
- if (openCallback.Open_WasPasswordAsked())
- g_StdOut << "Can not open encrypted archive. Wrong password?";
- else
- #endif
- g_StdOut << "Can not open file as archive";
- }
- else if (result == E_OUTOFMEMORY)
- g_StdOut << "Can't allocate required memory";
- else
- g_StdOut << NError::MyFormatMessage(result);
- g_StdOut << endl;
- numErrors++;
- continue;
- }
-
- if (!stdInMode)
- for (int v = 0; v < archiveLink.VolumePaths.Size(); v++)
- {
- int index = arcPathsFull.FindInSorted(archiveLink.VolumePaths[v]);
- if (index >= 0 && index > i)
- {
- arcPaths.Delete(index);
- arcPathsFull.Delete(index);
- numArcs = arcPaths.Size();
- }
- }
-
- if (enableHeaders)
- {
- g_StdOut << endl << kListing << archiveName << endl << endl;
-
- for (int i = 0; i < archiveLink.Arcs.Size(); i++)
- {
- const CArc &arc = archiveLink.Arcs[i];
-
- g_StdOut << "--\n";
- PrintPropPair(L"Path", arc.Path);
- PrintPropPair(L"Type", codecs->Formats[arc.FormatIndex].Name);
- if (!arc.ErrorMessage.IsEmpty())
- PrintPropPair(L"Error", arc.ErrorMessage);
- UInt32 numProps;
- IInArchive *archive = arc.Archive;
- if (archive->GetNumberOfArchiveProperties(&numProps) == S_OK)
- {
- for (UInt32 j = 0; j < numProps; j++)
- {
- CMyComBSTR name;
- PROPID propID;
- VARTYPE vt;
- RINOK(archive->GetArchivePropertyInfo(j, &name, &propID, &vt));
- NCOM::CPropVariant prop;
- RINOK(archive->GetArchiveProperty(propID, &prop));
- UString s = ConvertPropertyToString(prop, propID);
- if (!s.IsEmpty())
- PrintPropPair(GetPropName(propID, name), s);
- }
- }
- if (i != archiveLink.Arcs.Size() - 1)
- {
- UInt32 numProps;
- g_StdOut << "----\n";
- if (archive->GetNumberOfProperties(&numProps) == S_OK)
- {
- UInt32 mainIndex = archiveLink.Arcs[i + 1].SubfileIndex;
- for (UInt32 j = 0; j < numProps; j++)
- {
- CMyComBSTR name;
- PROPID propID;
- VARTYPE vt;
- RINOK(archive->GetPropertyInfo(j, &name, &propID, &vt));
- NCOM::CPropVariant prop;
- RINOK(archive->GetProperty(mainIndex, propID, &prop));
- UString s = ConvertPropertyToString(prop, propID);
- if (!s.IsEmpty())
- PrintPropPair(GetPropName(propID, name), s);
- }
- }
- }
-
- }
- g_StdOut << endl;
- if (techMode)
- g_StdOut << "----------\n";
- }
-
- if (enableHeaders && !techMode)
- {
- fieldPrinter.PrintTitle();
- g_StdOut << endl;
- fieldPrinter.PrintTitleLines();
- g_StdOut << endl;
- }
-
- const CArc &arc = archiveLink.Arcs.Back();
- IInArchive *archive = arc.Archive;
- if (techMode)
- {
- RINOK(fieldPrinter.Init(archive));
- }
- UInt64 numFiles = 0, numDirs = 0, totalPackSize = 0, totalUnPackSize = 0;
- UInt64 *totalPackSizePointer = 0, *totalUnPackSizePointer = 0;
- UInt32 numItems;
- RINOK(archive->GetNumberOfItems(&numItems));
- for (UInt32 i = 0; i < numItems; i++)
- {
- if (NConsoleClose::TestBreakSignal())
- return E_ABORT;
-
- UString filePath;
- HRESULT res = arc.GetItemPath(i, filePath);
- if (stdInMode && res == E_INVALIDARG)
- break;
- RINOK(res);
-
- bool isFolder;
- RINOK(IsArchiveItemFolder(archive, i, isFolder));
- if (!wildcardCensor.CheckPath(filePath, !isFolder))
- continue;
-
- fieldPrinter.PrintItemInfo(arc, i, techMode);
-
- UInt64 packSize, unpackSize;
- if (!GetUInt64Value(archive, i, kpidSize, unpackSize))
- unpackSize = 0;
- else
- totalUnPackSizePointer = &totalUnPackSize;
- if (!GetUInt64Value(archive, i, kpidPackSize, packSize))
- packSize = 0;
- else
- totalPackSizePointer = &totalPackSize;
-
- g_StdOut << endl;
-
- if (isFolder)
- numDirs++;
- else
- numFiles++;
- totalPackSize += packSize;
- totalUnPackSize += unpackSize;
- }
-
- if (!stdInMode && totalPackSizePointer == 0)
- {
- if (archiveLink.VolumePaths.Size() != 0)
- arcPackSize += archiveLink.VolumesSize;
- totalPackSize = (numFiles == 0) ? 0 : arcPackSize;
- totalPackSizePointer = &totalPackSize;
- }
- if (totalUnPackSizePointer == 0 && numFiles == 0)
- {
- totalUnPackSize = 0;
- totalUnPackSizePointer = &totalUnPackSize;
- }
- if (enableHeaders && !techMode)
- {
- fieldPrinter.PrintTitleLines();
- g_StdOut << endl;
- fieldPrinter.PrintSummaryInfo(numFiles, numDirs, totalUnPackSizePointer, totalPackSizePointer);
- g_StdOut << endl;
- }
- if (totalPackSizePointer != 0)
- {
- totalPackSizePointer2 = &totalPackSize2;
- totalPackSize2 += totalPackSize;
- }
- if (totalUnPackSizePointer != 0)
- {
- totalUnPackSizePointer2 = &totalUnPackSize2;
- totalUnPackSize2 += totalUnPackSize;
- }
- numFiles2 += numFiles;
- numDirs2 += numDirs;
- }
- if (enableHeaders && !techMode && numArcs > 1)
- {
- g_StdOut << endl;
- fieldPrinter.PrintTitleLines();
- g_StdOut << endl;
- fieldPrinter.PrintSummaryInfo(numFiles2, numDirs2, totalUnPackSizePointer2, totalPackSizePointer2);
- g_StdOut << endl;
- g_StdOut << "Archives: " << numArcs << endl;
- }
- return S_OK;
-}
diff --git a/src/libs/7zip/unix/CPP/7zip/UI/Console/List.h b/src/libs/7zip/unix/CPP/7zip/UI/Console/List.h
deleted file mode 100644
index 97d9fb15a..000000000
--- a/src/libs/7zip/unix/CPP/7zip/UI/Console/List.h
+++ /dev/null
@@ -1,20 +0,0 @@
-// List.h
-
-#ifndef __LIST_H
-#define __LIST_H
-
-#include "Common/Wildcard.h"
-#include "../Common/LoadCodecs.h"
-
-HRESULT ListArchives(CCodecs *codecs, const CIntVector &formatIndices,
- bool stdInMode,
- UStringVector &archivePaths, UStringVector &archivePathsFull,
- const NWildcard::CCensorNode &wildcardCensor,
- bool enableHeaders, bool techMode,
- #ifndef _NO_CRYPTO
- bool &passwordEnabled, UString &password,
- #endif
- UInt64 &errors);
-
-#endif
-
diff --git a/src/libs/7zip/unix/CPP/7zip/UI/Console/Main.cpp b/src/libs/7zip/unix/CPP/7zip/UI/Console/Main.cpp
deleted file mode 100644
index cebfe2e42..000000000
--- a/src/libs/7zip/unix/CPP/7zip/UI/Console/Main.cpp
+++ /dev/null
@@ -1,628 +0,0 @@
-// Main.cpp
-
-#include "StdAfx.h"
-
-#if defined( _7ZIP_LARGE_PAGES)
-#include "../../../../C/Alloc.h"
-#endif
-
-#include "Common/MyInitGuid.h"
-
-#include "Common/CommandLineParser.h"
-#include "Common/IntToString.h"
-#include "Common/MyException.h"
-#include "Common/StdOutStream.h"
-#include "Common/StringConvert.h"
-#include "Common/StringToInt.h"
-
-#include "Windows/Error.h"
-#ifdef _WIN32
-#include "Windows/MemoryLock.h"
-#endif
-
-#include "../Common/ArchiveCommandLine.h"
-#include "../Common/ExitCode.h"
-#include "../Common/Extract.h"
-#ifdef EXTERNAL_CODECS
-#include "../Common/LoadCodecs.h"
-#endif
-
-#include "BenchCon.h"
-#include "ExtractCallbackConsole.h"
-#include "List.h"
-#include "OpenCallbackConsole.h"
-#include "UpdateCallbackConsole.h"
-
-#include "../../MyVersion.h"
-
-#include "myPrivate.h"
-#include "Windows/System.h"
-
-using namespace NWindows;
-using namespace NFile;
-using namespace NCommandLineParser;
-
-// HINSTANCE g_hInstance = 0;
-extern CStdOutStream *g_StdStream;
-
-static const char *kCopyrightString = "\n7-Zip"
-#ifndef EXTERNAL_CODECS
-" (A)"
-#endif
-
-#ifdef _WIN64
-" [64]"
-#endif
-
-" " MY_VERSION_COPYRIGHT_DATE "\n"
-"p7zip Version " P7ZIP_VERSION ;
-
-static const char *kHelpString =
- "\nUsage: 7z"
-#ifdef _NO_CRYPTO
- "r"
-#else
-#ifndef EXTERNAL_CODECS
- "a"
-#endif
-#endif
- " <command> [<switches>...] <archive_name> [<file_names>...]\n"
- " [<@listfiles...>]\n"
- "\n"
- "<Commands>\n"
- " a: Add files to archive\n"
- " b: Benchmark\n"
- " d: Delete files from archive\n"
- " e: Extract files from archive (without using directory names)\n"
- " l: List contents of archive\n"
-// " l[a|t][f]: List contents of archive\n"
-// " a - with Additional fields\n"
-// " t - with all fields\n"
-// " f - with Full pathnames\n"
- " t: Test integrity of archive\n"
- " u: Update files to archive\n"
- " x: eXtract files with full paths\n"
- "<Switches>\n"
- " -ai[r[-|0]]{@listfile|!wildcard}: Include archives\n"
- " -ax[r[-|0]]{@listfile|!wildcard}: eXclude archives\n"
- " -bd: Disable percentage indicator\n"
- " -i[r[-|0]]{@listfile|!wildcard}: Include filenames\n"
- " -m{Parameters}: set compression Method\n"
- " -o{Directory}: set Output directory\n"
- #ifndef _NO_CRYPTO
- " -p{Password}: set Password\n"
- #endif
- " -r[-|0]: Recurse subdirectories\n"
- " -scs{UTF-8 | WIN | DOS}: set charset for list files\n"
- " -sfx[{name}]: Create SFX archive\n"
- " -si[{name}]: read data from stdin\n"
- " -slt: show technical information for l (List) command\n"
- " -so: write data to stdout\n"
- " -ssc[-]: set sensitive case mode\n"
- " -t{Type}: Set type of archive\n"
- " -u[-][p#][q#][r#][x#][y#][z#][!newArchiveName]: Update options\n"
- " -v{Size}[b|k|m|g]: Create volumes\n"
- " -w[{path}]: assign Work directory. Empty path means a temporary directory\n"
- " -x[r[-|0]]]{@listfile|!wildcard}: eXclude filenames\n"
- " -y: assume Yes on all queries\n";
-
-// ---------------------------
-// exception messages
-
-static const char *kEverythingIsOk = "Everything is Ok";
-static const char *kUserErrorMessage = "Incorrect command line";
-static const char *kNoFormats = "7-Zip cannot find the code that works with archives.";
-static const char *kUnsupportedArcTypeMessage = "Unsupported archive type";
-
-static const wchar_t *kDefaultSfxModule = L"7zCon.sfx";
-
-static void ShowMessageAndThrowException(CStdOutStream &s, LPCSTR message, NExitCode::EEnum code)
-{
- s << message << endl;
- throw code;
-}
-
-static void PrintHelpAndExit(CStdOutStream &s)
-{
- s << kHelpString;
- ShowMessageAndThrowException(s, kUserErrorMessage, NExitCode::kUserError);
-}
-
-#ifndef _WIN32
-static void GetArguments(int numArgs, const char *args[], UStringVector &parts)
-{
- parts.Clear();
- for (int i = 0; i < numArgs; i++)
- {
- UString s = MultiByteToUnicodeString(args[i]);
- parts.Add(s);
- }
-}
-#endif
-
-static void ShowCopyrightAndHelp(CStdOutStream &s, bool needHelp)
-{
- s << kCopyrightString << " (locale=" << my_getlocale() <<",Utf16=";
- if (global_use_utf16_conversion) s << "on";
- else s << "off";
- s << ",HugeFiles=";
- if (sizeof(off_t) >= 8) s << "on,";
- else s << "off,";
- int nbcpu = NWindows::NSystem::GetNumberOfProcessors();
- if (nbcpu > 1) s << nbcpu << " CPUs)\n";
- else s << nbcpu << " CPU)\n";
-
- if (needHelp)
- s << kHelpString;
-}
-
-#ifdef EXTERNAL_CODECS
-static void PrintString(CStdOutStream &stdStream, const AString &s, int size)
-{
- int len = s.Length();
- stdStream << s;
- for (int i = len; i < size; i++)
- stdStream << ' ';
-}
-#endif
-
-static void PrintString(CStdOutStream &stdStream, const UString &s, int size)
-{
- int len = s.Length();
- stdStream << s;
- for (int i = len; i < size; i++)
- stdStream << ' ';
-}
-
-static inline char GetHex(Byte value)
-{
- return (char)((value < 10) ? ('0' + value) : ('A' + (value - 10)));
-}
-
-int Main2(
- #ifndef _WIN32
- int numArgs, const char *args[]
- #endif
-)
-{
- #if defined(_WIN32) && !defined(UNDER_CE)
- SetFileApisToOEM();
- #endif
-
- UStringVector commandStrings;
- #ifdef _WIN32
- NCommandLineParser::SplitCommandLine(GetCommandLineW(), commandStrings);
- #else
- // GetArguments(numArgs, args, commandStrings);
- extern void mySplitCommandLine(int numArgs,const char *args[],UStringVector &parts);
- mySplitCommandLine(numArgs,args,commandStrings);
- #endif
-
- if (commandStrings.Size() == 1)
- {
- ShowCopyrightAndHelp(g_StdOut, true);
- return 0;
- }
- commandStrings.Delete(0);
-
- CArchiveCommandLineOptions options;
-
- CArchiveCommandLineParser parser;
-
- parser.Parse1(commandStrings, options);
-
- if (options.HelpMode)
- {
- ShowCopyrightAndHelp(g_StdOut, true);
- return 0;
- }
-
- #if defined(_7ZIP_LARGE_PAGES)
- if (options.LargePages)
- {
- SetLargePageSize();
-#ifdef _WIN32
- NSecurity::EnableLockMemoryPrivilege();
-#endif
- }
- #endif
-
- CStdOutStream &stdStream = options.StdOutMode ? g_StdErr : g_StdOut;
- g_StdStream = &stdStream;
-
- if (options.EnableHeaders)
- ShowCopyrightAndHelp(stdStream, false);
-
- parser.Parse2(options);
-
- CCodecs *codecs = new CCodecs;
- CMyComPtr<
- #ifdef EXTERNAL_CODECS
- ICompressCodecsInfo
- #else
- IUnknown
- #endif
- > compressCodecsInfo = codecs;
- HRESULT result = codecs->Load();
- if (result != S_OK)
- throw CSystemException(result);
-
- bool isExtractGroupCommand = options.Command.IsFromExtractGroup();
-
- if (codecs->Formats.Size() == 0 &&
- (isExtractGroupCommand ||
- options.Command.CommandType == NCommandType::kList ||
- options.Command.IsFromUpdateGroup()))
- throw kNoFormats;
-
- CIntVector formatIndices;
- if (!codecs->FindFormatForArchiveType(options.ArcType, formatIndices))
- throw kUnsupportedArcTypeMessage;
-
- if (options.Command.CommandType == NCommandType::kInfo)
- {
- stdStream << endl << "Formats:" << endl;
- int i;
- for (i = 0; i < codecs->Formats.Size(); i++)
- {
- const CArcInfoEx &arc = codecs->Formats[i];
- #ifdef EXTERNAL_CODECS
- if (arc.LibIndex >= 0)
- {
- char s[16];
- ConvertUInt32ToString(arc.LibIndex, s);
- PrintString(stdStream, s, 2);
- }
- else
- #endif
- stdStream << " ";
- stdStream << ' ';
- stdStream << (char)(arc.UpdateEnabled ? 'C' : ' ');
- stdStream << (char)(arc.KeepName ? 'K' : ' ');
- stdStream << " ";
- PrintString(stdStream, arc.Name, 6);
- stdStream << " ";
- UString s;
- for (int t = 0; t < arc.Exts.Size(); t++)
- {
- const CArcExtInfo &ext = arc.Exts[t];
- s += ext.Ext;
- if (!ext.AddExt.IsEmpty())
- {
- s += L" (";
- s += ext.AddExt;
- s += L')';
- }
- s += L' ';
- }
- PrintString(stdStream, s, 14);
- stdStream << " ";
- const CByteBuffer &sig = arc.StartSignature;
- for (size_t j = 0; j < sig.GetCapacity(); j++)
- {
- Byte b = sig[j];
- if (b > 0x20 && b < 0x80)
- {
- stdStream << (char)b;
- }
- else
- {
- stdStream << GetHex((Byte)((b >> 4) & 0xF));
- stdStream << GetHex((Byte)(b & 0xF));
- }
- stdStream << ' ';
- }
- stdStream << endl;
- }
- stdStream << endl << "Codecs:" << endl;
-
- #ifdef EXTERNAL_CODECS
- UInt32 numMethods;
- if (codecs->GetNumberOfMethods(&numMethods) == S_OK)
- for (UInt32 j = 0; j < numMethods; j++)
- {
- int libIndex = codecs->GetCodecLibIndex(j);
- if (libIndex >= 0)
- {
- char s[16];
- ConvertUInt32ToString(libIndex, s);
- PrintString(stdStream, s, 2);
- }
- else
- stdStream << " ";
- stdStream << ' ';
- stdStream << (char)(codecs->GetCodecEncoderIsAssigned(j) ? 'C' : ' ');
- UInt64 id;
- stdStream << " ";
- HRESULT res = codecs->GetCodecId(j, id);
- if (res != S_OK)
- id = (UInt64)(Int64)-1;
- char s[32];
- ConvertUInt64ToString(id, s, 16);
- PrintString(stdStream, s, 8);
- stdStream << " ";
- PrintString(stdStream, codecs->GetCodecName(j), 11);
- stdStream << endl;
- /*
- if (res != S_OK)
- throw "incorrect Codec ID";
- */
- }
- #endif
- return S_OK;
- }
- else if (options.Command.CommandType == NCommandType::kBenchmark)
- {
- if (options.Method.CompareNoCase(L"CRC") == 0)
- {
- HRESULT res = CrcBenchCon((FILE *)stdStream, options.NumIterations, options.NumThreads, options.DictionarySize);
- if (res != S_OK)
- {
- if (res == S_FALSE)
- {
- stdStream << "\nCRC Error\n";
- return NExitCode::kFatalError;
- }
- throw CSystemException(res);
- }
- }
- else
- {
- HRESULT res;
- #ifdef EXTERNAL_CODECS
- CObjectVector<CCodecInfoEx> externalCodecs;
- res = LoadExternalCodecs(compressCodecsInfo, externalCodecs);
- if (res != S_OK)
- throw CSystemException(res);
- #endif
- res = LzmaBenchCon(
- #ifdef EXTERNAL_CODECS
- compressCodecsInfo, &externalCodecs,
- #endif
- (FILE *)stdStream, options.NumIterations, options.NumThreads, options.DictionarySize);
- if (res != S_OK)
- {
- if (res == S_FALSE)
- {
- stdStream << "\nDecoding Error\n";
- return NExitCode::kFatalError;
- }
- throw CSystemException(res);
- }
- }
- }
- else if (isExtractGroupCommand || options.Command.CommandType == NCommandType::kList)
- {
- if (isExtractGroupCommand)
- {
- CExtractCallbackConsole *ecs = new CExtractCallbackConsole;
- CMyComPtr<IFolderArchiveExtractCallback> extractCallback = ecs;
-
- ecs->OutStream = &stdStream;
-
- #ifndef _NO_CRYPTO
- ecs->PasswordIsDefined = options.PasswordEnabled;
- ecs->Password = options.Password;
- #endif
-
- ecs->Init();
-
- COpenCallbackConsole openCallback;
- openCallback.OutStream = &stdStream;
-
- #ifndef _NO_CRYPTO
- openCallback.PasswordIsDefined = options.PasswordEnabled;
- openCallback.Password = options.Password;
- #endif
-
- CExtractOptions eo;
- eo.StdInMode = options.StdInMode;
- eo.StdOutMode = options.StdOutMode;
- eo.PathMode = options.Command.GetPathMode();
- eo.TestMode = options.Command.IsTestMode();
- eo.OverwriteMode = options.OverwriteMode;
- eo.OutputDir = options.OutputDir;
- eo.YesToAll = options.YesToAll;
- eo.CalcCrc = options.CalcCrc;
- #if !defined(_7ZIP_ST) && !defined(_SFX)
- eo.Properties = options.ExtractProperties;
- #endif
- UString errorMessage;
- CDecompressStat stat;
- HRESULT result = DecompressArchives(
- codecs,
- formatIndices,
- options.ArchivePathsSorted,
- options.ArchivePathsFullSorted,
- options.WildcardCensor.Pairs.Front().Head,
- eo, &openCallback, ecs, errorMessage, stat);
- if (!errorMessage.IsEmpty())
- {
- stdStream << endl << "Error: " << errorMessage;
- if (result == S_OK)
- result = E_FAIL;
- }
-
- stdStream << endl;
- if (ecs->NumArchives > 1)
- stdStream << "Archives: " << ecs->NumArchives << endl;
- if (ecs->NumArchiveErrors != 0 || ecs->NumFileErrors != 0)
- {
- if (ecs->NumArchives > 1)
- {
- stdStream << endl;
- if (ecs->NumArchiveErrors != 0)
- stdStream << "Archive Errors: " << ecs->NumArchiveErrors << endl;
- if (ecs->NumFileErrors != 0)
- stdStream << "Sub items Errors: " << ecs->NumFileErrors << endl;
- }
- if (result != S_OK)
- throw CSystemException(result);
- return NExitCode::kFatalError;
- }
- if (result != S_OK)
- throw CSystemException(result);
- if (stat.NumFolders != 0)
- stdStream << "Folders: " << stat.NumFolders << endl;
- if (stat.NumFiles != 1 || stat.NumFolders != 0)
- stdStream << "Files: " << stat.NumFiles << endl;
- stdStream
- << "Size: " << stat.UnpackSize << endl
- << "Compressed: " << stat.PackSize << endl;
- if (options.CalcCrc)
- {
- char s[16];
- ConvertUInt32ToHexWithZeros(stat.CrcSum, s);
- stdStream << "CRC: " << s << endl;
- }
- }
- else
- {
- UInt64 numErrors = 0;
- HRESULT result = ListArchives(
- codecs,
- formatIndices,
- options.StdInMode,
- options.ArchivePathsSorted,
- options.ArchivePathsFullSorted,
- options.WildcardCensor.Pairs.Front().Head,
- options.EnableHeaders,
- options.TechMode,
- #ifndef _NO_CRYPTO
- options.PasswordEnabled,
- options.Password,
- #endif
- numErrors);
- if (numErrors > 0)
- {
- g_StdOut << endl << "Errors: " << numErrors;
- return NExitCode::kFatalError;
- }
- if (result != S_OK)
- throw CSystemException(result);
- }
- }
- else if (options.Command.IsFromUpdateGroup())
- {
- CUpdateOptions &uo = options.UpdateOptions;
- if (uo.SfxMode && uo.SfxModule.IsEmpty())
- uo.SfxModule = kDefaultSfxModule;
-
- COpenCallbackConsole openCallback;
- openCallback.OutStream = &stdStream;
-
- #ifndef _NO_CRYPTO
- bool passwordIsDefined =
- options.PasswordEnabled && !options.Password.IsEmpty();
- openCallback.PasswordIsDefined = passwordIsDefined;
- openCallback.Password = options.Password;
- #endif
-
- CUpdateCallbackConsole callback;
- callback.EnablePercents = options.EnablePercents;
-
- #ifndef _NO_CRYPTO
- callback.PasswordIsDefined = passwordIsDefined;
- callback.AskPassword = options.PasswordEnabled && options.Password.IsEmpty();
- callback.Password = options.Password;
- #endif
- callback.StdOutMode = uo.StdOutMode;
- callback.Init(&stdStream);
-
- CUpdateErrorInfo errorInfo;
-
- if (!uo.Init(codecs, formatIndices, options.ArchiveName))
- throw kUnsupportedArcTypeMessage;
- HRESULT result = UpdateArchive(codecs,
- options.WildcardCensor, uo,
- errorInfo, &openCallback, &callback);
-
-#ifdef ENV_UNIX
- if (uo.SfxMode)
- {
- void myAddExeFlag(const UString &name);
- for(int i = 0; i < uo.Commands.Size(); i++)
- {
- CUpdateArchiveCommand &command = uo.Commands[i];
- if (!uo.StdOutMode)
- {
- myAddExeFlag(command.ArchivePath.GetFinalPath());
- }
- }
- }
-#endif
-
- int exitCode = NExitCode::kSuccess;
- if (callback.CantFindFiles.Size() > 0)
- {
- stdStream << endl;
- stdStream << "WARNINGS for files:" << endl << endl;
- int numErrors = callback.CantFindFiles.Size();
- for (int i = 0; i < numErrors; i++)
- {
- stdStream << callback.CantFindFiles[i] << " : ";
- stdStream << NError::MyFormatMessageW(callback.CantFindCodes[i]) << endl;
- }
- stdStream << "----------------" << endl;
- stdStream << "WARNING: Cannot find " << numErrors << " file";
- if (numErrors > 1)
- stdStream << "s";
- stdStream << endl;
- exitCode = NExitCode::kWarning;
- }
-
- if (result != S_OK)
- {
- UString message;
- if (!errorInfo.Message.IsEmpty())
- {
- message += errorInfo.Message;
- message += L"\n";
- }
- if (!errorInfo.FileName.IsEmpty())
- {
- message += errorInfo.FileName;
- message += L"\n";
- }
- if (!errorInfo.FileName2.IsEmpty())
- {
- message += errorInfo.FileName2;
- message += L"\n";
- }
- if (errorInfo.SystemError != 0)
- {
- message += NError::MyFormatMessageW(errorInfo.SystemError);
- message += L"\n";
- }
- if (!message.IsEmpty())
- stdStream << L"\nError:\n" << message;
- throw CSystemException(result);
- }
- int numErrors = callback.FailedFiles.Size();
- if (numErrors == 0)
- {
- if (callback.CantFindFiles.Size() == 0)
- stdStream << kEverythingIsOk << endl;
- }
- else
- {
- stdStream << endl;
- stdStream << "WARNINGS for files:" << endl << endl;
- for (int i = 0; i < numErrors; i++)
- {
- stdStream << callback.FailedFiles[i] << " : ";
- stdStream << NError::MyFormatMessageW(callback.FailedCodes[i]) << endl;
- }
- stdStream << "----------------" << endl;
- stdStream << "WARNING: Cannot open " << numErrors << " file";
- if (numErrors > 1)
- stdStream << "s";
- stdStream << endl;
- exitCode = NExitCode::kWarning;
- }
- return exitCode;
- }
- else
- PrintHelpAndExit(stdStream);
- return 0;
-}
diff --git a/src/libs/7zip/unix/CPP/7zip/UI/Console/MainAr.cpp b/src/libs/7zip/unix/CPP/7zip/UI/Console/MainAr.cpp
deleted file mode 100644
index 68059575b..000000000
--- a/src/libs/7zip/unix/CPP/7zip/UI/Console/MainAr.cpp
+++ /dev/null
@@ -1,127 +0,0 @@
-// MainAr.cpp
-
-#include "StdAfx.h"
-
-#include "Common/NewHandler.h" // FIXME
-
-#include "Common/MyException.h"
-#include "Common/StdOutStream.h"
-
-#include "Windows/Error.h"
-#include "Windows/NtCheck.h"
-
-#include "../Common/ArchiveCommandLine.h"
-#include "../Common/ExitCode.h"
-
-#include "ConsoleClose.h"
-
-using namespace NWindows;
-
-CStdOutStream *g_StdStream = 0;
-
-extern int Main2(
- #ifndef _WIN32
- int numArgs, const char *args[]
- #endif
-);
-
-static const char *kExceptionErrorMessage = "\n\nError:\n";
-static const char *kUserBreak = "\nBreak signaled\n";
-static const char *kMemoryExceptionMessage = "\n\nERROR: Can't allocate required memory!\n";
-static const char *kUnknownExceptionMessage = "\n\nUnknown Error\n";
-static const char *kInternalExceptionMessage = "\n\nInternal Error #";
-
-#define NT_CHECK_FAIL_ACTION (*g_StdStream) << "Unsupported Windows version"; return NExitCode::kFatalError;
-
-int MY_CDECL main
-(
- #ifndef _WIN32
- int numArgs, const char *args[]
- #endif
-)
-{
- g_StdStream = &g_StdOut;
-
- NT_CHECK
-
- NConsoleClose::CCtrlHandlerSetter ctrlHandlerSetter;
- int res = 0;
- try
- {
- res = Main2(
- #ifndef _WIN32
- numArgs, args
- #endif
- );
- }
- catch(const CNewException &)
- {
- (*g_StdStream) << kMemoryExceptionMessage;
- return (NExitCode::kMemoryError);
- }
- catch(const NConsoleClose::CCtrlBreakException &)
- {
- (*g_StdStream) << endl << kUserBreak;
- return (NExitCode::kUserBreak);
- }
- catch(const CArchiveCommandLineException &e)
- {
- (*g_StdStream) << kExceptionErrorMessage << e << endl;
- return (NExitCode::kUserError);
- }
- catch(const CSystemException &systemError)
- {
- if (systemError.ErrorCode == E_OUTOFMEMORY)
- {
- (*g_StdStream) << kMemoryExceptionMessage;
- return (NExitCode::kMemoryError);
- }
- if (systemError.ErrorCode == E_ABORT)
- {
- (*g_StdStream) << endl << kUserBreak;
- return (NExitCode::kUserBreak);
- }
- UString message;
- NError::MyFormatMessage(systemError.ErrorCode, message);
- (*g_StdStream) << endl << endl << "System error:" << endl << message << endl;
- return (NExitCode::kFatalError);
- }
- catch(NExitCode::EEnum &exitCode)
- {
- (*g_StdStream) << kInternalExceptionMessage << exitCode << endl;
- return (exitCode);
- }
- /*
- catch(const NExitCode::CMultipleErrors &multipleErrors)
- {
- (*g_StdStream) << endl << multipleErrors.NumErrors << " errors" << endl;
- return (NExitCode::kFatalError);
- }
- */
- catch(const UString &s)
- {
- (*g_StdStream) << kExceptionErrorMessage << s << endl;
- return (NExitCode::kFatalError);
- }
- catch(const AString &s)
- {
- (*g_StdStream) << kExceptionErrorMessage << s << endl;
- return (NExitCode::kFatalError);
- }
- catch(const char *s)
- {
- (*g_StdStream) << kExceptionErrorMessage << s << endl;
- return (NExitCode::kFatalError);
- }
- catch(int t)
- {
- (*g_StdStream) << kInternalExceptionMessage << t << endl;
- return (NExitCode::kFatalError);
- }
- catch(...)
- {
- (*g_StdStream) << kUnknownExceptionMessage;
- return (NExitCode::kFatalError);
- }
- return res;
-}
diff --git a/src/libs/7zip/unix/CPP/7zip/UI/Console/OpenCallbackConsole.cpp b/src/libs/7zip/unix/CPP/7zip/UI/Console/OpenCallbackConsole.cpp
deleted file mode 100644
index 7dba2ad5d..000000000
--- a/src/libs/7zip/unix/CPP/7zip/UI/Console/OpenCallbackConsole.cpp
+++ /dev/null
@@ -1,58 +0,0 @@
-// OpenCallbackConsole.cpp
-
-#include "StdAfx.h"
-
-#include "OpenCallbackConsole.h"
-
-#include "ConsoleClose.h"
-#include "UserInputUtils.h"
-
-HRESULT COpenCallbackConsole::Open_CheckBreak()
-{
- if (NConsoleClose::TestBreakSignal())
- return E_ABORT;
- return S_OK;
-}
-
-HRESULT COpenCallbackConsole::Open_SetTotal(const UInt64 *, const UInt64 *)
-{
- return Open_CheckBreak();
-}
-
-HRESULT COpenCallbackConsole::Open_SetCompleted(const UInt64 *, const UInt64 *)
-{
- return Open_CheckBreak();
-}
-
-#ifndef _NO_CRYPTO
-
-HRESULT COpenCallbackConsole::Open_CryptoGetTextPassword(BSTR *password)
-{
- PasswordWasAsked = true;
- RINOK(Open_CheckBreak());
- if (!PasswordIsDefined)
- {
- Password = GetPassword(OutStream);
- PasswordIsDefined = true;
- }
- return StringToBstr(Password, password);
-}
-
-HRESULT COpenCallbackConsole::Open_GetPasswordIfAny(UString &password)
-{
- if (PasswordIsDefined)
- password = Password;
- return S_OK;
-}
-
-bool COpenCallbackConsole::Open_WasPasswordAsked()
-{
- return PasswordWasAsked;
-}
-
-void COpenCallbackConsole::Open_ClearPasswordWasAskedFlag()
-{
- PasswordWasAsked = false;
-}
-
-#endif
diff --git a/src/libs/7zip/unix/CPP/7zip/UI/Console/OpenCallbackConsole.h b/src/libs/7zip/unix/CPP/7zip/UI/Console/OpenCallbackConsole.h
deleted file mode 100644
index c002e6a72..000000000
--- a/src/libs/7zip/unix/CPP/7zip/UI/Console/OpenCallbackConsole.h
+++ /dev/null
@@ -1,24 +0,0 @@
-// OpenCallbackConsole.h
-
-#ifndef __OPENCALLBACKCONSOLE_H
-#define __OPENCALLBACKCONSOLE_H
-
-#include "Common/StdOutStream.h"
-#include "../Common/ArchiveOpenCallback.h"
-
-class COpenCallbackConsole: public IOpenCallbackUI
-{
-public:
- INTERFACE_IOpenCallbackUI(;)
-
- CStdOutStream *OutStream;
-
- #ifndef _NO_CRYPTO
- bool PasswordIsDefined;
- bool PasswordWasAsked;
- UString Password;
- COpenCallbackConsole(): PasswordIsDefined(false), PasswordWasAsked(false) {}
- #endif
-};
-
-#endif
diff --git a/src/libs/7zip/unix/CPP/7zip/UI/Console/PercentPrinter.cpp b/src/libs/7zip/unix/CPP/7zip/UI/Console/PercentPrinter.cpp
index 28452b177..f2889957a 100644
--- a/src/libs/7zip/unix/CPP/7zip/UI/Console/PercentPrinter.cpp
+++ b/src/libs/7zip/unix/CPP/7zip/UI/Console/PercentPrinter.cpp
@@ -2,18 +2,18 @@
#include "StdAfx.h"
-#include "Common/IntToString.h"
-#include "Common/MyString.h"
+#include "../../../Common/Defs.h"
+#include "../../../Common/IntToString.h"
#include "PercentPrinter.h"
-const int kPaddingSize = 2;
-const int kPercentsSize = 4;
-const int kMaxExtraSize = kPaddingSize + 32 + kPercentsSize;
+static const unsigned kPaddingSize = 2;
+static const unsigned kPercentsSize = 4;
+static const unsigned kMaxExtraSize = kPaddingSize + 32 + kPercentsSize;
-static void ClearPrev(char *p, int num)
+static void ClearPrev(char *p, unsigned num)
{
- int i;
+ unsigned i;
for (i = 0; i < num; i++) *p++ = '\b';
for (i = 0; i < num; i++) *p++ = ' ';
for (i = 0; i < num; i++) *p++ = '\b';
@@ -51,18 +51,30 @@ void CPercentPrinter::PrintNewLine()
void CPercentPrinter::RePrintRatio()
{
char s[32];
- ConvertUInt64ToString(((m_Total == 0) ? 0 : (m_CurValue * 100 / m_Total)), s);
- int size = (int)strlen(s);
- s[size++] = '%';
- s[size] = '\0';
+ unsigned size;
+ {
+ char c = '%';
+ UInt64 value = 0;
+ if (m_Total == (UInt64)(Int64)-1)
+ {
+ value = m_CurValue >> 20;
+ c = 'M';
+ }
+ else if (m_Total != 0)
+ value = m_CurValue * 100 / m_Total;
+ ConvertUInt64ToString(value, s);
+ size = (unsigned)strlen(s);
+ s[size++] = c;
+ s[size] = '\0';
+ }
- int extraSize = kPaddingSize + MyMax(size, kPercentsSize);
+ unsigned extraSize = kPaddingSize + MyMax(size, kPercentsSize);
if (extraSize < m_NumExtraChars)
extraSize = m_NumExtraChars;
char fullString[kMaxExtraSize * 3];
char *p = fullString;
- int i;
+ unsigned i;
if (m_NumExtraChars == 0)
{
for (i = 0; i < extraSize; i++)
@@ -73,7 +85,7 @@ void CPercentPrinter::RePrintRatio()
for (i = 0; i < m_NumExtraChars; i++)
*p++ = '\b';
m_NumExtraChars = extraSize;
- for (; size < m_NumExtraChars; size++)
+ for (; size < extraSize; size++)
*p++ = ' ';
MyStringCopy(p, s);
(*OutStream) << fullString;
diff --git a/src/libs/7zip/unix/CPP/7zip/UI/Console/PercentPrinter.h b/src/libs/7zip/unix/CPP/7zip/UI/Console/PercentPrinter.h
index 97f2e6adb..509bab5fc 100644
--- a/src/libs/7zip/unix/CPP/7zip/UI/Console/PercentPrinter.h
+++ b/src/libs/7zip/unix/CPP/7zip/UI/Console/PercentPrinter.h
@@ -1,10 +1,9 @@
// PercentPrinter.h
-#ifndef __PERCENTPRINTER_H
-#define __PERCENTPRINTER_H
+#ifndef __PERCENT_PRINTER_H
+#define __PERCENT_PRINTER_H
-#include "Common/Types.h"
-#include "Common/StdOutStream.h"
+#include "../../../Common/StdOutStream.h"
class CPercentPrinter
{
@@ -12,12 +11,12 @@ class CPercentPrinter
UInt64 m_PrevValue;
UInt64 m_CurValue;
UInt64 m_Total;
- int m_NumExtraChars;
+ unsigned m_NumExtraChars;
public:
CStdOutStream *OutStream;
CPercentPrinter(UInt64 minStepSize = 1): m_MinStepSize(minStepSize),
- m_PrevValue(0), m_CurValue(0), m_Total(1), m_NumExtraChars(0) {}
+ m_PrevValue(0), m_CurValue(0), m_Total((UInt64)(Int64)-1), m_NumExtraChars(0) {}
void SetTotal(UInt64 total) { m_Total = total; m_PrevValue = 0; }
void SetRatio(UInt64 doneValue) { m_CurValue = doneValue; }
void PrintString(const char *s);
diff --git a/src/libs/7zip/unix/CPP/7zip/UI/Console/UpdateCallbackConsole.cpp b/src/libs/7zip/unix/CPP/7zip/UI/Console/UpdateCallbackConsole.cpp
deleted file mode 100644
index e0eb4dec7..000000000
--- a/src/libs/7zip/unix/CPP/7zip/UI/Console/UpdateCallbackConsole.cpp
+++ /dev/null
@@ -1,261 +0,0 @@
-// UpdateCallbackConsole.cpp
-
-#include "StdAfx.h"
-
-#include "UpdateCallbackConsole.h"
-
-#include "Windows/Error.h"
-#ifndef _7ZIP_ST
-#include "Windows/Synchronization.h"
-#endif
-
-#include "ConsoleClose.h"
-#include "UserInputUtils.h"
-
-using namespace NWindows;
-
-#ifndef _7ZIP_ST
-static NSynchronization::CCriticalSection g_CriticalSection;
-#define MT_LOCK NSynchronization::CCriticalSectionLock lock(g_CriticalSection);
-#else
-#define MT_LOCK
-#endif
-
-static const wchar_t *kEmptyFileAlias = L"[Content]";
-
-static const char *kCreatingArchiveMessage = "Creating archive ";
-static const char *kUpdatingArchiveMessage = "Updating archive ";
-static const char *kScanningMessage = "Scanning";
-
-
-HRESULT CUpdateCallbackConsole::OpenResult(const wchar_t *name, HRESULT result)
-{
- (*OutStream) << endl;
- if (result != S_OK)
- (*OutStream) << "Error: " << name << " is not supported archive" << endl;
- return S_OK;
-}
-
-HRESULT CUpdateCallbackConsole::StartScanning()
-{
- (*OutStream) << kScanningMessage;
- return S_OK;
-}
-
-HRESULT CUpdateCallbackConsole::ScanProgress(UInt64 /* numFolders */, UInt64 /* numFiles */, const wchar_t * /* path */)
-{
- return CheckBreak();
-}
-
-HRESULT CUpdateCallbackConsole::CanNotFindError(const wchar_t *name, DWORD systemError)
-{
- CantFindFiles.Add(name);
- CantFindCodes.Add(systemError);
- // m_PercentPrinter.ClosePrint();
- if (!m_WarningsMode)
- {
- (*OutStream) << endl << endl;
- m_PercentPrinter.PrintNewLine();
- m_WarningsMode = true;
- }
- m_PercentPrinter.PrintString(name);
- m_PercentPrinter.PrintString(": WARNING: ");
- m_PercentPrinter.PrintString(NError::MyFormatMessageW(systemError));
- m_PercentPrinter.PrintNewLine();
- return S_OK;
-}
-
-HRESULT CUpdateCallbackConsole::FinishScanning()
-{
- (*OutStream) << endl << endl;
- return S_OK;
-}
-
-HRESULT CUpdateCallbackConsole::StartArchive(const wchar_t *name, bool updating)
-{
- if(updating)
- (*OutStream) << kUpdatingArchiveMessage;
- else
- (*OutStream) << kCreatingArchiveMessage;
- if (name != 0)
- (*OutStream) << name;
- else
- (*OutStream) << "StdOut";
- (*OutStream) << endl << endl;
- return S_OK;
-}
-
-HRESULT CUpdateCallbackConsole::FinishArchive()
-{
- (*OutStream) << endl;
- return S_OK;
-}
-
-HRESULT CUpdateCallbackConsole::CheckBreak()
-{
- if (NConsoleClose::TestBreakSignal())
- return E_ABORT;
- return S_OK;
-}
-
-HRESULT CUpdateCallbackConsole::Finilize()
-{
- MT_LOCK
- if (m_NeedBeClosed)
- {
- if (EnablePercents)
- {
- m_PercentPrinter.ClosePrint();
- }
- if (!StdOutMode && m_NeedNewLine)
- {
- m_PercentPrinter.PrintNewLine();
- m_NeedNewLine = false;
- }
- m_NeedBeClosed = false;
- }
- return S_OK;
-}
-
-HRESULT CUpdateCallbackConsole::SetNumFiles(UInt64 /* numFiles */)
-{
- return S_OK;
-}
-
-HRESULT CUpdateCallbackConsole::SetTotal(UInt64 size)
-{
- MT_LOCK
- if (EnablePercents)
- m_PercentPrinter.SetTotal(size);
- return S_OK;
-}
-
-HRESULT CUpdateCallbackConsole::SetCompleted(const UInt64 *completeValue)
-{
- MT_LOCK
- if (completeValue != NULL)
- {
- if (EnablePercents)
- {
- m_PercentPrinter.SetRatio(*completeValue);
- m_PercentPrinter.PrintRatio();
- m_NeedBeClosed = true;
- }
- }
- if (NConsoleClose::TestBreakSignal())
- return E_ABORT;
- return S_OK;
-}
-
-HRESULT CUpdateCallbackConsole::SetRatioInfo(const UInt64 * /* inSize */, const UInt64 * /* outSize */)
-{
- if (NConsoleClose::TestBreakSignal())
- return E_ABORT;
- return S_OK;
-}
-
-HRESULT CUpdateCallbackConsole::GetStream(const wchar_t *name, bool isAnti)
-{
- MT_LOCK
- if (StdOutMode)
- return S_OK;
- if(isAnti)
- m_PercentPrinter.PrintString("Anti item ");
- else
- m_PercentPrinter.PrintString("Compressing ");
- if (name[0] == 0)
- name = kEmptyFileAlias;
- m_PercentPrinter.PrintString(name);
- if (EnablePercents)
- m_PercentPrinter.RePrintRatio();
- return S_OK;
-}
-
-HRESULT CUpdateCallbackConsole::OpenFileError(const wchar_t *name, DWORD systemError)
-{
- MT_LOCK
- FailedCodes.Add(systemError);
- FailedFiles.Add(name);
- // if (systemError == ERROR_SHARING_VIOLATION)
- {
- m_PercentPrinter.ClosePrint();
- m_PercentPrinter.PrintNewLine();
- m_PercentPrinter.PrintString("WARNING: ");
- m_PercentPrinter.PrintString(NError::MyFormatMessageW(systemError));
- return S_FALSE;
- }
- // return systemError;
-}
-
-HRESULT CUpdateCallbackConsole::SetOperationResult(Int32 )
-{
- m_NeedBeClosed = true;
- m_NeedNewLine = true;
- return S_OK;
-}
-
-HRESULT CUpdateCallbackConsole::CryptoGetTextPassword2(Int32 *passwordIsDefined, BSTR *password)
-{
- *password = NULL;
-
- #ifdef _NO_CRYPTO
-
- *passwordIsDefined = false;
- return S_OK;
-
- #else
-
- if (!PasswordIsDefined)
- {
- if (AskPassword)
- {
- Password = GetPassword(OutStream,true);
- PasswordIsDefined = true;
- }
- }
- *passwordIsDefined = BoolToInt(PasswordIsDefined);
- return StringToBstr(Password, password);
-
- #endif
-}
-
-HRESULT CUpdateCallbackConsole::CryptoGetTextPassword(BSTR *password)
-{
- *password = NULL;
-
- #ifdef _NO_CRYPTO
-
- return E_NOTIMPL;
-
- #else
-
- if (!PasswordIsDefined)
- {
- {
- Password = GetPassword(OutStream);
- PasswordIsDefined = true;
- }
- }
- return StringToBstr(Password, password);
-
- #endif
-}
-
-/*
-HRESULT CUpdateCallbackConsole::ShowDeleteFile(const wchar_t *name)
-{
- // MT_LOCK
- if (StdOutMode)
- return S_OK;
- RINOK(Finilize());
- m_PercentPrinter.PrintString("Deleting ");
- if (name[0] == 0)
- name = kEmptyFileAlias;
- m_PercentPrinter.PrintString(name);
- if (EnablePercents)
- m_PercentPrinter.RePrintRatio();
- m_NeedBeClosed = true;
- m_NeedNewLine = true;
- return S_OK;
-}
-*/
diff --git a/src/libs/7zip/unix/CPP/7zip/UI/Console/UpdateCallbackConsole.h b/src/libs/7zip/unix/CPP/7zip/UI/Console/UpdateCallbackConsole.h
deleted file mode 100644
index 5ffe3eb7a..000000000
--- a/src/libs/7zip/unix/CPP/7zip/UI/Console/UpdateCallbackConsole.h
+++ /dev/null
@@ -1,62 +0,0 @@
-// UpdateCallbackConsole.h
-
-#ifndef __UPDATE_CALLBACK_CONSOLE_H
-#define __UPDATE_CALLBACK_CONSOLE_H
-
-#include "Common/StdOutStream.h"
-
-#include "../Common/Update.h"
-
-#include "PercentPrinter.h"
-
-class CUpdateCallbackConsole: public IUpdateCallbackUI2
-{
- CPercentPrinter m_PercentPrinter;
- bool m_NeedBeClosed;
- bool m_NeedNewLine;
-
- bool m_WarningsMode;
-
- CStdOutStream *OutStream;
-public:
- bool EnablePercents;
- bool StdOutMode;
-
- #ifndef _NO_CRYPTO
- bool PasswordIsDefined;
- UString Password;
- bool AskPassword;
- #endif
-
- CUpdateCallbackConsole():
- m_PercentPrinter(1 << 16),
- #ifndef _NO_CRYPTO
- PasswordIsDefined(false),
- AskPassword(false),
- #endif
- StdOutMode(false),
- EnablePercents(true),
- m_WarningsMode(false)
- {}
-
- ~CUpdateCallbackConsole() { Finilize(); }
- void Init(CStdOutStream *outStream)
- {
- m_NeedBeClosed = false;
- m_NeedNewLine = false;
- FailedFiles.Clear();
- FailedCodes.Clear();
- OutStream = outStream;
- m_PercentPrinter.OutStream = outStream;
- }
-
- INTERFACE_IUpdateCallbackUI2(;)
-
- UStringVector FailedFiles;
- CRecordVector<HRESULT> FailedCodes;
-
- UStringVector CantFindFiles;
- CRecordVector<HRESULT> CantFindCodes;
-};
-
-#endif
diff --git a/src/libs/7zip/unix/CPP/7zip/UI/Console/UserInputUtils.cpp b/src/libs/7zip/unix/CPP/7zip/UI/Console/UserInputUtils.cpp
deleted file mode 100644
index 4733e4ffb..000000000
--- a/src/libs/7zip/unix/CPP/7zip/UI/Console/UserInputUtils.cpp
+++ /dev/null
@@ -1,96 +0,0 @@
-// UserInputUtils.cpp
-
-#include "StdAfx.h"
-
-#include "Common/StdInStream.h"
-#include "Common/StringConvert.h"
-
-#include "UserInputUtils.h"
-
-#ifdef USE_FLTK
-// the programs like file-roller or xarchiver do not support archives with password
-// these programs freeze because p7zip is waiting for a password
-// defining USE_FLTK allows p7zip to use a popup in order to ask the password.
-#include <FL/Fl.H>
-#include <FL/Fl_Window.H>
-#include <FL/fl_ask.H>
-#else
-#ifdef ENV_HAVE_GETPASS
-#include <pwd.h>
-#include <unistd.h>
-#include "Common/MyException.h"
-#endif
-#endif
-
-static const char kYes = 'Y';
-static const char kNo = 'N';
-static const char kYesAll = 'A';
-static const char kNoAll = 'S';
-static const char kAutoRenameAll = 'U';
-static const char kQuit = 'Q';
-
-static const char *kFirstQuestionMessage = "?\n";
-static const char *kHelpQuestionMessage =
- "(Y)es / (N)o / (A)lways / (S)kip all / A(u)to rename all / (Q)uit? ";
-
-// return true if pressed Quite;
-
-NUserAnswerMode::EEnum ScanUserYesNoAllQuit(CStdOutStream *outStream)
-{
- (*outStream) << kFirstQuestionMessage;
- for (;;)
- {
- (*outStream) << kHelpQuestionMessage;
- outStream->Flush();
- AString scannedString = g_StdIn.ScanStringUntilNewLine();
- scannedString.Trim();
- if (!scannedString.IsEmpty())
- switch(
- ::MyCharUpper(
- #ifdef UNDER_CE
- (wchar_t)
- #endif
- scannedString[0]))
- {
- case kYes:
- return NUserAnswerMode::kYes;
- case kNo:
- return NUserAnswerMode::kNo;
- case kYesAll:
- return NUserAnswerMode::kYesAll;
- case kNoAll:
- return NUserAnswerMode::kNoAll;
- case kAutoRenameAll:
- return NUserAnswerMode::kAutoRenameAll;
- case kQuit:
- return NUserAnswerMode::kQuit;
- }
- }
-}
-
-UString GetPassword(CStdOutStream *outStream,bool verify)
-{
-#ifdef USE_FLTK
- const char *r = fl_password("Enter password", 0);
- AString oemPassword = "";
- if (r) oemPassword = r;
-#else /* USE_FLTK */
-#ifdef ENV_HAVE_GETPASS
- (*outStream) << "\nEnter password (will not be echoed) :";
- outStream->Flush();
- AString oemPassword = getpass("");
- if (verify)
- {
- (*outStream) << "Verify password (will not be echoed) :";
- outStream->Flush();
- AString oemPassword2 = getpass("");
- if (oemPassword != oemPassword2) throw "password verification failed";
- }
-#else
- (*outStream) << "\nEnter password:";
- outStream->Flush();
- AString oemPassword = g_StdIn.ScanStringUntilNewLine();
-#endif
-#endif /* USE_FLTK */
- return MultiByteToUnicodeString(oemPassword, CP_OEMCP);
-}
diff --git a/src/libs/7zip/unix/CPP/7zip/UI/Console/UserInputUtils.h b/src/libs/7zip/unix/CPP/7zip/UI/Console/UserInputUtils.h
deleted file mode 100644
index 8c575194d..000000000
--- a/src/libs/7zip/unix/CPP/7zip/UI/Console/UserInputUtils.h
+++ /dev/null
@@ -1,24 +0,0 @@
-// UserInputUtils.h
-
-#ifndef __USERINPUTUTILS_H
-#define __USERINPUTUTILS_H
-
-#include "Common/StdOutStream.h"
-
-namespace NUserAnswerMode {
-
-enum EEnum
-{
- kYes,
- kNo,
- kYesAll,
- kNoAll,
- kAutoRenameAll,
- kQuit
-};
-}
-
-NUserAnswerMode::EEnum ScanUserYesNoAllQuit(CStdOutStream *outStream);
-UString GetPassword(CStdOutStream *outStream,bool verify = false);
-
-#endif