📄 archivecommandline.cpp
字号:
// ArchiveCommandLine.cpp#include "StdAfx.h"#include <io.h>#include <stdio.h>#include "Common/ListFileUtils.h"#include "Common/StringConvert.h"#include "Common/StringToInt.h"#include "Windows/FileName.h"#include "Windows/FileDir.h"#ifdef _WIN32#include "Windows/FileMapping.h"#include "Windows/Synchronization.h"#endif#include "ArchiveCommandLine.h"#include "UpdateAction.h"#include "Update.h"#include "ArchiverInfo.h"#include "SortUtils.h"#include "EnumDirItems.h"#ifdef HAVE_LSTATextern int global_use_lstat;#endifusing namespace NCommandLineParser;using namespace NWindows;using namespace NFile;static const int kNumSwitches = 27;namespace NKey {enum Enum{ kHelp1 = 0, kHelp2, kHelp3, kDisableHeaders, kDisablePercents, kArchiveType, kYes, kPassword, kProperty, kOutputDir, kWorkingDir, kInclude, kExclude, kArInclude, kArExclude, kNoArName, kUpdate, kVolume, kRecursed, kSfx, kStdIn, kStdOut, kOverwrite, kEmail, kShowDialog, kUseLStat, kTechMode};}static const wchar_t kRecursedIDChar = 'R';static const wchar_t *kRecursedPostCharSet = L"0-";static const wchar_t *kDefaultArchiveType = L"7z";static const wchar_t *kSFXExtension = #ifdef _WIN32 L"exe"; #else L""; #endifnamespace NRecursedPostCharIndex { enum EEnum { kWildCardRecursionOnly = 0, kNoRecursion = 1 };}static const char kImmediateNameID = '!';static const char kMapNameID = '#';static const char kFileListID = '@';static const char kSomeCludePostStringMinSize = 2; // at least <@|!><N>ame must bestatic const char kSomeCludeAfterRecursedPostStringMinSize = 2; // at least <@|!><N>ame must bestatic const wchar_t *kOverwritePostCharSet = L"asut";NExtract::NOverwriteMode::EEnum k_OverwriteModes[] ={ NExtract::NOverwriteMode::kWithoutPrompt, NExtract::NOverwriteMode::kSkipExisting, NExtract::NOverwriteMode::kAutoRename, NExtract::NOverwriteMode::kAutoRenameExisting};static const CSwitchForm kSwitchForms[kNumSwitches] = { { 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 }, { L"P", NSwitchType::kUnLimitedPostString, false, 0 }, { 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"L", NSwitchType::kSimple, false }, { L"SLT", NSwitchType::kSimple, false } };static const int kNumCommandForms = 7;static const CCommandForm g_CommandForms[kNumCommandForms] = { { L"A", false }, { L"U", false }, { L"D", false }, { L"T", false }, { L"E", false }, { L"X", false }, { L"L", false }};static const int kMaxCmdLineSize = 1000;static const wchar_t *kUniversalWildcard = L"*";static const int kMinNonSwitchWords = 1;static const int kCommandIndex = 0;// ---------------------------// exception messagesstatic const char *kUserErrorMessage = "Incorrect command line";static const char *kIncorrectListFile = "Incorrect wildcard in listfile";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";// ---------------------------bool CArchiveCommand::IsFromExtractGroup() const{ switch(CommandType) { case NCommandType::kTest: case NCommandType::kExtract: case NCommandType::kFullExtract: return true; default: return false; }}NExtract::NPathMode::EEnum CArchiveCommand::GetPathMode() const{ switch(CommandType) { case NCommandType::kTest: case NCommandType::kFullExtract: return NExtract::NPathMode::kFullPathnames; default: return NExtract::NPathMode::kNoPathnames; }}bool CArchiveCommand::IsFromUpdateGroup() const{ return (CommandType == NCommandType::kAdd || CommandType == NCommandType::kUpdate || CommandType == NCommandType::kDelete);}static NRecursedType::EEnum GetRecursedTypeFromIndex(int index){ switch (index) { case NRecursedPostCharIndex::kWildCardRecursionOnly: return NRecursedType::kWildCardOnlyRecursed; case NRecursedPostCharIndex::kNoRecursion: return NRecursedType::kNonRecursed; default: return NRecursedType::kRecursed; }}static bool ParseArchiveCommand(const UString &commandString, CArchiveCommand &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;}// ------------------------------------------------------------------// filenames functionsstatic bool AddNameToCensor(NWildcard::CCensor &wildcardCensor, const UString &name, bool include, NRecursedType::EEnum type){ bool isWildCard = DoesNameContainWildCard(name); bool recursed; switch (type) { case NRecursedType::kWildCardOnlyRecursed: recursed = isWildCard; break; case NRecursedType::kRecursed: recursed = true; break; case NRecursedType::kNonRecursed: recursed = false; break; } wildcardCensor.AddItem(include, name, recursed); return true;}static inline UINT GetCurrentCodePage() { return AreFileApisANSI() ? CP_ACP : CP_OEMCP; } static void AddToCensorFromListFile(NWildcard::CCensor &wildcardCensor, LPCWSTR fileName, bool include, NRecursedType::EEnum type, UINT codePage){ UStringVector names; if (!ReadNamesFromListFile(GetSystemString(fileName, GetCurrentCodePage()), names, codePage)) throw kIncorrectListFile; for (int i = 0; i < names.Size(); i++) if (!AddNameToCensor(wildcardCensor, names[i], include, type)) throw kIncorrectWildCardInListFile;}static void AddCommandLineWildCardToCensr(NWildcard::CCensor &wildcardCensor, const UString &name, bool include, NRecursedType::EEnum recursedType){ if (!AddNameToCensor(wildcardCensor, name, include, recursedType)) throw kIncorrectWildCardInCommandLine;}static void AddToCensorFromNonSwitchesStrings( int startIndex, NWildcard::CCensor &wildcardCensor, const UStringVector &nonSwitchStrings, NRecursedType::EEnum type, bool thereAreSwitchIncludes, UINT codePage){ if(nonSwitchStrings.Size() == startIndex && (!thereAreSwitchIncludes)) AddCommandLineWildCardToCensr(wildcardCensor, kUniversalWildcard, true, type); for(int i = startIndex; i < nonSwitchStrings.Size(); i++) { const UString &s = nonSwitchStrings[i]; if (s[0] == kFileListID) AddToCensorFromListFile(wildcardCensor, s.Mid(1), true, type, codePage); else AddCommandLineWildCardToCensr(wildcardCensor, s, true, type); }}#ifdef _WIN32static void ParseMapWithPaths(NWildcard::CCensor &wildcardCensor, const UString &switchParam, bool include, NRecursedType::EEnum commonRecursedType){ int splitPos = switchParam.Find(L':'); if (splitPos < 0) throw kUserErrorMessage; UString mappingName = switchParam.Left(splitPos); UString switchParam2 = switchParam.Mid(splitPos + 1); splitPos = switchParam2.Find(L':'); if (splitPos < 0) throw kUserErrorMessage; 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, false, GetSystemString(mappingName))) throw L"Can not open mapping"; LPVOID data = fileMapping.MapViewOfFile(FILE_MAP_READ, 0, dataSize); if (data == NULL) throw L"MapViewOfFile error"; try { const wchar_t *curData = (const wchar_t *)data; if (*curData != 0) throw L"Incorrect mapping data"; UInt32 numChars = dataSize / sizeof(wchar_t); UString name; for (UInt32 i = 1; i < numChars; i++) { wchar_t c = curData[i]; if (c == L'\0') { AddCommandLineWildCardToCensr(wildcardCensor, name, include, commonRecursedType); name.Empty(); } else name += c; } if (!name.IsEmpty()) throw L"data error"; } catch(...) { UnmapViewOfFile(data); throw; } UnmapViewOfFile(data); } { NSynchronization::CEvent event; event.Open(EVENT_MODIFY_STATE, false, GetSystemString(eventName)); event.Set(); }}#endifstatic void AddSwitchWildCardsToCensor(NWildcard::CCensor &wildcardCensor, const UStringVector &strings, bool include, NRecursedType::EEnum commonRecursedType, UINT codePage){ for(int i = 0; i < strings.Size(); i++) { const UString &name = strings[i]; NRecursedType::EEnum recursedType; int pos = 0; if (name.Length() < kSomeCludePostStringMinSize) throw kUserErrorMessage; if (::MyCharUpper(name[pos]) == kRecursedIDChar) { pos++; int index = UString(kRecursedPostCharSet).Find(name[pos]); recursedType = GetRecursedTypeFromIndex(index); if (index >= 0) pos++; } else recursedType = commonRecursedType; if (name.Length() < pos + kSomeCludeAfterRecursedPostStringMinSize) throw kUserErrorMessage; UString tail = name.Mid(pos + 1); if (name[pos] == kImmediateNameID) AddCommandLineWildCardToCensr(wildcardCensor, tail, include, recursedType); else if (name[pos] == kFileListID) AddToCensorFromListFile(wildcardCensor, tail, include, recursedType, codePage); #ifdef _WIN32 else if (name[pos] == kMapNameID) ParseMapWithPaths(wildcardCensor, tail, include, recursedType); #endif else throw kUserErrorMessage; }}#ifdef _WIN32// This code converts all short file names to long file names.static void ConvertToLongName(const UString &prefix, UString &name){ if (name.IsEmpty() || DoesNameContainWildCard(name)) return; NFind::CFileInfoW fileInfo; if (NFind::FindFile(prefix + name, fileInfo)) name = fileInfo.Name;}static void ConvertToLongNames(const UString &prefix, CObjectVector<NWildcard::CItem> &items){ for (int i = 0; i < items.Size(); i++) { NWildcard::CItem &item = items[i]; if (item.Recursive || item.PathParts.Size() != 1) continue; ConvertToLongName(prefix, item.PathParts.Front()); }}static void ConvertToLongNames(const UString &prefix, NWildcard::CCensorNode &node){ ConvertToLongNames(prefix, node.IncludeItems); ConvertToLongNames(prefix, node.ExcludeItems); int i; for (i = 0; i < node.SubNodes.Size(); i++) ConvertToLongName(prefix, node.SubNodes[i].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();) { const NWildcard::CCensorNode &nextNode2 = node.SubNodes[j]; if (nextNode1.Name.CompareNoCase(nextNode2.Name) == 0) { nextNode1.IncludeItems += nextNode2.IncludeItems; nextNode1.ExcludeItems += nextNode2.ExcludeItems; node.SubNodes.Delete(j); } else j++; } } for (i = 0; i < node.SubNodes.Size(); i++) { NWildcard::CCensorNode &nextNode = node.SubNodes[i]; ConvertToLongNames(prefix + nextNode.Name + wchar_t(NFile::NName::kDirDelimiter), nextNode); }}static void ConvertToLongNames(NWildcard::CCensor &censor){ for (int i = 0; i < censor.Pairs.Size(); i++) { NWildcard::CPair &pair = censor.Pairs[i]; ConvertToLongNames(pair.Prefix, pair.Head); }}#endifstatic NUpdateArchive::NPairAction::EEnum GetUpdatePairActionType(int i){ switch(i) { case NUpdateArchive::NPairAction::kIgnore: return NUpdateArchive::NPairAction::kIgnore; case NUpdateArchive::NPairAction::kCopy: return NUpdateArchive::NPairAction::kCopy; case NUpdateArchive::NPairAction::kCompress: return NUpdateArchive::NPairAction::kCompress; case NUpdateArchive::NPairAction::kCompressAsAnti: return NUpdateArchive::NPairAction::kCompressAsAnti; } throw 98111603;}const UString kUpdatePairStateIDSet = L"PQRXYZW";const int kUpdatePairStateNotSupportedActions[] = {2, 2, 1, -1, -1, -1, -1};const UString kUpdatePairActionIDSet = L"0123"; //Ignore, Copy, Compress, Create Anticonst wchar_t *kUpdateIgnoreItselfPostStringID = L"-"; const wchar_t kUpdateNewArchivePostCharID = '!'; static bool ParseUpdateCommandString2(const UString &command, NUpdateArchive::CActionSet &actionSet, UString &postString)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -