diff options
Diffstat (limited to 'src/libs/7zip/unix/CPP/7zip/UI/Common/ArchiveCommandLine.cpp')
-rw-r--r-- | src/libs/7zip/unix/CPP/7zip/UI/Common/ArchiveCommandLine.cpp | 1216 |
1 files changed, 736 insertions, 480 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; } |