Move placement of lzma.

This commit is contained in:
2023-09-24 02:41:01 +01:00
parent fb79a7ddf6
commit 7cc2d1c72e
687 changed files with 2 additions and 2 deletions

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,235 @@
# Microsoft Developer Studio Project File - Name="Client7z" - Package Owner=<4>
# Microsoft Developer Studio Generated Build File, Format Version 6.00
# ** DO NOT EDIT **
# TARGTYPE "Win32 (x86) Console Application" 0x0103
CFG=Client7z - Win32 Debug
!MESSAGE This is not a valid makefile. To build this project using NMAKE,
!MESSAGE use the Export Makefile command and run
!MESSAGE
!MESSAGE NMAKE /f "Client7z.mak".
!MESSAGE
!MESSAGE You can specify a configuration when running NMAKE
!MESSAGE by defining the macro CFG on the command line. For example:
!MESSAGE
!MESSAGE NMAKE /f "Client7z.mak" CFG="Client7z - Win32 Debug"
!MESSAGE
!MESSAGE Possible choices for configuration are:
!MESSAGE
!MESSAGE "Client7z - Win32 Release" (based on "Win32 (x86) Console Application")
!MESSAGE "Client7z - Win32 Debug" (based on "Win32 (x86) Console Application")
!MESSAGE
# Begin Project
# PROP AllowPerConfigDependencies 0
# PROP Scc_ProjName ""
# PROP Scc_LocalPath ""
CPP=cl.exe
RSC=rc.exe
!IF "$(CFG)" == "Client7z - Win32 Release"
# PROP BASE Use_MFC 0
# PROP BASE Use_Debug_Libraries 0
# PROP BASE Output_Dir "Release"
# PROP BASE Intermediate_Dir "Release"
# PROP BASE Target_Dir ""
# PROP Use_MFC 0
# PROP Use_Debug_Libraries 0
# PROP Output_Dir "Release"
# PROP Intermediate_Dir "Release"
# PROP Ignore_Export_Lib 0
# PROP Target_Dir ""
# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /Yu"stdafx.h" /FD /c
# ADD CPP /nologo /MD /W4 /WX /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /Yu"stdafx.h" /FD /c
# ADD BASE RSC /l 0x419 /d "NDEBUG"
# ADD RSC /l 0x419 /d "NDEBUG"
BSC32=bscmake.exe
# ADD BASE BSC32 /nologo
# ADD BSC32 /nologo
LINK32=link.exe
# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386
# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386 /out:"Release/7zcl.exe"
!ELSEIF "$(CFG)" == "Client7z - Win32 Debug"
# PROP BASE Use_MFC 0
# PROP BASE Use_Debug_Libraries 1
# PROP BASE Output_Dir "Debug"
# PROP BASE Intermediate_Dir "Debug"
# PROP BASE Target_Dir ""
# PROP Use_MFC 0
# PROP Use_Debug_Libraries 1
# PROP Output_Dir "Debug"
# PROP Intermediate_Dir "Debug"
# PROP Ignore_Export_Lib 0
# PROP Target_Dir ""
# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /Yu"stdafx.h" /FD /GZ /c
# ADD CPP /nologo /MDd /W4 /WX /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /Yu"stdafx.h" /FD /GZ /c
# ADD BASE RSC /l 0x419 /d "_DEBUG"
# ADD RSC /l 0x419 /d "_DEBUG"
BSC32=bscmake.exe
# ADD BASE BSC32 /nologo
# ADD BSC32 /nologo
LINK32=link.exe
# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept
# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /out:"Debug/7zcl.exe" /pdbtype:sept
!ENDIF
# Begin Target
# Name "Client7z - Win32 Release"
# Name "Client7z - Win32 Debug"
# Begin Group "Spec"
# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"
# Begin Source File
SOURCE=.\resource.rc
# End Source File
# Begin Source File
SOURCE=.\StdAfx.cpp
# ADD CPP /Yc"stdafx.h"
# End Source File
# Begin Source File
SOURCE=.\StdAfx.h
# End Source File
# End Group
# Begin Group "Windows"
# PROP Default_Filter ""
# Begin Source File
SOURCE=..\..\..\Windows\DLL.cpp
# End Source File
# Begin Source File
SOURCE=..\..\..\Windows\DLL.h
# End Source File
# Begin Source File
SOURCE=..\..\..\Windows\FileDir.cpp
# End Source File
# Begin Source File
SOURCE=..\..\..\Windows\FileDir.h
# End Source File
# Begin Source File
SOURCE=..\..\..\Windows\FileFind.cpp
# End Source File
# Begin Source File
SOURCE=..\..\..\Windows\FileFind.h
# End Source File
# Begin Source File
SOURCE=..\..\..\Windows\FileIO.cpp
# End Source File
# Begin Source File
SOURCE=..\..\..\Windows\FileIO.h
# End Source File
# Begin Source File
SOURCE=..\..\..\Windows\FileName.cpp
# End Source File
# Begin Source File
SOURCE=..\..\..\Windows\FileName.h
# End Source File
# Begin Source File
SOURCE=..\..\..\Windows\PropVariant.cpp
# End Source File
# Begin Source File
SOURCE=..\..\..\Windows\PropVariant.h
# End Source File
# Begin Source File
SOURCE=..\..\..\Windows\PropVariantConv.cpp
# End Source File
# Begin Source File
SOURCE=..\..\..\Windows\PropVariantConv.h
# End Source File
# End Group
# Begin Group "Common"
# PROP Default_Filter ""
# Begin Source File
SOURCE=..\..\..\Common\IntToString.cpp
# End Source File
# Begin Source File
SOURCE=..\..\..\Common\IntToString.h
# End Source File
# Begin Source File
SOURCE=..\..\..\Common\MyString.cpp
# End Source File
# Begin Source File
SOURCE=..\..\..\Common\MyString.h
# End Source File
# Begin Source File
SOURCE=..\..\..\Common\MyVector.cpp
# End Source File
# Begin Source File
SOURCE=..\..\..\Common\MyVector.h
# End Source File
# Begin Source File
SOURCE=..\..\..\Common\NewHandler.cpp
# End Source File
# Begin Source File
SOURCE=..\..\..\Common\NewHandler.h
# End Source File
# Begin Source File
SOURCE=..\..\..\Common\StringConvert.cpp
# End Source File
# Begin Source File
SOURCE=..\..\..\Common\StringConvert.h
# End Source File
# Begin Source File
SOURCE=..\..\..\Common\Wildcard.cpp
# End Source File
# Begin Source File
SOURCE=..\..\..\Common\Wildcard.h
# End Source File
# End Group
# Begin Group "7zip Common"
# PROP Default_Filter ""
# Begin Source File
SOURCE=..\..\Common\FileStreams.cpp
# End Source File
# Begin Source File
SOURCE=..\..\Common\FileStreams.h
# End Source File
# End Group
# Begin Source File
SOURCE=.\Client7z.cpp
# End Source File
# Begin Source File
SOURCE=..\..\..\..\C\Sort.h
# End Source File
# End Target
# End Project

View File

@@ -0,0 +1,29 @@
Microsoft Developer Studio Workspace File, Format Version 6.00
# WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE!
###############################################################################
Project: "Client7z"=.\Client7z.dsp - Package Owner=<4>
Package=<5>
{{{
}}}
Package=<4>
{{{
}}}
###############################################################################
Global:
Package=<5>
{{{
}}}
Package=<3>
{{{
}}}
###############################################################################

View File

@@ -0,0 +1,3 @@
// StdAfx.cpp
#include "StdAfx.h"

View File

@@ -0,0 +1,8 @@
// StdAfx.h
#ifndef __STDAFX_H
#define __STDAFX_H
#include "../../../Common/Common.h"
#endif

View File

@@ -0,0 +1,28 @@
PROG = 7zcl.exe
MY_CONSOLE = 1
CURRENT_OBJS = \
$O\Client7z.obj \
COMMON_OBJS = \
$O\IntToString.obj \
$O\NewHandler.obj \
$O\MyString.obj \
$O\MyVector.obj \
$O\StringConvert.obj \
$O\StringToInt.obj \
$O\Wildcard.obj \
WIN_OBJS = \
$O\DLL.obj \
$O\FileDir.obj \
$O\FileFind.obj \
$O\FileIO.obj \
$O\FileName.obj \
$O\PropVariant.obj \
$O\PropVariantConv.obj \
7ZIP_COMMON_OBJS = \
$O\FileStreams.obj \
!include "../../7zip.mak"

View File

@@ -0,0 +1,59 @@
PROG = 7zcl
IS_NOT_STANDALONE = 1
# IS_X64 = 1
ifdef SystemDrive
SYS_OBJS = \
$O/resource.o \
else
SYS_OBJS = \
$O/MyWindows.o \
$O/TimeUtils.o \
endif
LOCAL_FLAGS = \
CURRENT_OBJS = \
$O/Client7z.o \
COMMON_OBJS = \
$O/IntToString.o \
$O/MyString.o \
$O/MyVector.o \
$O/NewHandler.o \
$O/StringConvert.o \
$O/StringToInt.o \
$O/UTFConvert.o \
$O/Wildcard.o \
WIN_OBJS = \
$O/DLL.o \
$O/FileDir.o \
$O/FileFind.o \
$O/FileIO.o \
$O/FileName.o \
$O/PropVariant.o \
$O/PropVariantConv.o \
7ZIP_COMMON_OBJS = \
$O/FileStreams.o \
OBJS = \
$(COMMON_OBJS) \
$(WIN_OBJS) \
$(SYS_OBJS) \
$(7ZIP_COMMON_OBJS) \
$(CURRENT_OBJS) \
include ../../7zip_gcc.mak

View File

@@ -0,0 +1,3 @@
#include "../../MyVersionInfo.rc"
MY_VERSION_INFO_APP("7-Zip client" , "7zcl")

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,154 @@
// ArchiveCommandLine.h
#ifndef __ARCHIVE_COMMAND_LINE_H
#define __ARCHIVE_COMMAND_LINE_H
#include "../../../Common/CommandLineParser.h"
#include "../../../Common/Wildcard.h"
#include "EnumDirItems.h"
#include "Extract.h"
#include "HashCalc.h"
#include "Update.h"
typedef CMessagePathException CArcCmdLineException;
namespace NCommandType { enum EEnum
{
kAdd = 0,
kUpdate,
kDelete,
kTest,
kExtract,
kExtractFull,
kList,
kBenchmark,
kInfo,
kHash,
kRename
};}
struct CArcCommand
{
NCommandType::EEnum CommandType;
bool IsFromExtractGroup() const;
bool IsFromUpdateGroup() const;
bool IsTestCommand() const { return CommandType == NCommandType::kTest; }
NExtract::NPathMode::EEnum GetPathMode() const;
};
enum
{
k_OutStream_disabled = 0,
k_OutStream_stdout = 1,
k_OutStream_stderr = 2
};
struct CArcCmdLineOptions
{
bool HelpMode;
// bool LargePages;
bool CaseSensitiveChange;
bool CaseSensitive;
bool IsInTerminal;
bool IsStdOutTerminal;
bool IsStdErrTerminal;
bool StdInMode;
bool StdOutMode;
bool EnableHeaders;
bool YesToAll;
bool ShowDialog;
bool TechMode;
bool ShowTime;
int ConsoleCodePage;
NWildcard::CCensor Censor;
CArcCommand Command;
UString ArchiveName;
#ifndef _NO_CRYPTO
bool PasswordEnabled;
UString Password;
#endif
UStringVector HashMethods;
bool AppendName;
// UStringVector ArchivePathsSorted;
// UStringVector ArchivePathsFullSorted;
NWildcard::CCensor arcCensor;
UString ArcName_for_StdInMode;
CObjectVector<CProperty> Properties;
CExtractOptionsBase ExtractOptions;
CBoolPair NtSecurity;
CBoolPair AltStreams;
CBoolPair HardLinks;
CBoolPair SymLinks;
CUpdateOptions UpdateOptions;
CHashOptions HashOptions;
UString ArcType;
UStringVector ExcludedArcTypes;
unsigned Number_for_Out;
unsigned Number_for_Errors;
unsigned Number_for_Percents;
unsigned LogLevel;
// bool IsOutAllowed() const { return Number_for_Out != k_OutStream_disabled; }
// Benchmark
UInt32 NumIterations;
bool NumIterations_Defined;
CArcCmdLineOptions():
HelpMode(false),
// LargePages(false),
CaseSensitiveChange(false),
CaseSensitive(false),
IsInTerminal(false),
IsStdOutTerminal(false),
IsStdErrTerminal(false),
StdInMode(false),
StdOutMode(false),
EnableHeaders(false),
YesToAll(false),
ShowDialog(false),
TechMode(false),
ShowTime(false),
ConsoleCodePage(-1),
Number_for_Out(k_OutStream_stdout),
Number_for_Errors(k_OutStream_stderr),
Number_for_Percents(k_OutStream_stdout),
LogLevel(0)
{
};
};
class CArcCmdLineParser
{
NCommandLineParser::CParser parser;
public:
UString Parse1Log;
void Parse1(const UStringVector &commandStrings, CArcCmdLineOptions &options);
void Parse2(CArcCmdLineOptions &options);
};
#endif

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,500 @@
// ArchiveExtractCallback.h
#ifndef __ARCHIVE_EXTRACT_CALLBACK_H
#define __ARCHIVE_EXTRACT_CALLBACK_H
#include "../../../Common/MyCom.h"
#include "../../../Common/MyLinux.h"
#include "../../../Common/Wildcard.h"
#include "../../IPassword.h"
#include "../../Common/FileStreams.h"
#include "../../Common/ProgressUtils.h"
#include "../../Common/StreamObjects.h"
#include "../../Archive/IArchive.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 SymLinks_AllowDangerous;
CBoolPair HardLinks;
CBoolPair AltStreams;
bool ReplaceColonForAltStream;
bool WriteToAltStreamIfColon;
bool PreAllocateOutFile;
CExtractNtOptions():
ReplaceColonForAltStream(false),
WriteToAltStreamIfColon(false)
{
SymLinks.Val = true;
SymLinks_AllowDangerous.Val = false;
HardLinks.Val = true;
AltStreams.Val = true;
PreAllocateOutFile =
#ifdef _WIN32
true;
#else
false;
#endif
}
};
#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
#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
#ifdef SUPPORT_ALT_STREAMS
struct CIndexToPathPair
{
UInt32 Index;
FString Path;
CIndexToPathPair(UInt32 index): Index(index) {}
CIndexToPathPair(UInt32 index, const FString &path): Index(index), Path(path) {}
int Compare(const CIndexToPathPair &pair) const
{
return MyCompare(Index, pair.Index);
}
};
#endif
struct CDirPathTime
{
FILETIME CTime;
FILETIME ATime;
FILETIME MTime;
bool CTimeDefined;
bool ATimeDefined;
bool MTimeDefined;
FString Path;
bool SetDirTime() const;
};
#ifdef SUPPORT_LINKS
struct CLinkInfo
{
// bool isCopyLink;
bool isHardLink;
bool isJunction;
bool isRelative;
bool isWSL;
UString linkPath;
void Clear()
{
// IsCopyLink = false;
isHardLink = false;
isJunction = false;
isRelative = false;
isWSL = false;
linkPath.Empty();
}
bool Parse(const Byte *data, size_t dataSize, bool isLinuxData);
};
#endif // SUPPORT_LINKS
class CArchiveExtractCallback:
public IArchiveExtractCallback,
public IArchiveExtractCallbackMessage,
public ICryptoGetTextPassword,
public ICompressProgressInfo,
public CMyUnknownImp
{
const CArc *_arc;
CExtractNtOptions _ntOptions;
const NWildcard::CCensorNode *_wildcardCensor; // we need wildcard for single pass mode (stdin)
CMyComPtr<IFolderArchiveExtractCallback> _extractCallback2;
CMyComPtr<ICompressProgressInfo> _compressProgress;
CMyComPtr<ICryptoGetTextPassword> _cryptoGetTextPassword;
CMyComPtr<IArchiveExtractCallbackMessage> _callbackMessage;
CMyComPtr<IFolderArchiveExtractCallback2> _folderArchiveExtractCallback2;
FString _dirPathPrefix;
FString _dirPathPrefix_Full;
NExtract::NPathMode::EEnum _pathMode;
NExtract::NOverwriteMode::EEnum _overwriteMode;
bool _keepAndReplaceEmptyDirPrefixes; // replace them to "_";
#ifndef _SFX
CMyComPtr<IFolderExtractToStreamCallback> ExtractToStreamCallback;
CGetProp *GetProp_Spec;
CMyComPtr<IGetProp> GetProp;
#endif
CReadArcItem _item;
FString _diskFilePath;
UInt64 _position;
bool _isSplit;
bool _extractMode;
bool WriteCTime;
bool WriteATime;
bool WriteMTime;
bool _encrypted;
struct CProcessedFileInfo
{
FILETIME CTime;
FILETIME ATime;
FILETIME MTime;
UInt32 Attrib;
bool CTimeDefined;
bool ATimeDefined;
bool MTimeDefined;
bool AttribDefined;
bool IsReparse() const
{
return (AttribDefined && (Attrib & FILE_ATTRIBUTE_REPARSE_POINT) != 0);
}
bool IsLinuxSymLink() const
{
return (AttribDefined && MY_LIN_S_ISLNK(Attrib >> 16));
}
void SetFromPosixAttrib(UInt32 a)
{
// here we set only part of combined attribute required by SetFileAttrib() call
#ifdef _WIN32
// Windows sets FILE_ATTRIBUTE_NORMAL, if we try to set 0 as attribute.
Attrib = MY_LIN_S_ISDIR(a) ?
FILE_ATTRIBUTE_DIRECTORY :
FILE_ATTRIBUTE_ARCHIVE;
if ((a & 0222) == 0) // (& S_IWUSR) in p7zip
Attrib |= FILE_ATTRIBUTE_READONLY;
#else
Attrib = (a << 16) | FILE_ATTRIBUTE_UNIX_EXTENSION;
#endif
AttribDefined = true;
}
} _fi;
bool _is_SymLink_in_Data;
bool _is_SymLink_in_Data_Linux; // false = WIN32, true = LINUX
bool _fileWasExtracted;
UInt32 _index;
UInt64 _curSize;
bool _curSizeDefined;
bool _fileLengthWasSet;
UInt64 _fileLength_that_WasSet;
COutFileStream *_outFileStreamSpec;
CMyComPtr<ISequentialOutStream> _outFileStream;
CByteBuffer _outMemBuf;
CBufPtrSeqOutStream *_bufPtrSeqOutStream_Spec;
CMyComPtr<ISequentialOutStream> _bufPtrSeqOutStream;
#ifndef _SFX
COutStreamWithHash *_hashStreamSpec;
CMyComPtr<ISequentialOutStream> _hashStream;
bool _hashStreamWasUsed;
#endif
bool _removePartsForAltStreams;
UStringVector _removePathParts;
#ifndef _SFX
bool _use_baseParentFolder_mode;
UInt32 _baseParentFolder;
#endif
bool _stdOutMode;
bool _testMode;
bool _multiArchives;
CMyComPtr<ICompressProgressInfo> _localProgress;
UInt64 _packTotal;
UInt64 _progressTotal;
bool _progressTotal_Defined;
CObjectVector<CDirPathTime> _extractedFolders;
#ifndef _WIN32
// CObjectVector<NWindows::NFile::NDir::CDelayedSymLink> _delayedSymLinks;
#endif
#if defined(_WIN32) && !defined(UNDER_CE) && !defined(_SFX)
bool _saclEnabled;
#endif
void CreateComplexDirectory(const UStringVector &dirPathParts, FString &fullPath);
HRESULT GetTime(UInt32 index, PROPID propID, FILETIME &filetime, bool &filetimeIsDefined);
HRESULT GetUnpackSize();
HRESULT SendMessageError(const char *message, const FString &path);
HRESULT SendMessageError_with_LastError(const char *message, const FString &path);
HRESULT SendMessageError2(HRESULT errorCode, const char *message, const FString &path1, const FString &path2);
public:
CLocalProgress *LocalProgressSpec;
UInt64 NumFolders;
UInt64 NumFiles;
UInt64 NumAltStreams;
UInt64 UnpackSize;
UInt64 AltStreams_UnpackSize;
MY_UNKNOWN_IMP3(IArchiveExtractCallbackMessage, ICryptoGetTextPassword, ICompressProgressInfo)
INTERFACE_IArchiveExtractCallback(;)
INTERFACE_IArchiveExtractCallbackMessage(;)
STDMETHOD(SetRatioInfo)(const UInt64 *inSize, const UInt64 *outSize);
STDMETHOD(CryptoGetTextPassword)(BSTR *password);
CArchiveExtractCallback();
void InitForMulti(bool multiArchives,
NExtract::NPathMode::EEnum pathMode,
NExtract::NOverwriteMode::EEnum overwriteMode,
bool keepAndReplaceEmptyDirPrefixes)
{
_multiArchives = multiArchives;
_pathMode = pathMode;
_overwriteMode = overwriteMode;
_keepAndReplaceEmptyDirPrefixes = keepAndReplaceEmptyDirPrefixes;
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,
const FString &directoryPath,
const UStringVector &removePathParts, bool removePartsForAltStreams,
UInt64 packSize);
#ifdef SUPPORT_LINKS
private:
CHardLinks _hardLinks;
CLinkInfo _link;
// FString _CopyFile_Path;
// HRESULT MyCopyFile(ISequentialOutStream *outStream);
HRESULT Link(const FString &fullProcessedPath);
HRESULT ReadLink();
public:
// call PrepareHardLinks() after Init()
HRESULT PrepareHardLinks(const CRecordVector<UInt32> *realIndices); // NULL means all items
#endif
#ifdef SUPPORT_ALT_STREAMS
CObjectVector<CIndexToPathPair> _renamedFiles;
#endif
// call it after Init()
#ifndef _SFX
void SetBaseParentFolderIndex(UInt32 indexInArc)
{
_baseParentFolder = indexInArc;
_use_baseParentFolder_mode = true;
}
#endif
HRESULT CloseArc();
private:
void ClearExtractedDirsInfo()
{
_extractedFolders.Clear();
#ifndef _WIN32
// _delayedSymLinks.Clear();
#endif
}
HRESULT Read_fi_Props();
void CorrectPathParts();
void CreateFolders();
bool _isRenamed;
HRESULT CheckExistFile(FString &fullProcessedPath, bool &needExit);
HRESULT GetExtractStream(CMyComPtr<ISequentialOutStream> &outStreamLoc, bool &needExit);
HRESULT CloseFile();
HRESULT CloseReparseAndFile();
HRESULT CloseReparseAndFile2();
HRESULT SetDirsTimes();
const void *NtReparse_Data;
UInt32 NtReparse_Size;
#ifdef SUPPORT_LINKS
HRESULT SetFromLinkPath(
const FString &fullProcessedPath,
const CLinkInfo &linkInfo,
bool &linkWasSet);
#endif
};
struct CArchiveExtractCallback_Closer
{
CArchiveExtractCallback *_ref;
CArchiveExtractCallback_Closer(CArchiveExtractCallback *ref): _ref(ref) {}
HRESULT Close()
{
HRESULT res = S_OK;
if (_ref)
{
res = _ref->CloseArc();
_ref = NULL;
}
return res;
}
~CArchiveExtractCallback_Closer()
{
Close();
}
};
bool CensorNode_CheckPath(const NWildcard::CCensorNode &node, const CReadArcItem &item);
#endif

View File

@@ -0,0 +1,155 @@
// ArchiveName.cpp
#include "StdAfx.h"
#include "../../../Common/Wildcard.h"
#include "../../../Windows/FileDir.h"
#include "../../../Windows/FileName.h"
#include "ExtractingFilePath.h"
#include "ArchiveName.h"
using namespace NWindows;
using namespace NFile;
static UString CreateArchiveName(const NFind::CFileInfo &fi, bool keepName)
{
FString resultName = fi.Name;
if (!fi.IsDir() && !keepName)
{
int dotPos = resultName.ReverseFind_Dot();
if (dotPos > 0)
{
FString archiveName2 = resultName.Left((unsigned)dotPos);
if (archiveName2.ReverseFind_Dot() < 0)
resultName = archiveName2;
}
}
return Get_Correct_FsFile_Name(fs2us(resultName));
}
static FString CreateArchiveName2(const FString &path, bool fromPrev, bool keepName)
{
FString resultName ("Archive");
if (fromPrev)
{
FString dirPrefix;
if (NDir::GetOnlyDirPrefix(path, dirPrefix))
{
if (!dirPrefix.IsEmpty() && IsPathSepar(dirPrefix.Back()))
{
#if defined(_WIN32) && !defined(UNDER_CE)
if (NName::IsDriveRootPath_SuperAllowed(dirPrefix))
resultName = dirPrefix[dirPrefix.Len() - 3]; // only letter
else
#endif
{
dirPrefix.DeleteBack();
NFind::CFileInfo fi;
if (fi.Find(dirPrefix))
resultName = fi.Name;
}
}
}
}
else
{
NFind::CFileInfo fi;
if (fi.Find(path))
{
resultName = fi.Name;
if (!fi.IsDir() && !keepName)
{
int dotPos = resultName.ReverseFind_Dot();
if (dotPos > 0)
{
FString name2 = resultName.Left((unsigned)dotPos);
if (name2.ReverseFind_Dot() < 0)
resultName = name2;
}
}
}
}
return resultName;
}
UString CreateArchiveName(const UStringVector &paths, const NFind::CFileInfo *fi)
{
bool keepName = false;
/*
if (paths.Size() == 1)
{
const UString &name = paths[0];
if (name.Len() > 4)
if (CompareFileNames(name.RightPtr(4), L".tar") == 0)
keepName = true;
}
*/
UString name;
if (fi)
name = CreateArchiveName(*fi, keepName);
else
{
if (paths.IsEmpty())
return L"archive";
bool fromPrev = (paths.Size() > 1);
name = Get_Correct_FsFile_Name(fs2us(CreateArchiveName2(us2fs(paths.Front()), fromPrev, keepName)));
}
UStringVector names;
{
FOR_VECTOR (i, paths)
{
NFind::CFileInfo fi2;
const NFind::CFileInfo *fp;
if (fi && paths.Size() == 1)
fp = fi;
else
{
if (!fi2.Find(us2fs(paths[i])))
continue;
fp = &fi2;
}
names.Add(fs2us(fp->Name));
}
}
UString postfix;
UInt32 index = 1;
for (;;)
{
// we don't want cases when we include archive to itself.
// so we find first available name for archive
const UString name2 = name + postfix;
const UString name2_zip = name2 + L".zip";
const UString name2_7z = name2 + L".7z";
const UString name2_tar = name2 + L".tar";
const UString name2_wim = name2 + L".wim";
unsigned i = 0;
for (i = 0; i < names.Size(); i++)
{
const UString &fname = names[i];
if ( 0 == CompareFileNames(fname, name2_zip)
|| 0 == CompareFileNames(fname, name2_7z)
|| 0 == CompareFileNames(fname, name2_tar)
|| 0 == CompareFileNames(fname, name2_wim))
break;
}
if (i == names.Size())
break;
index++;
postfix = "_";
postfix.Add_UInt32(index);
}
name += postfix;
return name;
}

View File

@@ -0,0 +1,10 @@
// ArchiveName.h
#ifndef __ARCHIVE_NAME_H
#define __ARCHIVE_NAME_H
#include "../../../Windows/FileFind.h"
UString CreateArchiveName(const UStringVector &paths, const NWindows::NFile::NFind::CFileInfo *fi = NULL);
#endif

View File

@@ -0,0 +1,158 @@
// ArchiveOpenCallback.cpp
#include "StdAfx.h"
#include "../../../Common/ComTry.h"
#include "../../../Windows/FileName.h"
#include "../../../Windows/PropVariant.h"
#include "../../Common/FileStreams.h"
#include "ArchiveOpenCallback.h"
using namespace NWindows;
STDMETHODIMP COpenCallbackImp::SetTotal(const UInt64 *files, const UInt64 *bytes)
{
COM_TRY_BEGIN
if (ReOpenCallback)
return ReOpenCallback->SetTotal(files, bytes);
if (!Callback)
return S_OK;
return Callback->Open_SetTotal(files, bytes);
COM_TRY_END
}
STDMETHODIMP COpenCallbackImp::SetCompleted(const UInt64 *files, const UInt64 *bytes)
{
COM_TRY_BEGIN
if (ReOpenCallback)
return ReOpenCallback->SetCompleted(files, bytes);
if (!Callback)
return S_OK;
return Callback->Open_SetCompleted(files, bytes);
COM_TRY_END
}
STDMETHODIMP COpenCallbackImp::GetProperty(PROPID propID, PROPVARIANT *value)
{
COM_TRY_BEGIN
NCOM::CPropVariant prop;
if (_subArchiveMode)
switch (propID)
{
case kpidName: prop = _subArchiveName; break;
// case kpidSize: prop = _subArchiveSize; break; // we don't use it now
}
else
switch (propID)
{
case kpidName: prop = _fileInfo.Name; break;
case kpidIsDir: prop = _fileInfo.IsDir(); break;
case kpidSize: prop = _fileInfo.Size; break;
case kpidAttrib: prop = (UInt32)_fileInfo.Attrib; break;
case kpidCTime: prop = _fileInfo.CTime; break;
case kpidATime: prop = _fileInfo.ATime; break;
case kpidMTime: prop = _fileInfo.MTime; break;
}
prop.Detach(value);
return S_OK;
COM_TRY_END
}
struct CInFileStreamVol: public CInFileStream
{
unsigned FileNameIndex;
COpenCallbackImp *OpenCallbackImp;
CMyComPtr<IArchiveOpenCallback> OpenCallbackRef;
~CInFileStreamVol()
{
if (OpenCallbackRef)
OpenCallbackImp->FileNames_WasUsed[FileNameIndex] = false;
}
};
// from ArchiveExtractCallback.cpp
bool IsSafePath(const UString &path);
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());
}
UString name2 = name;
#ifndef _SFX
#ifdef _WIN32
name2.Replace(L'/', WCHAR_PATH_SEPARATOR);
#endif
// if (!allowAbsVolPaths)
if (!IsSafePath(name2))
return S_FALSE;
// #ifdef _WIN32
// we don't want to support wildcards in names here here
if (name2.Find(L'?') >= 0 ||
name2.Find(L'*') >= 0)
return S_FALSE;
// #endif
#endif
FString fullPath;
if (!NFile::NName::GetFullPath(_folderPrefix, us2fs(name2), fullPath))
return S_FALSE;
if (!_fileInfo.Find_FollowLink(fullPath))
return S_FALSE;
if (_fileInfo.IsDir())
return S_FALSE;
CInFileStreamVol *inFile = new CInFileStreamVol;
CMyComPtr<IInStream> inStreamTemp = inFile;
if (!inFile->Open(fullPath))
{
return GetLastError_noZero_HRESULT();
}
FileSizes.Add(_fileInfo.Size);
FileNames.Add(name2);
inFile->FileNameIndex = FileNames_WasUsed.Add(true);
inFile->OpenCallbackImp = this;
inFile->OpenCallbackRef = this;
// TotalSize += _fileInfo.Size;
*inStream = inStreamTemp.Detach();
return S_OK;
COM_TRY_END
}
#ifndef _NO_CRYPTO
STDMETHODIMP COpenCallbackImp::CryptoGetTextPassword(BSTR *password)
{
COM_TRY_BEGIN
if (ReOpenCallback)
{
CMyComPtr<ICryptoGetTextPassword> getTextPassword;
ReOpenCallback.QueryInterface(IID_ICryptoGetTextPassword, &getTextPassword);
if (getTextPassword)
return getTextPassword->CryptoGetTextPassword(password);
}
if (!Callback)
return E_NOTIMPL;
PasswordWasAsked = true;
return Callback->Open_CryptoGetTextPassword(password);
COM_TRY_END
}
#endif

View File

@@ -0,0 +1,117 @@
// ArchiveOpenCallback.h
#ifndef __ARCHIVE_OPEN_CALLBACK_H
#define __ARCHIVE_OPEN_CALLBACK_H
#include "../../../Common/MyCom.h"
#include "../../../Windows/FileFind.h"
#include "../../../Windows/FileIO.h"
#ifndef _NO_CRYPTO
#include "../../IPassword.h"
#endif
#include "../../Archive/IArchive.h"
#ifdef _NO_CRYPTO
#define INTERFACE_IOpenCallbackUI_Crypto(x)
#else
#define INTERFACE_IOpenCallbackUI_Crypto(x) \
virtual HRESULT Open_CryptoGetTextPassword(BSTR *password) x; \
/* virtual HRESULT Open_GetPasswordIfAny(bool &passwordIsDefined, UString &password) x; */ \
/* virtual bool Open_WasPasswordAsked() x; */ \
/* virtual void Open_Clear_PasswordWasAsked_Flag() x; */ \
#endif
#define INTERFACE_IOpenCallbackUI(x) \
virtual HRESULT Open_CheckBreak() x; \
virtual HRESULT Open_SetTotal(const UInt64 *files, const UInt64 *bytes) x; \
virtual HRESULT Open_SetCompleted(const UInt64 *files, const UInt64 *bytes) x; \
virtual HRESULT Open_Finished() x; \
INTERFACE_IOpenCallbackUI_Crypto(x)
struct IOpenCallbackUI
{
INTERFACE_IOpenCallbackUI(=0)
};
class COpenCallbackImp:
public IArchiveOpenCallback,
public IArchiveOpenVolumeCallback,
public IArchiveOpenSetSubArchiveName,
#ifndef _NO_CRYPTO
public ICryptoGetTextPassword,
#endif
public CMyUnknownImp
{
public:
MY_QUERYINTERFACE_BEGIN2(IArchiveOpenVolumeCallback)
MY_QUERYINTERFACE_ENTRY(IArchiveOpenSetSubArchiveName)
#ifndef _NO_CRYPTO
MY_QUERYINTERFACE_ENTRY(ICryptoGetTextPassword)
#endif
MY_QUERYINTERFACE_END
MY_ADDREF_RELEASE
INTERFACE_IArchiveOpenCallback(;)
INTERFACE_IArchiveOpenVolumeCallback(;)
#ifndef _NO_CRYPTO
STDMETHOD(CryptoGetTextPassword)(BSTR *password);
#endif
STDMETHOD(SetSubArchiveName(const wchar_t *name))
{
_subArchiveMode = true;
_subArchiveName = name;
// TotalSize = 0;
return S_OK;
}
private:
FString _folderPrefix;
NWindows::NFile::NFind::CFileInfo _fileInfo;
bool _subArchiveMode;
UString _subArchiveName;
public:
UStringVector FileNames;
CBoolVector FileNames_WasUsed;
CRecordVector<UInt64> FileSizes;
bool PasswordWasAsked;
IOpenCallbackUI *Callback;
CMyComPtr<IArchiveOpenCallback> ReOpenCallback;
// UInt64 TotalSize;
COpenCallbackImp(): _subArchiveMode(false), Callback(NULL) {}
HRESULT Init2(const FString &folderPrefix, const FString &fileName)
{
FileNames.Clear();
FileNames_WasUsed.Clear();
FileSizes.Clear();
_subArchiveMode = false;
// TotalSize = 0;
PasswordWasAsked = false;
_folderPrefix = folderPrefix;
if (!_fileInfo.Find_FollowLink(_folderPrefix + fileName))
{
// throw 20121118;
return GetLastError_noZero_HRESULT();
}
return S_OK;
}
bool SetSecondFileInfo(CFSTR newName)
{
return _fileInfo.Find_FollowLink(newName) && !_fileInfo.IsDir();
}
};
#endif

4535
3rdparty/lzma/CPP/7zip/UI/Common/Bench.cpp vendored Normal file

File diff suppressed because it is too large Load Diff

122
3rdparty/lzma/CPP/7zip/UI/Common/Bench.h vendored Normal file
View File

@@ -0,0 +1,122 @@
// Bench.h
#ifndef __7ZIP_BENCH_H
#define __7ZIP_BENCH_H
#include "../../../Windows/System.h"
#include "../../Common/CreateCoder.h"
#include "../../UI/Common/Property.h"
UInt64 Benchmark_GetUsage_Percents(UInt64 usage);
struct CBenchInfo
{
UInt64 GlobalTime;
UInt64 GlobalFreq;
UInt64 UserTime;
UInt64 UserFreq;
UInt64 UnpackSize;
UInt64 PackSize;
UInt64 NumIterations;
/*
during Code(): we track benchInfo only from one thread (theads with index[0])
NumIterations means number of threads
UnpackSize and PackSize are total sizes of all iterations of current thread
after Code():
NumIterations means the number of Iterations
UnpackSize and PackSize are total sizes of all threads
*/
CBenchInfo(): NumIterations(0) {}
UInt64 GetUsage() const;
UInt64 GetRatingPerUsage(UInt64 rating) const;
UInt64 GetSpeed(UInt64 numUnits) const;
UInt64 GetUnpackSizeSpeed() const { return GetSpeed(UnpackSize * NumIterations); }
UInt64 Get_UnpackSize_Full() const { return UnpackSize * NumIterations; }
UInt64 GetRating_LzmaEnc(UInt64 dictSize) const;
UInt64 GetRating_LzmaDec() const;
};
struct CTotalBenchRes
{
// UInt64 NumIterations1; // for Usage
UInt64 NumIterations2; // for Rating / RPU
UInt64 Rating;
UInt64 Usage;
UInt64 RPU;
UInt64 Speed;
void Init() { /* NumIterations1 = 0; */ NumIterations2 = 0; Rating = 0; Usage = 0; RPU = 0; Speed = 0; }
void SetSum(const CTotalBenchRes &r1, const CTotalBenchRes &r2)
{
Rating = (r1.Rating + r2.Rating);
Usage = (r1.Usage + r2.Usage);
RPU = (r1.RPU + r2.RPU);
Speed = (r1.Speed + r2.Speed);
// NumIterations1 = (r1.NumIterations1 + r2.NumIterations1);
NumIterations2 = (r1.NumIterations2 + r2.NumIterations2);
}
void Generate_From_BenchInfo(const CBenchInfo &info);
void Mult_For_Weight(unsigned weight);
void Update_With_Res(const CTotalBenchRes &r);
};
struct IBenchCallback
{
// virtual HRESULT SetFreq(bool showFreq, UInt64 cpuFreq) = 0;
virtual HRESULT SetEncodeResult(const CBenchInfo &info, bool final) = 0;
virtual HRESULT SetDecodeResult(const CBenchInfo &info, bool final) = 0;
};
const unsigned kBenchMinDicLogSize = 18;
UInt64 GetBenchMemoryUsage(UInt32 numThreads, int level, UInt64 dictionary, bool totalBench);
struct IBenchPrintCallback
{
virtual void Print(const char *s) = 0;
virtual void NewLine() = 0;
virtual HRESULT CheckBreak() = 0;
};
struct IBenchFreqCallback
{
virtual HRESULT AddCpuFreq(unsigned numThreads, UInt64 freq, UInt64 usage) = 0;
virtual HRESULT FreqsFinished(unsigned numThreads) = 0;
};
HRESULT Bench(
DECL_EXTERNAL_CODECS_LOC_VARS
IBenchPrintCallback *printCallback,
IBenchCallback *benchCallback,
const CObjectVector<CProperty> &props,
UInt32 numIterations,
bool multiDict,
IBenchFreqCallback *freqCallback = NULL);
AString GetProcessThreadsInfo(const NWindows::NSystem::CProcessAffinity &ti);
void GetSysInfo(AString &s1, AString &s2);
void GetCpuName(AString &s);
void AddCpuFeatures(AString &s);
#ifdef _7ZIP_LARGE_PAGES
void Add_LargePages_String(AString &s);
#else
// #define Add_LargePages_String
#endif
#endif

View File

@@ -0,0 +1,37 @@
// DefaultName.cpp
#include "StdAfx.h"
#include "DefaultName.h"
static UString GetDefaultName3(const UString &fileName,
const UString &extension, const UString &addSubExtension)
{
const unsigned extLen = extension.Len();
const unsigned fileNameLen = fileName.Len();
if (fileNameLen > extLen + 1)
{
const unsigned dotPos = fileNameLen - (extLen + 1);
if (fileName[dotPos] == '.')
if (extension.IsEqualTo_NoCase(fileName.Ptr(dotPos + 1)))
return fileName.Left(dotPos) + addSubExtension;
}
int dotPos = fileName.ReverseFind_Dot();
if (dotPos > 0)
return fileName.Left((unsigned)dotPos) + addSubExtension;
if (addSubExtension.IsEmpty())
return fileName + L'~';
else
return fileName + addSubExtension;
}
UString GetDefaultName2(const UString &fileName,
const UString &extension, const UString &addSubExtension)
{
UString name = GetDefaultName3(fileName, extension, addSubExtension);
name.TrimRight();
return name;
}

View File

@@ -0,0 +1,11 @@
// DefaultName.h
#ifndef __DEFAULT_NAME_H
#define __DEFAULT_NAME_H
#include "../../../Common/MyString.h"
UString GetDefaultName2(const UString &fileName,
const UString &extension, const UString &addSubExtension);
#endif

View File

@@ -0,0 +1,212 @@
// DirItem.h
#ifndef __DIR_ITEM_H
#define __DIR_ITEM_H
#ifdef _WIN32
#include "../../../Common/MyLinux.h"
#endif
#include "../../../Common/MyString.h"
#include "../../../Windows/FileFind.h"
#include "../../Common/UniqBlocks.h"
#include "../../Archive/IArchive.h"
struct CDirItemsStat
{
UInt64 NumDirs;
UInt64 NumFiles;
UInt64 NumAltStreams;
UInt64 FilesSize;
UInt64 AltStreamsSize;
UInt64 NumErrors;
// UInt64 Get_NumItems() const { return NumDirs + NumFiles + NumAltStreams; }
UInt64 Get_NumDataItems() const { return NumFiles + NumAltStreams; }
UInt64 GetTotalBytes() const { return FilesSize + AltStreamsSize; }
bool IsEmpty() const { return
0 == NumDirs
&& 0 == NumFiles
&& 0 == NumAltStreams
&& 0 == FilesSize
&& 0 == AltStreamsSize
&& 0 == NumErrors; }
CDirItemsStat():
NumDirs(0),
NumFiles(0),
NumAltStreams(0),
FilesSize(0),
AltStreamsSize(0),
NumErrors(0)
{}
};
struct CDirItemsStat2: public CDirItemsStat
{
UInt64 Anti_NumDirs;
UInt64 Anti_NumFiles;
UInt64 Anti_NumAltStreams;
// UInt64 Get_NumItems() const { return Anti_NumDirs + Anti_NumFiles + Anti_NumAltStreams + CDirItemsStat::Get_NumItems(); }
UInt64 Get_NumDataItems2() const { return Anti_NumFiles + Anti_NumAltStreams + CDirItemsStat::Get_NumDataItems(); }
bool IsEmpty() const { return CDirItemsStat::IsEmpty()
&& 0 == Anti_NumDirs
&& 0 == Anti_NumFiles
&& 0 == Anti_NumAltStreams; }
CDirItemsStat2():
Anti_NumDirs(0),
Anti_NumFiles(0),
Anti_NumAltStreams(0)
{}
};
#define INTERFACE_IDirItemsCallback(x) \
virtual HRESULT ScanError(const FString &path, DWORD systemError) x; \
virtual HRESULT ScanProgress(const CDirItemsStat &st, const FString &path, bool isDir) x; \
struct IDirItemsCallback
{
INTERFACE_IDirItemsCallback(=0)
};
struct CDirItem
{
UInt64 Size;
FILETIME CTime;
FILETIME ATime;
FILETIME MTime;
UString Name;
#ifndef UNDER_CE
CByteBuffer ReparseData;
#ifdef _WIN32
// UString ShortName;
CByteBuffer ReparseData2; // fixed (reduced) absolute links for WIM format
bool AreReparseData() const { return ReparseData.Size() != 0 || ReparseData2.Size() != 0; }
#else
bool AreReparseData() const { return ReparseData.Size() != 0; }
#endif // _WIN32
#endif // !UNDER_CE
UInt32 Attrib;
int PhyParent;
int LogParent;
int SecureIndex;
bool IsAltStream;
CDirItem(): PhyParent(-1), LogParent(-1), SecureIndex(-1), IsAltStream(false) {}
bool IsDir() const { return (Attrib & FILE_ATTRIBUTE_DIRECTORY) != 0; }
bool IsReadOnly() const { return (Attrib & FILE_ATTRIBUTE_READONLY) != 0; }
bool Has_Attrib_ReparsePoint() const { return (Attrib & FILE_ATTRIBUTE_REPARSE_POINT) != 0; }
#ifdef _WIN32
UInt32 GetPosixAttrib() const
{
UInt32 v = IsDir() ? MY_LIN_S_IFDIR : MY_LIN_S_IFREG;
v |= (IsReadOnly() ? 0555 : 0777);
return v;
}
#endif
};
class CDirItems
{
UStringVector Prefixes;
CIntVector PhyParents;
CIntVector LogParents;
UString GetPrefixesPath(const CIntVector &parents, int index, const UString &name) const;
HRESULT EnumerateDir(int phyParent, int logParent, const FString &phyPrefix);
public:
CObjectVector<CDirItem> Items;
bool SymLinks;
bool ScanAltStreams;
CDirItemsStat Stat;
#if !defined(UNDER_CE)
HRESULT SetLinkInfo(CDirItem &dirItem, const NWindows::NFile::NFind::CFileInfo &fi,
const FString &phyPrefix);
#endif
#if defined(_WIN32) && !defined(UNDER_CE)
CUniqBlocks SecureBlocks;
CByteBuffer TempSecureBuf;
bool _saclEnabled;
bool ReadSecure;
HRESULT AddSecurityItem(const FString &path, int &secureIndex);
HRESULT FillFixedReparse();
#endif
IDirItemsCallback *Callback;
CDirItems();
void AddDirFileInfo(int phyParent, int logParent, int secureIndex,
const NWindows::NFile::NFind::CFileInfo &fi);
HRESULT AddError(const FString &path, DWORD errorCode);
HRESULT AddError(const FString &path);
HRESULT ScanProgress(const FString &path);
// unsigned GetNumFolders() const { return Prefixes.Size(); }
FString GetPhyPath(unsigned index) const;
UString GetLogPath(unsigned index) const;
unsigned AddPrefix(int phyParent, int logParent, const UString &prefix);
void DeleteLastPrefix();
// HRESULT EnumerateOneDir(const FString &phyPrefix, CObjectVector<NWindows::NFile::NFind::CDirEntry> &files);
HRESULT EnumerateOneDir(const FString &phyPrefix, CObjectVector<NWindows::NFile::NFind::CFileInfo> &files);
HRESULT EnumerateItems2(
const FString &phyPrefix,
const UString &logPrefix,
const FStringVector &filePaths,
FStringVector *requestedPaths);
void ReserveDown();
};
struct CArcItem
{
UInt64 Size;
FILETIME MTime;
UString Name;
bool IsDir;
bool IsAltStream;
bool SizeDefined;
bool MTimeDefined;
bool Censored;
UInt32 IndexInServer;
int TimeType;
CArcItem(): IsDir(false), IsAltStream(false), SizeDefined(false), MTimeDefined(false), Censored(false), TimeType(-1) {}
};
#endif

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,38 @@
// EnumDirItems.h
#ifndef __ENUM_DIR_ITEMS_H
#define __ENUM_DIR_ITEMS_H
#include "../../../Common/Wildcard.h"
#include "DirItem.h"
HRESULT EnumerateItems(
const NWildcard::CCensor &censor,
NWildcard::ECensorPathMode pathMode,
const UString &addPathPrefix,
CDirItems &dirItems);
struct CMessagePathException: public UString
{
CMessagePathException(const char *a, const wchar_t *u = NULL);
CMessagePathException(const wchar_t *a, const wchar_t *u = NULL);
};
HRESULT EnumerateDirItemsAndSort(
NWildcard::CCensor &censor,
NWildcard::ECensorPathMode pathMode,
const UString &addPathPrefix,
UStringVector &sortedPaths,
UStringVector &sortedFullPaths,
CDirItemsStat &st,
IDirItemsCallback *callback);
#ifdef _WIN32
void ConvertToLongNames(NWildcard::CCensor &censor);
#endif
#endif

View File

@@ -0,0 +1,27 @@
// 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

View File

@@ -0,0 +1,503 @@
// Extract.cpp
#include "StdAfx.h"
#include "../../../../C/Sort.h"
#include "../../../Common/StringConvert.h"
#include "../../../Windows/FileDir.h"
#include "../../../Windows/ErrorMsg.h"
#include "../../../Windows/PropVariant.h"
#include "../../../Windows/PropVariantConv.h"
#include "../Common/ExtractingFilePath.h"
#include "Extract.h"
#include "SetProperties.h"
using namespace NWindows;
using namespace NFile;
using namespace NDir;
static void SetErrorMessage(const char *message,
const FString &path, HRESULT errorCode,
UString &s)
{
s = message;
s += " : ";
s += NError::MyFormatMessage(errorCode);
s += " : ";
s += fs2us(path);
}
static HRESULT DecompressArchive(
CCodecs *codecs,
const CArchiveLink &arcLink,
UInt64 packSize,
const NWildcard::CCensorNode &wildcardCensor,
const CExtractOptions &options,
bool calcCrc,
IExtractCallbackUI *callback,
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 (arc0.FormatIndex >= 0 && StringsAreEqualNoCase_Ascii(codecs->Formats[(unsigned)arc0.FormatIndex].Name, "pe"))
replaceName = arc0.DefaultName;
}
outDir.Replace(FString("*"), us2fs(Get_Correct_FsFile_Name(replaceName)));
bool elimIsPossible = false;
UString elimPrefix; // only pure name without dir delimiter
FString outDirReduced = outDir;
if (options.ElimDup.Val && options.PathMode != NExtract::NPathMode::kAbsPaths)
{
UString dirPrefix;
SplitPathToParts_Smart(fs2us(outDir), dirPrefix, elimPrefix);
if (!elimPrefix.IsEmpty())
{
if (IsPathSepar(elimPrefix.Back()))
elimPrefix.DeleteBack();
if (!elimPrefix.IsEmpty())
{
outDirReduced = us2fs(dirPrefix);
elimIsPossible = true;
}
}
}
bool allFilesAreAllowed = wildcardCensor.AreAllAllowed();
if (!options.StdInMode)
{
UInt32 numItems;
RINOK(archive->GetNumberOfItems(&numItems));
CReadArcItem item;
for (UInt32 i = 0; i < numItems; i++)
{
if (elimIsPossible || !allFilesAreAllowed)
{
RINOK(arc.GetItem(i, item));
}
else
{
#ifdef SUPPORT_ALT_STREAMS
item.IsAltStream = false;
if (!options.NtOptions.AltStreams.Val && arc.Ask_AltStream)
{
RINOK(Archive_IsItem_AltStream(arc.Archive, i, item.IsAltStream));
}
#endif
}
#ifdef SUPPORT_ALT_STREAMS
if (!options.NtOptions.AltStreams.Val && item.IsAltStream)
continue;
#endif
if (elimIsPossible)
{
const UString &s =
#ifdef SUPPORT_ALT_STREAMS
item.MainPath;
#else
item.Path;
#endif
if (!IsPath1PrefixedByPath2(s, elimPrefix))
elimIsPossible = false;
else
{
wchar_t c = s[elimPrefix.Len()];
if (c == 0)
{
if (!item.MainIsDir)
elimIsPossible = false;
}
else if (!IsPathSepar(c))
elimIsPossible = false;
}
}
if (!allFilesAreAllowed)
{
if (!CensorNode_CheckPath(wildcardCensor, item))
continue;
}
realIndices.Add(i);
}
if (realIndices.Size() == 0)
{
callback->ThereAreNoFiles();
return callback->ExtractResult(S_OK);
}
}
if (elimIsPossible)
{
removePathParts.Add(elimPrefix);
// outDir = outDirReduced;
}
#ifdef _WIN32
// GetCorrectFullFsPath doesn't like "..".
// outDir.TrimRight();
// outDir = GetCorrectFullFsPath(outDir);
#endif
if (outDir.IsEmpty())
outDir = "." STRING_PATH_SEPARATOR;
/*
#ifdef _WIN32
else if (NName::IsAltPathPrefix(outDir)) {}
#endif
*/
else if (!CreateComplexDir(outDir))
{
const HRESULT res = GetLastError_noZero_HRESULT();
SetErrorMessage("Cannot create output directory", outDir, res, errorMessage);
return res;
}
ecs->Init(
options.NtOptions,
options.StdInMode ? &wildcardCensor : NULL,
&arc,
callback,
options.StdOutMode, options.TestMode,
outDir,
removePathParts, false,
packSize);
#ifdef SUPPORT_LINKS
if (!options.StdInMode &&
!options.TestMode &&
options.NtOptions.HardLinks.Val)
{
RINOK(ecs->PrepareHardLinks(&realIndices));
}
#endif
HRESULT result;
Int32 testMode = (options.TestMode && !calcCrc) ? 1: 0;
CArchiveExtractCallback_Closer ecsCloser(ecs);
if (options.StdInMode)
{
result = archive->Extract(NULL, (UInt32)(Int32)-1, testMode, ecs);
NCOM::CPropVariant prop;
if (archive->GetArchiveProperty(kpidPhySize, &prop) == S_OK)
ConvertPropVariantToUInt64(prop, stdInProcessed);
}
else
result = archive->Extract(&realIndices.Front(), realIndices.Size(), testMode, ecs);
HRESULT res2 = ecsCloser.Close();
if (result == S_OK)
result = res2;
return callback->ExtractResult(result);
}
/* 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);
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 (int)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 &st)
{
st.Clear();
UInt64 totalPackSize = 0;
CRecordVector<UInt64> arcSizes;
unsigned numArcs = options.StdInMode ? 1 : arcPaths.Size();
unsigned i;
for (i = 0; i < numArcs; i++)
{
NFind::CFileInfo fi;
fi.Size = 0;
if (!options.StdInMode)
{
const FString arcPath = us2fs(arcPaths[i]);
if (!fi.Find_FollowLink(arcPath))
{
const HRESULT errorCode = GetLastError_noZero_HRESULT();
SetErrorMessage("Cannot find archive file", arcPath, errorCode, errorMessage);
return errorCode;
}
if (fi.IsDir())
{
HRESULT errorCode = E_FAIL;
SetErrorMessage("The item is a directory", arcPath, errorCode, errorMessage);
return errorCode;
}
}
arcSizes.Add(fi.Size);
totalPackSize += fi.Size;
}
CBoolArr skipArcs(numArcs);
for (i = 0; i < numArcs; i++)
skipArcs[i] = false;
CArchiveExtractCallback *ecs = new CArchiveExtractCallback;
CMyComPtr<IArchiveExtractCallback> ec(ecs);
bool multi = (numArcs > 1);
ecs->InitForMulti(multi, options.PathMode, options.OverwriteMode,
false // keepEmptyDirParts
);
#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];
NFind::CFileInfo fi;
if (options.StdInMode)
{
fi.Size = 0;
fi.Attrib = 0;
}
else
{
if (!fi.Find_FollowLink(us2fs(arcPath)) || fi.IsDir())
{
const HRESULT errorCode = GetLastError_noZero_HRESULT();
SetErrorMessage("Cannot find archive file", us2fs(arcPath), errorCode, errorMessage);
return errorCode;
}
}
/*
#ifndef _NO_CRYPTO
openCallback->Open_Clear_PasswordWasAsked_Flag();
#endif
*/
RINOK(extractCallback->BeforeOpen(arcPath, options.TestMode));
CArchiveLink arcLink;
CObjectVector<COpenType> types2 = types;
/*
#ifndef _SFX
if (types.IsEmpty())
{
int pos = arcPath.ReverseFind(L'.');
if (pos >= 0)
{
UString s = arcPath.Ptr(pos + 1);
int index = codecs->FindFormatForExtension(s);
if (index >= 0 && s == L"001")
{
s = arcPath.Left(pos);
pos = s.ReverseFind(L'.');
if (pos >= 0)
{
int index2 = codecs->FindFormatForExtension(s.Ptr(pos + 1));
if (index2 >= 0) // && s.CompareNoCase(L"rar") != 0
{
types2.Add(index2);
types2.Add(index);
}
}
}
}
}
#endif
*/
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.Open_Strict(op, openCallback);
if (result == E_ABORT)
return result;
// arcLink.Set_ErrorsText();
RINOK(extractCallback->OpenResult(codecs, arcLink, arcPath, result));
if (result != S_OK)
{
thereAreNotOpenArcs = true;
if (!options.StdInMode)
totalPackProcessed += fi.Size;
continue;
}
if (!options.StdInMode)
{
// numVolumes += arcLink.VolumePaths.Size();
// arcLink.VolumesSize;
// totalPackSize -= DeleteUsedFileNamesFromList(arcLink, i + 1, arcPaths, arcPathsFull, &arcSizes);
// numArcs = arcPaths.Size();
if (arcLink.VolumePaths.Size() != 0)
{
Int64 correctionSize = (Int64)arcLink.VolumesSize;
FOR_VECTOR (v, arcLink.VolumePaths)
{
int index = Find_FileName_InSortedVector(arcPathsFull, arcLink.VolumePaths[v]);
if (index >= 0)
{
if ((unsigned)index > i)
{
skipArcs[(unsigned)index] = true;
correctionSize -= arcSizes[(unsigned)index];
}
}
}
if (correctionSize != 0)
{
Int64 newPackSize = (Int64)totalPackSize + correctionSize;
if (newPackSize < 0)
newPackSize = 0;
totalPackSize = (UInt64)newPackSize;
RINOK(extractCallback->SetTotal(totalPackSize));
}
}
}
/*
// Now openCallback and extractCallback use same object. So we don't need to send password.
#ifndef _NO_CRYPTO
bool passwordIsDefined;
UString password;
RINOK(openCallback->Open_GetPasswordIfAny(passwordIsDefined, password));
if (passwordIsDefined)
{
RINOK(extractCallback->SetPassword(password));
}
#endif
*/
CArc &arc = arcLink.Arcs.Back();
arc.MTimeDefined = (!options.StdInMode && !fi.IsDevice);
arc.MTime = fi.MTime;
UInt64 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 + arcLink.VolumesSize;
totalPackProcessed += packProcessed;
ecs->LocalProgressSpec->InSize += packProcessed;
ecs->LocalProgressSpec->OutSize = ecs->UnpackSize;
if (!errorMessage.IsEmpty())
return E_FAIL;
}
if (multi || thereAreNotOpenArcs)
{
RINOK(extractCallback->SetTotal(totalPackSize));
RINOK(extractCallback->SetCompleted(&totalPackProcessed));
}
st.NumFolders = ecs->NumFolders;
st.NumFiles = ecs->NumFiles;
st.NumAltStreams = ecs->NumAltStreams;
st.UnpackSize = ecs->UnpackSize;
st.AltStreams_UnpackSize = ecs->AltStreams_UnpackSize;
st.NumArchives = arcPaths.Size();
st.PackSize = ecs->LocalProgressSpec->InSize;
return S_OK;
}

View File

@@ -0,0 +1,94 @@
// Extract.h
#ifndef __EXTRACT_H
#define __EXTRACT_H
#include "../../../Windows/FileFind.h"
#include "../../Archive/IArchive.h"
#include "ArchiveExtractCallback.h"
#include "ArchiveOpenCallback.h"
#include "ExtractMode.h"
#include "Property.h"
#include "../Common/LoadCodecs.h"
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 ShowDialog;
// bool PasswordEnabled;
// UString Password;
#ifndef _SFX
CObjectVector<CProperty> Properties;
#endif
#ifdef EXTERNAL_CODECS
CCodecs *Codecs;
#endif
CExtractOptions():
StdInMode(false),
StdOutMode(false),
YesToAll(false),
TestMode(false)
{}
};
struct CDecompressStat
{
UInt64 NumArchives;
UInt64 UnpackSize;
UInt64 AltStreams_UnpackSize;
UInt64 PackSize;
UInt64 NumFolders;
UInt64 NumFiles;
UInt64 NumAltStreams;
void Clear()
{
NumArchives = UnpackSize = AltStreams_UnpackSize = PackSize = NumFolders = NumFiles = NumAltStreams = 0;
}
};
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 &st);
#endif

View File

@@ -0,0 +1,34 @@
// ExtractMode.h
#ifndef __EXTRACT_MODE_H
#define __EXTRACT_MODE_H
namespace NExtract {
namespace NPathMode
{
enum EEnum
{
kFullPaths,
kCurPaths,
kNoPaths,
kAbsPaths,
kNoPathsAlt // alt streams must be extracted without name of base file
};
}
namespace NOverwriteMode
{
enum EEnum
{
kAsk,
kOverwrite,
kSkip,
kRename,
kRenameExisting
};
}
}
#endif

View File

@@ -0,0 +1,287 @@
// ExtractingFilePath.cpp
#include "StdAfx.h"
#include "../../../Common/Wildcard.h"
#include "../../../Windows/FileName.h"
#include "ExtractingFilePath.h"
extern
bool g_PathTrailReplaceMode;
bool g_PathTrailReplaceMode =
#ifdef _WIN32
true
#else
false
#endif
;
#ifdef _WIN32
static void ReplaceIncorrectChars(UString &s)
{
{
for (unsigned i = 0; i < s.Len(); i++)
{
wchar_t c = s[i];
if (
#ifdef _WIN32
c == ':' || c == '*' || c == '?' || c < 0x20 || c == '<' || c == '>' || c == '|' || c == '"'
|| c == '/'
// || c == 0x202E // RLO
||
#endif
c == WCHAR_PATH_SEPARATOR)
s.ReplaceOneCharAtPos(i,
'_' // default
// (wchar_t)(0xf000 + c) // 21.02 debug: WSL encoding for unsupported characters
);
}
}
if (g_PathTrailReplaceMode)
{
/*
// if (g_PathTrailReplaceMode == 1)
{
if (!s.IsEmpty())
{
wchar_t c = s.Back();
if (c == '.' || c == ' ')
{
// s += (wchar_t)(0x9c); // STRING TERMINATOR
s += (wchar_t)'_';
}
}
}
else
*/
{
unsigned i;
for (i = s.Len(); i != 0;)
{
wchar_t c = s[i - 1];
if (c != '.' && c != ' ')
break;
i--;
s.ReplaceOneCharAtPos(i, '_');
// s.ReplaceOneCharAtPos(i, (c == ' ' ? (wchar_t)(0x2423) : (wchar_t)0x00B7));
}
/*
if (g_PathTrailReplaceMode > 1 && i != s.Len())
{
s.DeleteFrom(i);
}
*/
}
}
}
#endif
/* WinXP-64 doesn't support ':', '\\' and '/' symbols in name of alt stream.
But colon in postfix ":$DATA" is allowed.
WIN32 functions don't allow empty alt stream name "name:" */
void Correct_AltStream_Name(UString &s)
{
unsigned len = s.Len();
const unsigned kPostfixSize = 6;
if (s.Len() >= kPostfixSize
&& StringsAreEqualNoCase_Ascii(s.RightPtr(kPostfixSize), ":$DATA"))
len -= kPostfixSize;
for (unsigned i = 0; i < len; i++)
{
wchar_t c = s[i];
if (c == ':' || c == '\\' || c == '/'
|| c == 0x202E // RLO
)
s.ReplaceOneCharAtPos(i, '_');
}
if (s.IsEmpty())
s = '_';
}
#ifdef _WIN32
static const unsigned g_ReservedWithNum_Index = 4;
static const char * const g_ReservedNames[] =
{
"CON", "PRN", "AUX", "NUL",
"COM", "LPT"
};
static bool IsSupportedName(const UString &name)
{
for (unsigned i = 0; i < ARRAY_SIZE(g_ReservedNames); i++)
{
const char *reservedName = g_ReservedNames[i];
unsigned len = MyStringLen(reservedName);
if (name.Len() < len)
continue;
if (!name.IsPrefixedBy_Ascii_NoCase(reservedName))
continue;
if (i >= g_ReservedWithNum_Index)
{
wchar_t c = name[len];
if (c < L'0' || c > L'9')
continue;
len++;
}
for (;;)
{
wchar_t c = name[len++];
if (c == 0 || c == '.')
return false;
if (c != ' ')
break;
}
}
return true;
}
static void CorrectUnsupportedName(UString &name)
{
if (!IsSupportedName(name))
name.InsertAtFront(L'_');
}
#endif
static void Correct_PathPart(UString &s)
{
// "." and ".."
if (s.IsEmpty())
return;
if (s[0] == '.' && (s[1] == 0 || (s[1] == '.' && s[2] == 0)))
s.Empty();
#ifdef _WIN32
else
ReplaceIncorrectChars(s);
#endif
}
// static const char * const k_EmptyReplaceName = "[]";
static const char k_EmptyReplaceName = '_';
UString Get_Correct_FsFile_Name(const UString &name)
{
UString res = name;
Correct_PathPart(res);
#ifdef _WIN32
CorrectUnsupportedName(res);
#endif
if (res.IsEmpty())
res = k_EmptyReplaceName;
return res;
}
void Correct_FsPath(bool absIsAllowed, bool keepAndReplaceEmptyPrefixes, UStringVector &parts, bool isDir)
{
unsigned i = 0;
if (absIsAllowed)
{
#if defined(_WIN32) && !defined(UNDER_CE)
bool isDrive = false;
#endif
if (parts[0].IsEmpty())
{
i = 1;
#if defined(_WIN32) && !defined(UNDER_CE)
if (parts.Size() > 1 && parts[1].IsEmpty())
{
i = 2;
if (parts.Size() > 2 && parts[2] == L"?")
{
i = 3;
if (parts.Size() > 3 && NWindows::NFile::NName::IsDrivePath2(parts[3]))
{
isDrive = true;
i = 4;
}
}
}
#endif
}
#if defined(_WIN32) && !defined(UNDER_CE)
else if (NWindows::NFile::NName::IsDrivePath2(parts[0]))
{
isDrive = true;
i = 1;
}
if (isDrive)
{
// we convert "c:name" to "c:\name", if absIsAllowed path.
UString &ds = parts[i - 1];
if (ds.Len() > 2)
{
parts.Insert(i, ds.Ptr(2));
ds.DeleteFrom(2);
}
}
#endif
}
if (i != 0)
keepAndReplaceEmptyPrefixes = false;
for (; i < parts.Size();)
{
UString &s = parts[i];
Correct_PathPart(s);
if (s.IsEmpty())
{
if (!keepAndReplaceEmptyPrefixes)
if (isDir || i != parts.Size() - 1)
{
parts.Delete(i);
continue;
}
s = k_EmptyReplaceName;
}
else
{
keepAndReplaceEmptyPrefixes = false;
#ifdef _WIN32
CorrectUnsupportedName(s);
#endif
}
i++;
}
if (!isDir)
{
if (parts.IsEmpty())
parts.Add((UString)k_EmptyReplaceName);
else
{
UString &s = parts.Back();
if (s.IsEmpty())
s = k_EmptyReplaceName;
}
}
}
UString MakePathFromParts(const UStringVector &parts)
{
UString s;
FOR_VECTOR (i, parts)
{
if (i != 0)
s.Add_PathSepar();
s += parts[i];
}
return s;
}

View File

@@ -0,0 +1,31 @@
// ExtractingFilePath.h
#ifndef __EXTRACTING_FILE_PATH_H
#define __EXTRACTING_FILE_PATH_H
#include "../../../Common/MyString.h"
// #ifdef _WIN32
void Correct_AltStream_Name(UString &s);
// #endif
// replaces unsuported characters, and replaces "." , ".." and "" to "[]"
UString Get_Correct_FsFile_Name(const UString &name);
/*
Correct_FsPath() corrects path parts to prepare it for File System operations.
It also corrects empty path parts like "\\\\":
- frontal empty path parts : it removes them or changes them to "_"
- another empty path parts : it removes them
if (absIsAllowed && path is absolute) : it removes empty path parts after start absolute path prefix marker
else
{
if (!keepAndReplaceEmptyPrefixes) : it removes empty path parts
if ( keepAndReplaceEmptyPrefixes) : it changes each empty frontal path part to "_"
}
*/
void Correct_FsPath(bool absIsAllowed, bool keepAndReplaceEmptyPrefixes, UStringVector &parts, bool isDir);
UString MakePathFromParts(const UStringVector &parts);
#endif

View File

@@ -0,0 +1,366 @@
// HashCalc.cpp
#include "StdAfx.h"
#include "../../../../C/Alloc.h"
#include "../../../Common/StringToInt.h"
#include "../../Common/FileStreams.h"
#include "../../Common/StreamUtils.h"
#include "../../Common/StreamObjects.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); }
};
static const char * const k_DefaultHashMethod = "CRC32";
HRESULT CHashBundle::SetMethods(DECL_EXTERNAL_CODECS_LOC_VARS const UStringVector &hashMethods)
{
UStringVector names = hashMethods;
if (names.IsEmpty())
names.Add(UString(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 == "*")
{
CRecordVector<CMethodId> tempMethods;
GetHashMethods(EXTERNAL_CODECS_LOC_VARS tempMethods);
methods.Clear();
ids.Clear();
FOR_VECTOR (t, tempMethods)
{
unsigned 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;
unsigned index = ids.AddToUniqueSorted(id);
if (ids.Size() != methods.Size())
methods.Insert(index, m);
}
}
for (i = 0; i < ids.Size(); i++)
{
CMyComPtr<IHasher> hasher;
AString 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 (unsigned k = 0; k < k_HashCalc_NumGroups; k++)
memset(h.Digests[k], 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,
AString &errorInfo,
IHashCallbackUI *callback)
{
CDirItems dirItems;
dirItems.Callback = callback;
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
{
RINOK(callback->StartScanning());
dirItems.SymLinks = options.SymLinks.Val;
dirItems.ScanAltStreams = options.AltStreamsMode;
HRESULT res = EnumerateItems(censor,
options.PathMode,
UString(),
dirItems);
if (res != S_OK)
{
if (res != E_ABORT)
errorInfo = "Scanning error";
return res;
}
RINOK(callback->FinishScanning(dirItems.Stat));
}
unsigned i;
CHashBundle hb;
RINOK(hb.SetMethods(EXTERNAL_CODECS_LOC_VARS options.Methods));
// hb.Init();
hb.NumErrors = dirItems.Stat.NumErrors;
if (options.StdInMode)
{
RINOK(callback->SetNumFiles(1));
}
else
{
RINOK(callback->SetTotal(dirItems.Stat.GetTotalBytes()));
}
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
{
path = dirItems.GetLogPath(i);
const CDirItem &di = dirItems.Items[i];
isAltStream = di.IsAltStream;
#ifndef UNDER_CE
// if (di.AreReparseData())
if (di.ReparseData.Size() != 0)
{
CBufInStream *inStreamSpec = new CBufInStream();
inStream = inStreamSpec;
inStreamSpec->Init(di.ReparseData, di.ReparseData.Size());
}
else
#endif
{
CInFileStream *inStreamSpec = new CInFileStream;
inStreamSpec->File.PreserveATime = options.PreserveATime;
inStream = inStreamSpec;
isDir = di.IsDir();
if (!isDir)
{
const FString phyPath = dirItems.GetPhyPath(i);
if (!inStreamSpec->OpenShared(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(unsigned v)
{
return (char)((v < 10) ? ('0' + v) : ('A' + (v - 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++)
{
unsigned b = data[i];
dest[0] = GetHex((b >> 4) & 0xF);
dest[1] = GetHex(b & 0xF);
dest += step;
}
}

View File

@@ -0,0 +1,120 @@
// HashCalc.h
#ifndef __HASH_CALC_H
#define __HASH_CALC_H
#include "../../../Common/Wildcard.h"
#include "../../Common/CreateCoder.h"
#include "../../Common/MethodProps.h"
#include "DirItem.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;
AString 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 NumDirs;
UInt64 NumFiles;
UInt64 NumAltStreams;
UInt64 FilesSize;
UInt64 AltStreamsSize;
UInt64 NumErrors;
UInt64 CurSize;
UString MainName;
UString FirstFileName;
HRESULT SetMethods(DECL_EXTERNAL_CODECS_LOC_VARS const UStringVector &methods);
// void Init() {}
CHashBundle()
{
NumDirs = NumFiles = NumAltStreams = FilesSize = AltStreamsSize = NumErrors = 0;
}
virtual ~CHashBundle() {};
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) \
INTERFACE_IDirItemsCallback(x) \
virtual HRESULT StartScanning() x; \
virtual HRESULT FinishScanning(const CDirItemsStat &st) 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 FString &path, DWORD systemError) x; \
virtual HRESULT SetOperationResult(UInt64 fileSize, const CHashBundle &hb, bool showHash) x; \
virtual HRESULT AfterLastFile(CHashBundle &hb) x; \
struct IHashCallbackUI: public IDirItemsCallback
{
INTERFACE_IHashCallbackUI(=0)
};
struct CHashOptions
{
UStringVector Methods;
bool PreserveATime;
bool OpenShareForWrite;
bool StdInMode;
bool AltStreamsMode;
CBoolPair SymLinks;
NWildcard::ECensorPathMode PathMode;
CHashOptions():
PreserveATime(false),
OpenShareForWrite(false),
StdInMode(false),
AltStreamsMode(false),
PathMode(NWildcard::k_RelatPath) {};
};
HRESULT HashCalc(
DECL_EXTERNAL_CODECS_LOC_VARS
const NWildcard::CCensor &censor,
const CHashOptions &options,
AString &errorInfo,
IHashCallbackUI *callback);
void AddHashHexToString(char *dest, const Byte *data, UInt32 size);
#endif

View File

@@ -0,0 +1,114 @@
// IFileExtractCallback.h
#ifndef __I_FILE_EXTRACT_CALLBACK_H
#define __I_FILE_EXTRACT_CALLBACK_H
#include "../../../Common/MyString.h"
#include "../../IDecl.h"
#include "LoadCodecs.h"
#include "OpenArchive.h"
namespace NOverwriteAnswer
{
enum EEnum
{
kYes,
kYesToAll,
kNo,
kNoToAll,
kAutoRename,
kCancel
};
}
/* ---------- IFolderArchiveExtractCallback ----------
is implemented by
Console/ExtractCallbackConsole.h CExtractCallbackConsole
FileManager/ExtractCallback.h CExtractCallbackImp
FAR/ExtractEngine.cpp CExtractCallBackImp: (QueryInterface is not supported)
IID_IFolderArchiveExtractCallback is requested by:
- Agent/ArchiveFolder.cpp
CAgentFolder::CopyTo(..., IFolderOperationsExtractCallback *callback)
is sent to IArchiveFolder::Extract()
- FileManager/PanelCopy.cpp
CPanel::CopyTo(), if (options->testMode)
is sent to IArchiveFolder::Extract()
IFolderArchiveExtractCallback is used by Common/ArchiveExtractCallback.cpp
*/
#define INTERFACE_IFolderArchiveExtractCallback(x) \
STDMETHOD(AskOverwrite)( \
const wchar_t *existName, const FILETIME *existTime, const UInt64 *existSize, \
const wchar_t *newName, const FILETIME *newTime, const UInt64 *newSize, \
Int32 *answer) x; \
STDMETHOD(PrepareOperation)(const wchar_t *name, Int32 isFolder, Int32 askExtractMode, const UInt64 *position) x; \
STDMETHOD(MessageError)(const wchar_t *message) x; \
STDMETHOD(SetOperationResult)(Int32 opRes, Int32 encrypted) x; \
DECL_INTERFACE_SUB(IFolderArchiveExtractCallback, IProgress, 0x01, 0x07)
{
INTERFACE_IFolderArchiveExtractCallback(PURE)
};
#define INTERFACE_IFolderArchiveExtractCallback2(x) \
STDMETHOD(ReportExtractResult)(Int32 opRes, Int32 encrypted, const wchar_t *name) x; \
DECL_INTERFACE_SUB(IFolderArchiveExtractCallback2, IUnknown, 0x01, 0x08)
{
INTERFACE_IFolderArchiveExtractCallback2(PURE)
};
/* ---------- IExtractCallbackUI ----------
is implemented by
Console/ExtractCallbackConsole.h CExtractCallbackConsole
FileManager/ExtractCallback.h CExtractCallbackImp
*/
#ifdef _NO_CRYPTO
#define INTERFACE_IExtractCallbackUI_Crypto(x)
#else
#define INTERFACE_IExtractCallbackUI_Crypto(x) \
virtual HRESULT SetPassword(const UString &password) x;
#endif
#define INTERFACE_IExtractCallbackUI(x) \
virtual HRESULT BeforeOpen(const wchar_t *name, bool testMode) x; \
virtual HRESULT OpenResult(const CCodecs *codecs, const CArchiveLink &arcLink, const wchar_t *name, HRESULT result) x; \
virtual HRESULT ThereAreNoFiles() x; \
virtual HRESULT ExtractResult(HRESULT result) x; \
INTERFACE_IExtractCallbackUI_Crypto(x)
struct IExtractCallbackUI: IFolderArchiveExtractCallback
{
INTERFACE_IExtractCallbackUI(PURE)
};
#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, Int32 encrypted) x; \
DECL_INTERFACE_SUB(IFolderExtractToStreamCallback, IUnknown, 0x01, 0x30)
{
INTERFACE_IFolderExtractToStreamCallback(PURE)
};
#endif

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,436 @@
// LoadCodecs.h
#ifndef __LOAD_CODECS_H
#define __LOAD_CODECS_H
/*
Client application uses LoadCodecs.* to load plugins to
CCodecs object, that contains 3 lists of plugins:
1) Formats - internal and external archive handlers
2) Codecs - external codecs
3) Hashers - external hashers
EXTERNAL_CODECS
---------------
if EXTERNAL_CODECS is defined, then the code tries to load external
plugins from DLL files (shared libraries).
There are two types of executables in 7-Zip:
1) Executable that uses external plugins must be compiled
with EXTERNAL_CODECS defined:
- 7z.exe, 7zG.exe, 7zFM.exe
Note: EXTERNAL_CODECS is used also in CPP/7zip/Common/CreateCoder.h
that code is used in plugin module (7z.dll).
2) Standalone modules are compiled without EXTERNAL_CODECS:
- SFX modules: 7z.sfx, 7zCon.sfx
- standalone versions of console 7-Zip: 7za.exe, 7zr.exe
if EXTERNAL_CODECS is defined, CCodecs class implements interfaces:
- ICompressCodecsInfo : for Codecs
- IHashers : for Hashers
The client application can send CCodecs object to each plugin module.
And plugin module can use ICompressCodecsInfo or IHashers interface to access
another plugins.
There are 2 ways to send (ICompressCodecsInfo * compressCodecsInfo) to plugin
1) for old versions:
a) request ISetCompressCodecsInfo from created archive handler.
b) call ISetCompressCodecsInfo::SetCompressCodecsInfo(compressCodecsInfo)
2) for new versions:
a) request "SetCodecs" function from DLL file
b) call SetCodecs(compressCodecsInfo) function from DLL file
*/
#include "../../../Common/MyBuffer.h"
#include "../../../Common/MyCom.h"
#include "../../../Common/MyString.h"
#include "../../../Common/ComTry.h"
#ifdef EXTERNAL_CODECS
#include "../../../Windows/DLL.h"
#endif
#include "../../ICoder.h"
#include "../../Archive/IArchive.h"
#ifdef EXTERNAL_CODECS
struct CDllCodecInfo
{
unsigned LibIndex;
UInt32 CodecIndex;
bool EncoderIsAssigned;
bool DecoderIsAssigned;
CLSID Encoder;
CLSID Decoder;
};
struct CDllHasherInfo
{
unsigned LibIndex;
UInt32 HasherIndex;
};
#endif
struct CArcExtInfo
{
UString Ext;
UString AddExt;
CArcExtInfo() {}
CArcExtInfo(const UString &ext): Ext(ext) {}
CArcExtInfo(const UString &ext, const UString &addExt): Ext(ext), AddExt(addExt) {}
};
struct CArcInfoEx
{
UInt32 Flags;
Func_CreateInArchive CreateInArchive;
Func_IsArc IsArcFunc;
UString Name;
CObjectVector<CArcExtInfo> Exts;
#ifndef _SFX
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 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; }
bool Flags_ByExtOnlyOpen() const { return (Flags & NArcInfoFlags::kByExtOnlyOpen) != 0; }
UString GetMainExt() const
{
if (Exts.IsEmpty())
return UString();
return Exts[0].Ext;
}
int FindExtension(const UString &ext) const;
/*
UString GetAllExtensions() const
{
UString s;
for (int i = 0; i < Exts.Size(); i++)
{
if (i > 0)
s += ' ';
s += Exts[i].Ext;
}
return s;
}
*/
void AddExts(const UString &ext, const UString &addExt);
bool IsSplit() const { return StringsAreEqualNoCase_Ascii(Name, "Split"); }
// bool IsRar() const { return StringsAreEqualNoCase_Ascii(Name, "Rar"); }
CArcInfoEx():
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 NEW_FOLDER_INTERFACE
struct CCodecIcons
{
struct CIconPair
{
UString Ext;
int IconIndex;
};
CObjectVector<CIconPair> IconPairs;
void LoadIcons(HMODULE m);
bool FindIconIndex(const UString &ext, int &iconIndex) const;
};
#endif
#ifdef EXTERNAL_CODECS
struct CCodecLib
#ifdef NEW_FOLDER_INTERFACE
: public CCodecIcons
#endif
{
NWindows::NDLL::CLibrary Lib;
FString Path;
Func_CreateObject CreateObject;
Func_GetMethodProperty GetMethodProperty;
Func_CreateDecoder CreateDecoder;
Func_CreateEncoder CreateEncoder;
Func_SetCodecs SetCodecs;
CMyComPtr<IHashers> ComHashers;
#ifdef NEW_FOLDER_INTERFACE
void LoadIcons() { CCodecIcons::LoadIcons((HMODULE)Lib); }
#endif
CCodecLib():
CreateObject(NULL),
GetMethodProperty(NULL),
CreateDecoder(NULL),
CreateEncoder(NULL),
SetCodecs(NULL)
{}
};
#endif
struct CCodecError
{
FString Path;
HRESULT ErrorCode;
AString Message;
CCodecError(): ErrorCode(0) {}
};
class CCodecs:
#ifdef EXTERNAL_CODECS
public ICompressCodecsInfo,
public IHashers,
#else
public IUnknown,
#endif
public CMyUnknownImp
{
CLASS_NO_COPY(CCodecs);
public:
#ifdef EXTERNAL_CODECS
CObjectVector<CCodecLib> Libs;
FString MainDll_ErrorPath;
CObjectVector<CCodecError> Errors;
void AddLastError(const FString &path);
void CloseLibs();
class CReleaser
{
CLASS_NO_COPY(CReleaser);
/* CCodecsReleaser object releases CCodecs links.
1) CCodecs is COM object that is deleted when all links to that object will be released/
2) CCodecs::Libs[i] can hold (ICompressCodecsInfo *) link to CCodecs object itself.
To break that reference loop, we must close all CCodecs::Libs in CCodecsReleaser desttructor. */
CCodecs *_codecs;
public:
CReleaser(): _codecs(NULL) {}
void Set(CCodecs *codecs) { _codecs = codecs; }
~CReleaser() { if (_codecs) _codecs->CloseLibs(); }
};
bool NeedSetLibCodecs; // = false, if we don't need to set codecs for archive handler via ISetCompressCodecsInfo
HRESULT LoadCodecs();
HRESULT LoadFormats();
HRESULT LoadDll(const FString &path, bool needCheckDll, bool *loadedOK = NULL);
HRESULT LoadDllsFromFolder(const FString &folderPrefix);
HRESULT CreateArchiveHandler(const CArcInfoEx &ai, bool outHandler, void **archive) const
{
return Libs[(unsigned)ai.LibIndex].CreateObject(&ai.ClassID, outHandler ? &IID_IOutArchive : &IID_IInArchive, (void **)archive);
}
#endif
#ifdef NEW_FOLDER_INTERFACE
CCodecIcons InternalIcons;
#endif
CObjectVector<CArcInfoEx> Formats;
#ifdef EXTERNAL_CODECS
CRecordVector<CDllCodecInfo> Codecs;
CRecordVector<CDllHasherInfo> Hashers;
#endif
bool CaseSensitiveChange;
bool CaseSensitive;
CCodecs():
#ifdef EXTERNAL_CODECS
NeedSetLibCodecs(true),
#endif
CaseSensitiveChange(false),
CaseSensitive(false)
{}
~CCodecs()
{
// OutputDebugStringA("~CCodecs");
}
const wchar_t *GetFormatNamePtr(int formatIndex) const
{
return formatIndex < 0 ? L"#" : (const wchar_t *)Formats[(unsigned)formatIndex].Name;
}
HRESULT Load();
#ifndef _SFX
int FindFormatForArchiveName(const UString &arcPath) const;
int FindFormatForExtension(const UString &ext) const;
int FindFormatForArchiveType(const UString &arcType) const;
bool FindFormatForArchiveType(const UString &arcType, CIntVector &formatIndices) const;
#endif
#ifdef EXTERNAL_CODECS
MY_UNKNOWN_IMP2(ICompressCodecsInfo, IHashers)
STDMETHOD(GetNumMethods)(UInt32 *numMethods);
STDMETHOD(GetProperty)(UInt32 index, PROPID propID, PROPVARIANT *value);
STDMETHOD(CreateDecoder)(UInt32 index, const GUID *iid, void **coder);
STDMETHOD(CreateEncoder)(UInt32 index, const GUID *iid, void **coder);
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 GetCodec_LibIndex(UInt32 index) const;
bool GetCodec_DecoderIsAssigned(UInt32 index) const;
bool GetCodec_EncoderIsAssigned(UInt32 index) const;
UInt32 GetCodec_NumStreams(UInt32 index);
HRESULT GetCodec_Id(UInt32 index, UInt64 &id);
AString GetCodec_Name(UInt32 index);
int GetHasherLibIndex(UInt32 index);
UInt64 GetHasherId(UInt32 index);
AString GetHasherName(UInt32 index);
UInt32 GetHasherDigestSize(UInt32 index);
void GetCodecsErrorMessage(UString &s);
#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, false, (void **)&archive);
#endif
}
#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, true, (void **)&archive);
#endif
}
int FindOutFormatFromName(const UString &name) const
{
FOR_VECTOR (i, Formats)
{
const CArcInfoEx &arc = Formats[i];
if (!arc.UpdateEnabled)
continue;
if (arc.Name.IsEqualTo_NoCase(name))
return (int)i;
}
return -1;
}
#endif // _SFX
};
#ifdef EXTERNAL_CODECS
#define CREATE_CODECS_OBJECT \
CCodecs *codecs = new CCodecs; \
CExternalCodecs __externalCodecs; \
__externalCodecs.GetCodecs = codecs; \
__externalCodecs.GetHashers = codecs; \
CCodecs::CReleaser codecsReleaser; \
codecsReleaser.Set(codecs);
#else
#define CREATE_CODECS_OBJECT \
CCodecs *codecs = new CCodecs; \
CMyComPtr<IUnknown> __codecsRef = codecs;
#endif
#endif

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,443 @@
// OpenArchive.h
#ifndef __OPEN_ARCHIVE_H
#define __OPEN_ARCHIVE_H
#include "../../../Windows/PropVariant.h"
#include "ArchiveOpenCallback.h"
#include "LoadCodecs.h"
#include "Property.h"
#ifndef _SFX
#define SUPPORT_ALT_STREAMS
#endif
HRESULT Archive_GetItemBoolProp(IInArchive *arc, UInt32 index, PROPID propID, bool &result) throw();
HRESULT Archive_IsItem_Dir(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();
#ifdef SUPPORT_ALT_STREAMS
int FindAltStreamColon_in_Path(const wchar_t *path);
#endif
/*
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; // it's used for SFX only
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;
}
};
struct CReadArcItem
{
UString Path; // Path from root (including alt stream name, if alt stream)
UStringVector PathParts; // without altStream name, path from root or from _baseParentFolder, if _use_baseParentFolder_mode
#ifdef SUPPORT_ALT_STREAMS
UString MainPath;
/* MainPath = Path for non-AltStream,
MainPath = Path of parent, if there is parent for AltStream. */
UString AltStreamName;
bool IsAltStream;
bool WriteToAltStreamIfColon;
#endif
bool IsDir;
bool MainIsDir;
UInt32 ParentIndex; // use it, if IsAltStream
#ifndef _SFX
bool _use_baseParentFolder_mode;
int _baseParentFolder;
#endif
CReadArcItem()
{
#ifdef SUPPORT_ALT_STREAMS
WriteToAltStreamIfColon = false;
#endif
#ifndef _SFX
_use_baseParentFolder_mode = false;
_baseParentFolder = -1;
#endif
}
};
class CArc
{
HRESULT PrepareToOpen(const COpenOptions &op, unsigned formatIndex, CMyComPtr<IInArchive> &archive);
HRESULT CheckZerosTail(const COpenOptions &op, UInt64 offset);
HRESULT OpenStream2(const COpenOptions &options);
#ifndef _SFX
// parts.Back() can contain alt stream name "nams:AltName"
HRESULT GetItemPathToParent(UInt32 index, UInt32 parent, UStringVector &parts) const;
#endif
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; // - 1 means Parser.
UInt32 SubfileIndex; // (UInt32)(Int32)-1; means no subfile
FILETIME MTime;
bool MTimeDefined;
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 GetEstmatedPhySize() const { return PhySizeDefined ? PhySize : FileSize; }
UInt64 ArcStreamOffset; // offset of stream that is open by Archive Handler
Int64 GetGlobalOffset() const { return (Int64)ArcStreamOffset + Offset; } // it's global offset of archive
// AString ErrorFlagsText;
bool IsParseArc;
bool IsTree;
bool IsReadOnly;
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),
IsReadOnly(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();
}
HRESULT GetItemPath(UInt32 index, UString &result) const;
HRESULT GetDefaultItemPath(UInt32 index, UString &result) const;
// GetItemPath2 adds [DELETED] dir prefix for deleted items.
HRESULT GetItemPath2(UInt32 index, UString &result) const;
HRESULT GetItem(UInt32 index, CReadArcItem &item) 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 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
{
CObjectVector<CArc> Arcs;
UStringVector VolumePaths;
UInt64 VolumesSize;
bool IsOpen;
bool PasswordWasAsked;
// UString Password;
// int NonOpenErrorFormatIndex; // - 1 means no Error.
UString NonOpen_ArcPath;
CArcErrorInfo NonOpen_ErrorInfo;
// UString ErrorsText;
// void Set_ErrorsText();
CArchiveLink():
VolumesSize(0),
IsOpen(false),
PasswordWasAsked(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; }
/*
Open() opens archive and COpenOptions::callback
Open2() uses COpenCallbackImp that implements Volumes and password callback
Open3() calls Open2() and callbackUI->Open_Finished();
Open_Strict() returns S_FALSE also in case, if there is non-open expected nested archive.
*/
HRESULT Open(COpenOptions &options);
HRESULT Open2(COpenOptions &options, IOpenCallbackUI *callbackUI);
HRESULT Open3(COpenOptions &options, IOpenCallbackUI *callbackUI);
HRESULT Open_Strict(COpenOptions &options, IOpenCallbackUI *callbackUI)
{
HRESULT result = Open3(options, callbackUI);
if (result == S_OK && NonOpen_ErrorInfo.ErrorFormatIndex >= 0)
result = S_FALSE;
return result;
}
HRESULT ReOpen(COpenOptions &options);
};
bool ParseOpenTypes(CCodecs &codecs, const UString &s, CObjectVector<COpenType> &types);
struct CDirPathSortPair
{
unsigned Len;
unsigned Index;
void SetNumSlashes(const FChar *s);
int Compare(const CDirPathSortPair &a) const
{
// We need sorting order where parent items will be after child items
if (Len < a.Len) return 1;
if (Len > a.Len) return -1;
if (Index < a.Index) return -1;
if (Index > a.Index) return 1;
return 0;
}
};
#endif

View File

@@ -0,0 +1,696 @@
// PropIDUtils.cpp
#include "StdAfx.h"
#include "../../../../C/CpuArch.h"
#include "../../../Common/IntToString.h"
#include "../../../Common/StringConvert.h"
#include "../../../Windows/FileIO.h"
#include "../../../Windows/PropVariantConv.h"
#include "../../PropID.h"
#include "PropIDUtils.h"
#ifndef _SFX
#define Get16(x) GetUi16(x)
#define Get32(x) GetUi32(x)
#endif
using namespace NWindows;
static const unsigned kNumWinAtrribFlags = 21;
static const char g_WinAttribChars[kNumWinAtrribFlags + 1] = "RHS8DAdNTsLCOIEV.X.PU";
/*
FILE_ATTRIBUTE_
0 READONLY
1 HIDDEN
2 SYSTEM
3 (Volume label - obsolete)
4 DIRECTORY
5 ARCHIVE
6 DEVICE
7 NORMAL
8 TEMPORARY
9 SPARSE_FILE
10 REPARSE_POINT
11 COMPRESSED
12 OFFLINE
13 NOT_CONTENT_INDEXED (I - Win10 attrib/Explorer)
14 ENCRYPTED
15 INTEGRITY_STREAM (V - ReFS Win8/Win2012)
16 VIRTUAL (reserved)
17 NO_SCRUB_DATA (X - ReFS Win8/Win2012 attrib)
18 RECALL_ON_OPEN or EA
19 PINNED
20 UNPINNED
21 STRICTLY_SEQUENTIAL
22 RECALL_ON_DATA_ACCESS
*/
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 : '-';
static void ConvertPosixAttribToString(char *s, UInt32 a) throw()
{
s[0] = kPosixTypes[(a >> 12) & 0xF];
for (int i = 6; i >= 0; i -= 3)
{
s[7 - i] = MY_ATTR_CHAR(a, i + 2, 'r');
s[8 - i] = MY_ATTR_CHAR(a, i + 1, 'w');
s[9 - i] = MY_ATTR_CHAR(a, i + 0, 'x');
}
if ((a & 0x800) != 0) s[3] = ((a & (1 << 6)) ? 's' : 'S'); // S_ISUID
if ((a & 0x400) != 0) s[6] = ((a & (1 << 3)) ? 's' : 'S'); // S_ISGID
if ((a & 0x200) != 0) s[9] = ((a & (1 << 0)) ? 't' : 'T'); // S_ISVTX
s[10] = 0;
a &= ~(UInt32)0xFFFF;
if (a != 0)
{
s[10] = ' ';
ConvertUInt32ToHex8Digits(a, s + 11);
}
}
void ConvertWinAttribToString(char *s, UInt32 wa) throw()
{
/*
some programs store posix attributes in high 16 bits.
p7zip - stores additional 0x8000 flag marker.
macos - stores additional 0x4000 flag marker.
info-zip - no additional marker.
*/
bool isPosix = ((wa & 0xF0000000) != 0);
UInt32 posix = 0;
if (isPosix)
{
posix = wa >> 16;
wa &= (UInt32)0x3FFF;
}
for (unsigned i = 0; i < kNumWinAtrribFlags; i++)
{
UInt32 flag = (1 << i);
if ((wa & flag) != 0)
{
char c = g_WinAttribChars[i];
if (c != '.')
{
wa &= ~flag;
// if (i != 7) // we can disable N (NORMAL) printing
*s++ = c;
}
}
}
if (wa != 0)
{
*s++ = ' ';
ConvertUInt32ToHex8Digits(wa, s);
s += strlen(s);
}
*s = 0;
if (isPosix)
{
*s++ = ' ';
ConvertPosixAttribToString(s, posix);
}
}
void ConvertPropertyToShortString2(char *dest, const PROPVARIANT &prop, PROPID propID, int level) throw()
{
*dest = 0;
if (prop.vt == VT_FILETIME)
{
const FILETIME &ft = prop.filetime;
if ((ft.dwHighDateTime == 0 &&
ft.dwLowDateTime == 0))
return;
ConvertUtcFileTimeToString(prop.filetime, dest, level);
return;
}
switch (propID)
{
case kpidCRC:
{
if (prop.vt != VT_UI4)
break;
ConvertUInt32ToHex8Digits(prop.ulVal, dest);
return;
}
case kpidAttrib:
{
if (prop.vt != VT_UI4)
break;
UInt32 a = prop.ulVal;
/*
if ((a & 0x8000) && (a & 0x7FFF) == 0)
ConvertPosixAttribToString(dest, a >> 16);
else
*/
ConvertWinAttribToString(dest, a);
return;
}
case kpidPosixAttrib:
{
if (prop.vt != VT_UI4)
break;
ConvertPosixAttribToString(dest, prop.ulVal);
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 (prop.vt == VT_UI4)
v = prop.ulVal;
else if (prop.vt == VT_UI8)
v = (UInt64)prop.uhVal.QuadPart;
else
break;
dest[0] = '0';
dest[1] = 'x';
ConvertUInt64ToHex(v, dest + 2);
return;
}
}
ConvertPropVariantToShortString(prop, dest);
}
void ConvertPropertyToString2(UString &dest, const PROPVARIANT &prop, PROPID propID, int level)
{
if (prop.vt == VT_BSTR)
{
dest.SetFromBstr(prop.bstrVal);
return;
}
char temp[64];
ConvertPropertyToShortString2(temp, prop, propID, level);
dest = temp;
}
#ifndef _SFX
static inline unsigned GetHex(unsigned v)
{
return (v < 10) ? ('0' + v) : ('A' + (v - 10));
}
static inline void AddHexToString(AString &res, unsigned v)
{
res += (char)GetHex(v >> 4);
res += (char)GetHex(v & 0xF);
}
/*
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 * const 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;
};
static int FindPairIndex(const CSecID2Name * pairs, unsigned num, UInt32 id)
{
for (unsigned i = 0; i < num; i++)
if (pairs[i].n == id)
return (int)i;
return -1;
}
static 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);
int index = FindPairIndex(sid_32_Names, ARRAY_SIZE(sid_32_Names), v1);
if (index >= 0)
{
s += sid_32_Names[(unsigned)index].sz;
return;
}
}
if (v0 == 21 && num == 5)
{
UInt32 v4 = Get32(p + 8 + 4 * 4);
int index = FindPairIndex(sid_21_Names, ARRAY_SIZE(sid_21_Names), v4);
if (index >= 0)
{
s += sid_21_Names[(unsigned)index].sz;
return;
}
}
if (v0 == 80 && num == 6)
{
for (unsigned 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;
}
}
}
}
s += "S-1-";
if (p[2] == 0 && p[3] == 0)
s.Add_UInt32(authority);
else
{
s += "0x";
for (int i = 2; i < 8; i++)
AddHexToString(s, p[i]);
}
for (UInt32 i = 0; i < num; i++)
{
s += '-';
s.Add_UInt32(Get32(p + 8 + i * 4));
}
}
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 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.Add_Space();
s += strName;
if (pos >= size)
return;
p += pos;
size -= pos;
if (size < 8)
return;
if (Get16(p) != 2) // revision
return;
UInt32 num = Get32(p + 4);
s.Add_UInt32(num);
/*
UInt32 aclSize = Get16(p + 2);
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.Add_Space();
ParseSid(s, p, size, sidSize);
if (sidSize == 0)
return;
p += sidSize;
size -= sidSize;
}
// the tail can contain zeros. So (size != 0) is not ERROR
// 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.Add_Space();
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.Add_Space();
s.Add_UInt32(size);
// s += '\n';
// s += Data_To_Hex(data, size);
}
#ifdef _WIN32
static bool CheckSid(const Byte *data, UInt32 size, UInt32 pos) throw()
{
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) throw()
{
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) throw()
{
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
// IO_REPARSE_TAG_*
static const CSecID2Name k_ReparseTags[] =
{
{ 0xA0000003, "MOUNT_POINT" },
{ 0xC0000004, "HSM" },
{ 0x80000005, "DRIVE_EXTENDER" },
{ 0x80000006, "HSM2" },
{ 0x80000007, "SIS" },
{ 0x80000008, "WIM" },
{ 0x80000009, "CSV" },
{ 0x8000000A, "DFS" },
{ 0x8000000B, "FILTER_MANAGER" },
{ 0xA000000C, "SYMLINK" },
{ 0xA0000010, "IIS_CACHE" },
{ 0x80000012, "DFSR" },
{ 0x80000013, "DEDUP" },
{ 0xC0000014, "APPXSTRM" },
{ 0x80000014, "NFS" },
{ 0x80000015, "FILE_PLACEHOLDER" },
{ 0x80000016, "DFM" },
{ 0x80000017, "WOF" },
{ 0x80000018, "WCI" },
{ 0x8000001B, "APPEXECLINK" },
{ 0xA000001D, "LX_SYMLINK" },
{ 0x80000023, "AF_UNIX" },
{ 0x80000024, "LX_FIFO" },
{ 0x80000025, "LX_CHR" },
{ 0x80000026, "LX_BLK" }
};
bool ConvertNtReparseToString(const Byte *data, UInt32 size, UString &s)
{
s.Empty();
NFile::CReparseAttr attr;
if (attr.Parse(data, size))
{
if (attr.IsSymLink_WSL())
{
s += "WSL: ";
s += attr.GetPath();
}
else
{
if (!attr.IsSymLink_Win())
s += "Junction: ";
s += attr.GetPath();
if (s.IsEmpty())
s += "Link: ";
if (!attr.IsOkNamePair())
{
s += " : ";
s += attr.PrintName;
}
}
if (attr.MinorError)
s += " : MINOR_ERROR";
return true;
// s += " "; // for debug
}
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;
/*
#define _my_IO_REPARSE_TAG_DEDUP (0x80000013L)
if (tag == _my_IO_REPARSE_TAG_DEDUP)
{
}
*/
{
int index = FindPairIndex(k_ReparseTags, ARRAY_SIZE(k_ReparseTags), tag);
if (index >= 0)
s += k_ReparseTags[(unsigned)index].sz;
else
{
s += "REPARSE:";
char hex[16];
ConvertUInt32ToHex8Digits(tag, hex);
s += hex;
}
}
s += ":";
s.Add_UInt32(len);
if (len != 0)
{
s.Add_Space();
data += 8;
for (UInt32 i = 0; i < len; i++)
{
if (i >= 16)
{
s += "...";
break;
}
unsigned b = data[i];
s += (char)GetHex((b >> 4) & 0xF);
s += (char)GetHex(b & 0xF);
}
}
return true;
}
#endif

View File

@@ -0,0 +1,18 @@
// PropIDUtils.h
#ifndef __PROPID_UTILS_H
#define __PROPID_UTILS_H
#include "../../../Common/MyString.h"
// provide at least 64 bytes for buffer including zero-end
void ConvertPropertyToShortString2(char *dest, const PROPVARIANT &propVariant, PROPID propID, int level = 0) throw();
void ConvertPropertyToString2(UString &dest, const PROPVARIANT &propVariant, PROPID propID, int level = 0);
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) throw();;
void ConvertWinAttribToString(char *s, UInt32 wa) throw();
#endif

View File

@@ -0,0 +1,14 @@
// Property.h
#ifndef __7Z_PROPERTY_H
#define __7Z_PROPERTY_H
#include "../../../Common/MyString.h"
struct CProperty
{
UString Name;
UString Value;
};
#endif

View File

@@ -0,0 +1,87 @@
// SetProperties.cpp
#include "StdAfx.h"
#include "../../../Common/MyCom.h"
#include "../../../Common/MyString.h"
#include "../../../Common/StringToInt.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 *end;
UInt64 result = ConvertStringToUInt64(s, &end);
if (*end != 0 || s.IsEmpty())
prop = s;
else if (result <= (UInt32)0xFFFFFFFF)
prop = (UInt32)result;
else
prop = result;
}
struct CPropPropetiesVector
{
CPropVariant *values;
CPropPropetiesVector(unsigned num)
{
values = new CPropVariant[num];
}
~CPropPropetiesVector()
{
delete []values;
}
};
HRESULT SetProperties(IUnknown *unknown, const CObjectVector<CProperty> &properties)
{
if (properties.IsEmpty())
return S_OK;
CMyComPtr<ISetProperties> setProperties;
unknown->QueryInterface(IID_ISetProperties, (void **)&setProperties);
if (!setProperties)
return S_OK;
UStringVector realNames;
CPropPropetiesVector values(properties.Size());
{
unsigned i;
for (i = 0; i < properties.Size(); i++)
{
const CProperty &property = properties[i];
NCOM::CPropVariant propVariant;
UString name = property.Name;
if (property.Value.IsEmpty())
{
if (!name.IsEmpty())
{
wchar_t c = name.Back();
if (c == L'-')
propVariant = false;
else if (c == L'+')
propVariant = true;
if (propVariant.vt != VT_EMPTY)
name.DeleteBack();
}
}
else
ParseNumberString(property.Value, propVariant);
realNames.Add(name);
values.values[i] = propVariant;
}
CRecordVector<const wchar_t *> names;
for (i = 0; i < realNames.Size(); i++)
names.Add((const wchar_t *)realNames[i]);
return setProperties->SetProperties(&names.Front(), values.values, names.Size());
}
}

View File

@@ -0,0 +1,10 @@
// SetProperties.h
#ifndef __SETPROPERTIES_H
#define __SETPROPERTIES_H
#include "Property.h"
HRESULT SetProperties(IUnknown *unknown, const CObjectVector<CProperty> &properties);
#endif

View File

@@ -0,0 +1,25 @@
// SortUtils.cpp
#include "StdAfx.h"
#include "../../../Common/Wildcard.h"
#include "SortUtils.h"
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, CUIntVector &indices)
{
const unsigned numItems = strings.Size();
indices.ClearAndSetSize(numItems);
if (numItems == 0)
return;
unsigned *vals = &indices[0];
for (unsigned i = 0; i < numItems; i++)
vals[i] = i;
indices.Sort(CompareStrings, (void *)&strings);
}

View File

@@ -0,0 +1,10 @@
// SortUtils.h
#ifndef __SORT_UTLS_H
#define __SORT_UTLS_H
#include "../../../Common/MyString.h"
void SortFileNames(const UStringVector &strings, CUIntVector &indices);
#endif

View File

@@ -0,0 +1,8 @@
// StdAfx.h
#ifndef __STDAFX_H
#define __STDAFX_H
#include "../../../Common/Common.h"
#endif

View File

@@ -0,0 +1,19 @@
// TempFiles.cpp
#include "StdAfx.h"
#include "../../../Windows/FileDir.h"
#include "TempFiles.h"
using namespace NWindows;
using namespace NFile;
void CTempFiles::Clear()
{
while (!Paths.IsEmpty())
{
NDir::DeleteFileAlways(Paths.Back());
Paths.DeleteBack();
}
}

View File

@@ -0,0 +1,16 @@
// TempFiles.h
#ifndef __TEMP_FILES_H
#define __TEMP_FILES_H
#include "../../../Common/MyString.h"
class CTempFiles
{
void Clear();
public:
FStringVector Paths;
~CTempFiles() { Clear(); }
};
#endif

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,208 @@
// Update.h
#ifndef __COMMON_UPDATE_H
#define __COMMON_UPDATE_H
#include "../../../Common/Wildcard.h"
#include "ArchiveOpenCallback.h"
#include "LoadCodecs.h"
#include "OpenArchive.h"
#include "Property.h"
#include "UpdateAction.h"
#include "UpdateCallback.h"
#include "DirItem.h"
enum EArcNameMode
{
k_ArcNameMode_Smart,
k_ArcNameMode_Exact,
k_ArcNameMode_Add
};
struct CArchivePath
{
UString OriginalPath;
UString Prefix; // path(folder) prefix including slash
UString Name; // base name
UString BaseExtension; // archive type extension or "exe" extension
UString VolExtension; // archive type extension for volumes
bool Temp;
FString TempPrefix; // path(folder) for temp location
FString TempPostfix;
CArchivePath(): Temp(false) {};
void ParseFromPath(const UString &path, EArcNameMode mode);
UString GetPathWithoutExt() const { return Prefix + Name; }
UString GetFinalPath() const;
UString GetFinalVolPath() const;
FString GetTempPath() const;
};
struct CUpdateArchiveCommand
{
UString UserArchivePath;
CArchivePath ArchivePath;
NUpdateArchive::CActionSet ActionSet;
};
struct CCompressionMethodMode
{
bool Type_Defined;
COpenType Type;
CObjectVector<CProperty> Properties;
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
{
CCompressionMethodMode MethodMode;
CObjectVector<CUpdateArchiveCommand> Commands;
bool UpdateArchiveItself;
CArchivePath ArchivePath;
EArcNameMode ArcNameMode;
bool SfxMode;
FString SfxModule;
bool PreserveATime;
bool OpenShareForWrite;
bool StopAfterOpenError;
bool StdInMode;
UString StdInFileName;
bool StdOutMode;
bool EMailMode;
bool EMailRemoveAfter;
UString EMailAddress;
FString WorkingDir;
NWildcard::ECensorPathMode PathMode;
// UString AddPathPrefix;
CBoolPair NtSecurity;
CBoolPair AltStreams;
CBoolPair HardLinks;
CBoolPair SymLinks;
bool DeleteAfterCompressing;
bool SetArcMTime;
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),
PreserveATime(false),
OpenShareForWrite(false),
StopAfterOpenError(false),
StdInMode(false),
StdOutMode(false),
EMailMode(false),
EMailRemoveAfter(false),
PathMode(NWildcard::k_RelatPath),
DeleteAfterCompressing(false),
SetArcMTime(false)
{};
void SetActionCommand_Add()
{
Commands.Clear();
CUpdateArchiveCommand c;
c.ActionSet = NUpdateArchive::k_ActionSet_Add;
Commands.Add(c);
}
CRecordVector<UInt64> VolumesSizes;
};
struct CUpdateErrorInfo
{
DWORD SystemError; // it's DWORD (WRes) only;
AString Message;
FStringVector FileNames;
bool ThereIsError() const { return SystemError != 0 || !Message.IsEmpty() || !FileNames.IsEmpty(); }
HRESULT Get_HRESULT_Error() const { return SystemError == 0 ? E_FAIL : HRESULT_FROM_WIN32(SystemError); }
void SetFromLastError(const char *message);
HRESULT SetFromLastError(const char *message, const FString &fileName);
HRESULT SetFromError_DWORD(const char *message, const FString &fileName, DWORD error);
CUpdateErrorInfo(): SystemError(0) {};
};
struct CFinishArchiveStat
{
UInt64 OutArcFileSize;
CFinishArchiveStat(): OutArcFileSize(0) {}
};
#define INTERFACE_IUpdateCallbackUI2(x) \
INTERFACE_IUpdateCallbackUI(x) \
INTERFACE_IDirItemsCallback(x) \
virtual HRESULT OpenResult(const CCodecs *codecs, const CArchiveLink &arcLink, const wchar_t *name, HRESULT result) x; \
virtual HRESULT StartScanning() x; \
virtual HRESULT FinishScanning(const CDirItemsStat &st) x; \
virtual HRESULT StartOpenArchive(const wchar_t *name) x; \
virtual HRESULT StartArchive(const wchar_t *name, bool updating) x; \
virtual HRESULT FinishArchive(const CFinishArchiveStat &st) x; \
virtual HRESULT DeletingAfterArchiving(const FString &path, bool isDir) x; \
virtual HRESULT FinishDeletingAfterArchiving() x; \
struct IUpdateCallbackUI2: public IUpdateCallbackUI, public IDirItemsCallback
{
INTERFACE_IUpdateCallbackUI2(=0)
};
HRESULT UpdateArchive(
CCodecs *codecs,
const CObjectVector<COpenType> &types,
const UString &cmdArcPath2,
NWildcard::CCensor &censor,
CUpdateOptions &options,
CUpdateErrorInfo &errorInfo,
IOpenCallbackUI *openCallback,
IUpdateCallbackUI2 *callback,
bool needSetPath);
#endif

View File

@@ -0,0 +1,64 @@
// UpdateAction.cpp
#include "StdAfx.h"
#include "UpdateAction.h"
namespace NUpdateArchive {
const CActionSet k_ActionSet_Add =
{{
NPairAction::kCopy,
NPairAction::kCopy,
NPairAction::kCompress,
NPairAction::kCompress,
NPairAction::kCompress,
NPairAction::kCompress,
NPairAction::kCompress
}};
const CActionSet k_ActionSet_Update =
{{
NPairAction::kCopy,
NPairAction::kCopy,
NPairAction::kCompress,
NPairAction::kCopy,
NPairAction::kCompress,
NPairAction::kCopy,
NPairAction::kCompress
}};
const CActionSet k_ActionSet_Fresh =
{{
NPairAction::kCopy,
NPairAction::kCopy,
NPairAction::kIgnore,
NPairAction::kCopy,
NPairAction::kCompress,
NPairAction::kCopy,
NPairAction::kCompress
}};
const CActionSet k_ActionSet_Sync =
{{
NPairAction::kCopy,
NPairAction::kIgnore,
NPairAction::kCompress,
NPairAction::kCopy,
NPairAction::kCompress,
NPairAction::kCopy,
NPairAction::kCompress,
}};
const CActionSet k_ActionSet_Delete =
{{
NPairAction::kCopy,
NPairAction::kIgnore,
NPairAction::kIgnore,
NPairAction::kIgnore,
NPairAction::kIgnore,
NPairAction::kIgnore,
NPairAction::kIgnore
}};
}

View File

@@ -0,0 +1,66 @@
// UpdateAction.h
#ifndef __UPDATE_ACTION_H
#define __UPDATE_ACTION_H
namespace NUpdateArchive {
namespace NPairState
{
const unsigned kNumValues = 7;
enum EEnum
{
kNotMasked = 0,
kOnlyInArchive,
kOnlyOnDisk,
kNewInArchive,
kOldInArchive,
kSameFiles,
kUnknowNewerFiles
};
}
namespace NPairAction
{
enum EEnum
{
kIgnore = 0,
kCopy,
kCompress,
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
{
unsigned i;
for (i = 0; i < NPairState::kNumValues; i++)
if (StateActions[i] == NPairAction::kCompress)
return true;
for (i = 1; i < NPairState::kNumValues; i++)
if (StateActions[i] != NPairAction::kIgnore)
return true;
return false;
}
};
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

View File

@@ -0,0 +1,834 @@
// UpdateCallback.cpp
#include "StdAfx.h"
// #include <stdio.h>
#ifndef _7ZIP_ST
#include "../../../Windows/Synchronization.h"
#endif
#include "../../../Common/ComTry.h"
#include "../../../Common/IntToString.h"
#include "../../../Common/StringConvert.h"
#include "../../../Common/Wildcard.h"
#include "../../../Common/UTFConvert.h"
#include "../../../Windows/FileDir.h"
#include "../../../Windows/FileName.h"
#include "../../../Windows/PropVariant.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;
#ifndef _7ZIP_ST
static NSynchronization::CCriticalSection g_CriticalSection;
#define MT_LOCK NSynchronization::CCriticalSectionLock lock(g_CriticalSection);
#else
#define MT_LOCK
#endif
#ifdef _USE_SECURITY_CODE
bool InitLocalPrivileges();
#endif
CArchiveUpdateCallback::CArchiveUpdateCallback():
_hardIndex_From((UInt32)(Int32)-1),
Callback(NULL),
DirItems(NULL),
ParentDirItem(NULL),
Arc(NULL),
ArcItems(NULL),
UpdatePairs(NULL),
NewNames(NULL),
CommentIndex(-1),
Comment(NULL),
PreserveATime(false),
ShareForWrite(false),
StopAfterOpenError(false),
StdInMode(false),
KeepOriginalItemNames(false),
StoreNtSecurity(false),
StoreHardLinks(false),
StoreSymLinks(false),
ProcessedItemsStatuses(NULL)
{
#ifdef _USE_SECURITY_CODE
_saclEnabled = InitLocalPrivileges();
#endif
}
STDMETHODIMP CArchiveUpdateCallback::SetTotal(UInt64 size)
{
COM_TRY_BEGIN
return Callback->SetTotal(size);
COM_TRY_END
}
STDMETHODIMP CArchiveUpdateCallback::SetCompleted(const UInt64 *completeValue)
{
COM_TRY_BEGIN
return Callback->SetCompleted(completeValue);
COM_TRY_END
}
STDMETHODIMP CArchiveUpdateCallback::SetRatioInfo(const UInt64 *inSize, const UInt64 *outSize)
{
COM_TRY_BEGIN
return Callback->SetRatioInfo(inSize, outSize);
COM_TRY_END
}
/*
static const CStatProp kProps[] =
{
{ NULL, kpidPath, VT_BSTR},
{ NULL, kpidIsDir, VT_BOOL},
{ NULL, kpidSize, VT_UI8},
{ NULL, kpidCTime, VT_FILETIME},
{ NULL, kpidATime, VT_FILETIME},
{ NULL, kpidMTime, VT_FILETIME},
{ NULL, kpidAttrib, VT_UI4},
{ NULL, kpidIsAnti, VT_BOOL}
};
STDMETHODIMP CArchiveUpdateCallback::EnumProperties(IEnumSTATPROPSTG **)
{
return CStatPropEnumerator::CreateEnumerator(kProps, ARRAY_SIZE(kProps), enumerator);
}
*/
STDMETHODIMP CArchiveUpdateCallback::GetUpdateItemInfo(UInt32 index,
Int32 *newData, Int32 *newProps, UInt32 *indexInArchive)
{
COM_TRY_BEGIN
RINOK(Callback->CheckBreak());
const CUpdatePair2 &up = (*UpdatePairs)[index];
if (newData) *newData = BoolToInt(up.NewData);
if (newProps) *newProps = BoolToInt(up.NewProps);
if (indexInArchive)
{
*indexInArchive = (UInt32)(Int32)-1;
if (up.ExistInArchive())
*indexInArchive = ArcItems ? (*ArcItems)[(unsigned)up.ArcIndex].IndexInServer : (UInt32)(Int32)up.ArcIndex;
}
return S_OK;
COM_TRY_END
}
STDMETHODIMP CArchiveUpdateCallback::GetRootProp(PROPID propID, PROPVARIANT *value)
{
NCOM::CPropVariant prop;
switch (propID)
{
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[(unsigned)ParentDirItem->SecureIndex];
*data = buf;
*dataSize = (UInt32)buf.Size();
*propType = NPropDataType::kRaw;
return S_OK;
}
if (Arc && Arc->GetRootProps)
return Arc->GetRootProps->GetRootRawProp(propID, data, dataSize, propType);
}
#endif
return S_OK;
}
// #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)
{
if (StdInMode)
return S_OK;
const CUpdatePair2 &up = (*UpdatePairs)[index];
if (up.UseArcProps && up.ExistInArchive() && Arc->GetRawProps)
return Arc->GetRawProps->GetRawProp(
ArcItems ? (*ArcItems)[(unsigned)up.ArcIndex].IndexInServer : (UInt32)(Int32)up.ArcIndex,
propID, data, dataSize, propType);
{
/*
if (!up.NewData)
return E_FAIL;
*/
if (up.IsAnti)
return S_OK;
#if defined(_WIN32) && !defined(UNDER_CE)
const CDirItem &di = DirItems->Items[(unsigned)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[(unsigned)di.SecureIndex];
*data = buf;
*dataSize = (UInt32)buf.Size();
*propType = NPropDataType::kRaw;
}
else
#endif
if (propID == kpidNtReparse)
{
if (!StoreSymLinks)
return S_OK;
#if defined(_WIN32) && !defined(UNDER_CE)
// we use ReparseData2 instead of ReparseData for WIM format
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;
}
#if defined(_WIN32) && !defined(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 += ".." STRING_PATH_SEPARATOR;
for (k = i; k < partsTo.Size(); k++)
{
if (k != i)
s.Add_PathSepar();
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 !defined(UNDER_CE)
if (up.DirIndex >= 0)
{
const CDirItem &di = DirItems->Items[(unsigned)up.DirIndex];
#ifdef _WIN32
// if (di.IsDir())
{
CReparseAttr attr;
if (attr.Parse(di.ReparseData, di.ReparseData.Size()))
{
UString simpleName = attr.GetPath();
if (!attr.IsSymLink_WSL() && attr.IsRelative_Win())
prop = simpleName;
else
{
const FString phyPath = DirItems->GetPhyPath((unsigned)up.DirIndex);
FString fullPath;
if (NDir::MyGetFullPathName(phyPath, fullPath))
{
prop = GetRelativePath(simpleName, fs2us(fullPath));
}
}
prop.Detach(value);
return S_OK;
}
}
#else // _WIN32
if (di.ReparseData.Size() != 0)
{
AString utf;
utf.SetFrom_CalcLen((const char *)(const Byte *)di.ReparseData, (unsigned)di.ReparseData.Size());
UString us;
if (ConvertUTF8ToUnicode(utf, us))
{
prop = us;
prop.Detach(value);
return S_OK;
}
}
#endif // _WIN32
}
#endif // !defined(UNDER_CE)
}
else if (propID == kpidHardLink)
{
if (index == _hardIndex_From)
{
const CKeyKeyValPair &pair = _map[_hardIndex_To];
const CUpdatePair2 &up2 = (*UpdatePairs)[pair.Value];
prop = DirItems->GetLogPath((unsigned)up2.DirIndex);
prop.Detach(value);
return S_OK;
}
if (up.DirIndex >= 0)
{
prop.Detach(value);
return S_OK;
}
}
}
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)[(unsigned)up.NewNameIndex];
else if (propID == kpidComment
&& CommentIndex >= 0
&& (unsigned)CommentIndex == index
&& Comment)
prop = *Comment;
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)[(unsigned)up.ArcIndex].IndexInServer : (UInt32)(Int32)up.ArcIndex, propID, value);
else if (up.ExistOnDisk())
{
const CDirItem &di = DirItems->Items[(unsigned)up.DirIndex];
switch (propID)
{
case kpidPath: prop = DirItems->GetLogPath((unsigned)up.DirIndex); break;
case kpidIsDir: prop = di.IsDir(); break;
case kpidSize: prop = di.IsDir() ? (UInt64)0 : di.Size; break;
case kpidAttrib: prop = di.Attrib; break;
case kpidCTime: prop = di.CTime; break;
case kpidATime: prop = di.ATime; break;
case kpidMTime: prop = di.MTime; break;
case kpidIsAltStream: prop = di.IsAltStream; break;
#if defined(_WIN32) && !defined(UNDER_CE)
// case kpidShortName: prop = di.ShortName; break;
#endif
case kpidPosixAttrib:
{
#ifdef _WIN32
prop = di.GetPosixAttrib();
#else
if (di.Attrib & FILE_ATTRIBUTE_UNIX_EXTENSION)
prop = (UInt32)(di.Attrib >> 16);
#endif
break;
}
}
}
prop.Detach(value);
return S_OK;
COM_TRY_END
}
#ifndef _7ZIP_ST
static NSynchronization::CCriticalSection CS;
#endif
STDMETHODIMP CArchiveUpdateCallback::GetStream2(UInt32 index, ISequentialInStream **inStream, UInt32 mode)
{
COM_TRY_BEGIN
*inStream = NULL;
const CUpdatePair2 &up = (*UpdatePairs)[index];
if (!up.NewData)
return E_FAIL;
RINOK(Callback->CheckBreak());
// RINOK(Callback->Finalize());
bool isDir = IsDir(up);
if (up.IsAnti)
{
UString name;
if (up.ArcIndex >= 0)
name = (*ArcItems)[(unsigned)up.ArcIndex].Name;
else if (up.DirIndex >= 0)
name = DirItems->GetLogPath((unsigned)up.DirIndex);
RINOK(Callback->GetStream(name, isDir, true, mode));
/* 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;
}
RINOK(Callback->GetStream(DirItems->GetLogPath((unsigned)up.DirIndex), isDir, false, mode));
if (isDir)
return S_OK;
if (StdInMode)
{
if (mode != NUpdateNotifyOp::kAdd &&
mode != NUpdateNotifyOp::kUpdate)
return S_OK;
CStdInFileStream *inStreamSpec = new CStdInFileStream;
CMyComPtr<ISequentialInStream> inStreamLoc(inStreamSpec);
*inStream = inStreamLoc.Detach();
}
else
{
#if !defined(UNDER_CE)
const CDirItem &di = DirItems->Items[(unsigned)up.DirIndex];
if (di.AreReparseData())
{
/*
// we still need DeviceIoControlOut() instead of Read
if (!inStreamSpec->File.OpenReparse(path))
{
return Callback->OpenFileError(path, ::GetLastError());
}
*/
// 20.03: we use Reparse Data instead of real data
CBufInStream *inStreamSpec = new CBufInStream();
CMyComPtr<ISequentialInStream> inStreamLoc = inStreamSpec;
inStreamSpec->Init(di.ReparseData, di.ReparseData.Size());
*inStream = inStreamLoc.Detach();
return S_OK;
}
#endif // !defined(UNDER_CE)
CInFileStream *inStreamSpec = new CInFileStream;
CMyComPtr<ISequentialInStream> inStreamLoc(inStreamSpec);
inStreamSpec->SupportHardLinks = StoreHardLinks;
inStreamSpec->File.PreserveATime = PreserveATime;
const FString path = DirItems->GetPhyPath((unsigned)up.DirIndex);
_openFiles_Indexes.Add(index);
_openFiles_Paths.Add(path);
/* 21.02 : we set Callback/CallbackRef after _openFiles_Indexes adding
for correct working if exception was raised in GetPhyPath */
inStreamSpec->Callback = this;
inStreamSpec->CallbackRef = index;
if (!inStreamSpec->OpenShared(path, ShareForWrite))
{
DWORD error = ::GetLastError();
HRESULT hres = Callback->OpenFileError(path, error);
if (StopAfterOpenError)
if (hres == S_OK || hres == S_FALSE)
return HRESULT_FROM_WIN32(error);
return hres;
}
// #if defined(USE_WIN_FILE) || !defined(_WIN32)
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)
{
#ifndef _7ZIP_ST
NSynchronization::CCriticalSectionLock lock(CS);
#endif
ProcessedItemsStatuses[(unsigned)up.DirIndex] = 1;
}
*inStream = inStreamLoc.Detach();
}
return S_OK;
COM_TRY_END
}
STDMETHODIMP CArchiveUpdateCallback::SetOperationResult(Int32 opRes)
{
COM_TRY_BEGIN
return Callback->SetOperationResult(opRes);
COM_TRY_END
}
STDMETHODIMP CArchiveUpdateCallback::GetStream(UInt32 index, ISequentialInStream **inStream)
{
COM_TRY_BEGIN
return GetStream2(index, inStream,
(*UpdatePairs)[index].ArcIndex < 0 ?
NUpdateNotifyOp::kAdd :
NUpdateNotifyOp::kUpdate);
COM_TRY_END
}
STDMETHODIMP CArchiveUpdateCallback::ReportOperation(UInt32 indexType, UInt32 index, UInt32 op)
{
COM_TRY_BEGIN
bool isDir = false;
if (indexType == NArchive::NEventIndexType::kOutArcIndex)
{
UString name;
if (index != (UInt32)(Int32)-1)
{
const CUpdatePair2 &up = (*UpdatePairs)[index];
if (up.ExistOnDisk())
{
name = DirItems->GetLogPath((unsigned)up.DirIndex);
isDir = DirItems->Items[(unsigned)up.DirIndex].IsDir();
}
}
return Callback->ReportUpdateOpeartion(op, name.IsEmpty() ? NULL : name.Ptr(), isDir);
}
wchar_t temp[16];
UString s2;
const wchar_t *s = NULL;
if (indexType == NArchive::NEventIndexType::kInArcIndex)
{
if (index != (UInt32)(Int32)-1)
{
if (ArcItems)
{
const CArcItem &ai = (*ArcItems)[index];
s = ai.Name;
isDir = ai.IsDir;
}
else if (Arc)
{
RINOK(Arc->GetItemPath(index, s2));
s = s2;
RINOK(Archive_IsItem_Dir(Arc->Archive, index, isDir));
}
}
}
else if (indexType == NArchive::NEventIndexType::kBlockIndex)
{
temp[0] = '#';
ConvertUInt32ToString(index, temp + 1);
s = temp;
}
if (!s)
s = L"";
return Callback->ReportUpdateOpeartion(op, s, isDir);
COM_TRY_END
}
STDMETHODIMP CArchiveUpdateCallback::ReportExtractResult(UInt32 indexType, UInt32 index, Int32 opRes)
{
COM_TRY_BEGIN
bool isEncrypted = false;
wchar_t temp[16];
UString s2;
const wchar_t *s = NULL;
if (indexType == NArchive::NEventIndexType::kOutArcIndex)
{
/*
UString name;
if (index != (UInt32)(Int32)-1)
{
const CUpdatePair2 &up = (*UpdatePairs)[index];
if (up.ExistOnDisk())
{
s2 = DirItems->GetLogPath(up.DirIndex);
s = s2;
}
}
*/
return E_FAIL;
}
if (indexType == NArchive::NEventIndexType::kInArcIndex)
{
if (index != (UInt32)(Int32)-1)
{
if (ArcItems)
s = (*ArcItems)[index].Name;
else if (Arc)
{
RINOK(Arc->GetItemPath(index, s2));
s = s2;
}
if (Archive)
{
RINOK(Archive_GetItemBoolProp(Archive, index, kpidEncrypted, isEncrypted));
}
}
}
else if (indexType == NArchive::NEventIndexType::kBlockIndex)
{
temp[0] = '#';
ConvertUInt32ToString(index, temp + 1);
s = temp;
}
return Callback->ReportExtractResult(opRes, BoolToInt(isEncrypted), s);
COM_TRY_END
}
STDMETHODIMP CArchiveUpdateCallback::GetVolumeSize(UInt32 index, UInt64 *size)
{
if (VolumesSizes.Size() == 0)
return S_FALSE;
if (index >= (UInt32)VolumesSizes.Size())
index = VolumesSizes.Size() - 1;
*size = VolumesSizes[index];
return S_OK;
}
STDMETHODIMP CArchiveUpdateCallback::GetVolumeStream(UInt32 index, ISequentialOutStream **volumeStream)
{
COM_TRY_BEGIN
char temp[16];
ConvertUInt32ToString(index + 1, temp);
FString res (temp);
while (res.Len() < 2)
res.InsertAtFront(FTEXT('0'));
FString fileName = VolName;
fileName += '.';
fileName += res;
fileName += VolExt;
COutFileStream *streamSpec = new COutFileStream;
CMyComPtr<ISequentialOutStream> streamLoc(streamSpec);
if (!streamSpec->Create(fileName, false))
return GetLastError_noZero_HRESULT();
*volumeStream = streamLoc.Detach();
return S_OK;
COM_TRY_END
}
STDMETHODIMP CArchiveUpdateCallback::CryptoGetTextPassword2(Int32 *passwordIsDefined, BSTR *password)
{
COM_TRY_BEGIN
return Callback->CryptoGetTextPassword2(passwordIsDefined, password);
COM_TRY_END
}
STDMETHODIMP CArchiveUpdateCallback::CryptoGetTextPassword(BSTR *password)
{
COM_TRY_BEGIN
return Callback->CryptoGetTextPassword(password);
COM_TRY_END
}
HRESULT CArchiveUpdateCallback::InFileStream_On_Error(UINT_PTR val, DWORD error)
{
#ifdef _WIN32 // FIX IT !!!
// why did we check only for ERROR_LOCK_VIOLATION ?
// if (error == ERROR_LOCK_VIOLATION)
#endif
{
MT_LOCK
UInt32 index = (UInt32)val;
FOR_VECTOR(i, _openFiles_Indexes)
{
if (_openFiles_Indexes[i] == index)
{
RINOK(Callback->ReadingFileError(_openFiles_Paths[i], error));
break;
}
}
}
return HRESULT_FROM_WIN32(error);
}
void CArchiveUpdateCallback::InFileStream_On_Destroy(UINT_PTR val)
{
{
MT_LOCK
UInt32 index = (UInt32)val;
FOR_VECTOR(i, _openFiles_Indexes)
{
if (_openFiles_Indexes[i] == index)
{
_openFiles_Indexes.Delete(i);
_openFiles_Paths.Delete(i);
return;
}
}
}
/* 21.02 : this function can be called in destructor.
And destructor can be called after some exception.
If we don't want to throw exception in desctructors or after another exceptions,
we must disable the code below that raises new exception.
*/
// throw 20141125;
}

View File

@@ -0,0 +1,163 @@
// UpdateCallback.h
#ifndef __UPDATE_CALLBACK_H
#define __UPDATE_CALLBACK_H
#include "../../../Common/MyCom.h"
#include "../../Common/FileStreams.h"
#include "../../IPassword.h"
#include "../../ICoder.h"
#include "../Common/UpdatePair.h"
#include "../Common/UpdateProduce.h"
#include "OpenArchive.h"
struct CArcToDoStat
{
CDirItemsStat2 NewData;
CDirItemsStat2 OldData;
CDirItemsStat2 DeleteData;
UInt64 Get_NumDataItems_Total() const
{
return NewData.Get_NumDataItems2() + OldData.Get_NumDataItems2();
}
};
#define INTERFACE_IUpdateCallbackUI(x) \
virtual HRESULT WriteSfx(const wchar_t *name, UInt64 size) x; \
virtual HRESULT SetTotal(UInt64 size) x; \
virtual HRESULT SetCompleted(const UInt64 *completeValue) x; \
virtual HRESULT SetRatioInfo(const UInt64 *inSize, const UInt64 *outSize) x; \
virtual HRESULT CheckBreak() x; \
/* virtual HRESULT Finalize() x; */ \
virtual HRESULT SetNumItems(const CArcToDoStat &stat) x; \
virtual HRESULT GetStream(const wchar_t *name, bool isDir, bool isAnti, UInt32 mode) x; \
virtual HRESULT OpenFileError(const FString &path, DWORD systemError) x; \
virtual HRESULT ReadingFileError(const FString &path, DWORD systemError) x; \
virtual HRESULT SetOperationResult(Int32 opRes) x; \
virtual HRESULT ReportExtractResult(Int32 opRes, Int32 isEncrypted, const wchar_t *name) x; \
virtual HRESULT ReportUpdateOpeartion(UInt32 op, const wchar_t *name, bool isDir) x; \
/* virtual HRESULT SetPassword(const UString &password) x; */ \
virtual HRESULT CryptoGetTextPassword2(Int32 *passwordIsDefined, BSTR *password) x; \
virtual HRESULT CryptoGetTextPassword(BSTR *password) x; \
virtual HRESULT ShowDeleteFile(const wchar_t *name, bool isDir) x; \
/* virtual HRESULT CloseProgress() { return S_OK; } */
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 IArchiveUpdateCallbackFile,
public IArchiveExtractCallbackMessage,
public IArchiveGetRawProps,
public IArchiveGetRootProps,
public ICryptoGetTextPassword2,
public ICryptoGetTextPassword,
public ICompressProgressInfo,
public IInFileStream_Callback,
public CMyUnknownImp
{
#if defined(_WIN32) && !defined(UNDER_CE)
bool _saclEnabled;
#endif
CRecordVector<CKeyKeyValPair> _map;
UInt32 _hardIndex_From;
UInt32 _hardIndex_To;
public:
MY_QUERYINTERFACE_BEGIN2(IArchiveUpdateCallback2)
MY_QUERYINTERFACE_ENTRY(IArchiveUpdateCallbackFile)
MY_QUERYINTERFACE_ENTRY(IArchiveExtractCallbackMessage)
MY_QUERYINTERFACE_ENTRY(IArchiveGetRawProps)
MY_QUERYINTERFACE_ENTRY(IArchiveGetRootProps)
MY_QUERYINTERFACE_ENTRY(ICryptoGetTextPassword2)
MY_QUERYINTERFACE_ENTRY(ICryptoGetTextPassword)
MY_QUERYINTERFACE_ENTRY(ICompressProgressInfo)
MY_QUERYINTERFACE_END
MY_ADDREF_RELEASE
STDMETHOD(SetRatioInfo)(const UInt64 *inSize, const UInt64 *outSize);
INTERFACE_IArchiveUpdateCallback2(;)
INTERFACE_IArchiveUpdateCallbackFile(;)
INTERFACE_IArchiveExtractCallbackMessage(;)
INTERFACE_IArchiveGetRawProps(;)
INTERFACE_IArchiveGetRootProps(;)
STDMETHOD(CryptoGetTextPassword2)(Int32 *passwordIsDefined, BSTR *password);
STDMETHOD(CryptoGetTextPassword)(BSTR *password);
CRecordVector<UInt32> _openFiles_Indexes;
FStringVector _openFiles_Paths;
bool AreAllFilesClosed() const { return _openFiles_Indexes.IsEmpty(); }
virtual HRESULT InFileStream_On_Error(UINT_PTR val, DWORD error);
virtual void InFileStream_On_Destroy(UINT_PTR val);
CRecordVector<UInt64> VolumesSizes;
FString VolName;
FString VolExt;
IUpdateCallbackUI *Callback;
const CDirItems *DirItems;
const CDirItem *ParentDirItem;
const CArc *Arc;
CMyComPtr<IInArchive> Archive;
const CObjectVector<CArcItem> *ArcItems;
const CRecordVector<CUpdatePair2> *UpdatePairs;
const UStringVector *NewNames;
int CommentIndex;
const UString *Comment;
bool PreserveATime;
bool ShareForWrite;
bool StopAfterOpenError;
bool StdInMode;
bool KeepOriginalItemNames;
bool StoreNtSecurity;
bool StoreHardLinks;
bool StoreSymLinks;
Byte *ProcessedItemsStatuses;
CArchiveUpdateCallback();
bool IsDir(const CUpdatePair2 &up) const
{
if (up.DirIndex >= 0)
return DirItems->Items[(unsigned)up.DirIndex].IsDir();
else if (up.ArcIndex >= 0)
return (*ArcItems)[(unsigned)up.ArcIndex].IsDir;
return false;
}
};
#endif

View File

@@ -0,0 +1,235 @@
// UpdatePair.cpp
#include "StdAfx.h"
#include <time.h>
#include "../../../Common/Wildcard.h"
#include "../../../Windows/TimeUtils.h"
#include "SortUtils.h"
#include "UpdatePair.h"
using namespace NWindows;
using namespace NTime;
static int MyCompareTime(NFileTimeType::EEnum fileTimeType, const FILETIME &time1, const FILETIME &time2)
{
switch (fileTimeType)
{
case NFileTimeType::kWindows:
return ::CompareFileTime(&time1, &time2);
case NFileTimeType::kUnix:
{
UInt32 unixTime1, unixTime2;
FileTimeToUnixTime(time1, unixTime1);
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 char * const k_Duplicate_inArc_Message = "Duplicate filename in archive:";
static const char * const k_Duplicate_inDir_Message = "Duplicate filename on disk:";
static const char * const k_NotCensoredCollision_Message = "Internal file name collision (file on disk, file in archive):";
MY_ATTR_NORETURN
static
void ThrowError(const char *message, const UString &s1, const UString &s2)
{
UString m (message);
m.Add_LF(); m += s1;
m.Add_LF(); m += s2;
throw m;
}
static int CompareArcItemsBase(const CArcItem &ai1, const CArcItem &ai2)
{
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(
const CDirItems &dirItems,
const CObjectVector<CArcItem> &arcItems,
NFileTimeType::EEnum fileTimeType,
CRecordVector<CUpdatePair> &updatePairs)
{
CUIntVector dirIndices, arcIndices;
unsigned numDirItems = dirItems.Items.Size();
unsigned numArcItems = arcItems.Size();
CIntArr duplicatedArcItem(numArcItems);
{
int *vals = &duplicatedArcItem[0];
for (unsigned i = 0; i < numArcItems; i++)
vals[i] = 0;
}
{
arcIndices.ClearAndSetSize(numArcItems);
if (numArcItems != 0)
{
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.ClearAndReserve(numDirItems);
unsigned i;
for (i = 0; i < numDirItems; i++)
dirNames.AddInReserved(dirItems.GetLogPath(i));
SortFileNames(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);
}
}
unsigned dirIndex = 0;
unsigned arcIndex = 0;
int prevHostFile = -1;
const UString *prevHostName = NULL;
while (dirIndex < numDirItems || arcIndex < numArcItems)
{
CUpdatePair pair;
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 = (int)dirIndices[dirIndex];
di = &dirItems.Items[(unsigned)dirIndex2];
}
if (arcIndex < numArcItems)
{
arcIndex2 = (int)arcIndices[arcIndex];
ai = &arcItems[(unsigned)arcIndex2];
compareResult = 1;
if (dirIndex < numDirItems)
{
compareResult = CompareFileNames(dirNames[(unsigned)dirIndex2], ai->Name);
if (compareResult == 0)
{
if (di->IsDir() != ai->IsDir)
compareResult = (ai->IsDir ? 1 : -1);
}
}
}
if (compareResult < 0)
{
name = &dirNames[(unsigned)dirIndex2];
pair.State = NUpdateArchive::NPairState::kOnlyOnDisk;
pair.DirIndex = dirIndex2;
dirIndex++;
}
else if (compareResult > 0)
{
name = &ai->Name;
pair.State = ai->Censored ?
NUpdateArchive::NPairState::kOnlyInArchive:
NUpdateArchive::NPairState::kNotMasked;
pair.ArcIndex = arcIndex2;
arcIndex++;
}
else
{
int dupl = duplicatedArcItem[arcIndex];
if (dupl != 0)
ThrowError(k_Duplicate_inArc_Message, ai->Name, arcItems[arcIndices[(unsigned)((int)arcIndex + dupl)]].Name);
name = &dirNames[(unsigned)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)
{
case -1: pair.State = NUpdateArchive::NPairState::kNewInArchive; break;
case 1: pair.State = NUpdateArchive::NPairState::kOldInArchive; break;
default:
pair.State = (ai->SizeDefined && di->Size == ai->Size) ?
NUpdateArchive::NPairState::kSameFiles :
NUpdateArchive::NPairState::kUnknowNewerFiles;
}
dirIndex++;
arcIndex++;
}
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 = (int)updatePairs.Size();
prevHostName = name;
}
updatePairs.Add(pair);
}
updatePairs.ReserveDown();
}

View File

@@ -0,0 +1,27 @@
// UpdatePair.h
#ifndef __UPDATE_PAIR_H
#define __UPDATE_PAIR_H
#include "DirItem.h"
#include "UpdateAction.h"
#include "../../Archive/IArchive.h"
struct CUpdatePair
{
NUpdateArchive::NPairState::EEnum State;
int ArcIndex;
int DirIndex;
int HostIndex; // >= 0 for alt streams only, contains index of host pair
CUpdatePair(): ArcIndex(-1), DirIndex(-1), HostIndex(-1) {}
};
void GetUpdatePairInfoList(
const CDirItems &dirItems,
const CObjectVector<CArcItem> &arcItems,
NFileTimeType::EEnum fileTimeType,
CRecordVector<CUpdatePair> &updatePairs);
#endif

View File

@@ -0,0 +1,70 @@
// UpdateProduce.cpp
#include "StdAfx.h"
#include "UpdateProduce.h"
using namespace NUpdateArchive;
static const char * const kUpdateActionSetCollision = "Internal collision in update action set";
void UpdateProduce(
const CRecordVector<CUpdatePair> &updatePairs,
const CActionSet &actionSet,
CRecordVector<CUpdatePair2> &operationChain,
IUpdateProduceCallback *callback)
{
FOR_VECTOR (i, updatePairs)
{
const CUpdatePair &pair = updatePairs[i];
CUpdatePair2 up2;
up2.DirIndex = pair.DirIndex;
up2.ArcIndex = pair.ArcIndex;
up2.NewData = up2.NewProps = true;
up2.UseArcProps = false;
switch (actionSet.StateActions[(unsigned)pair.State])
{
case NPairAction::kIgnore:
if (pair.ArcIndex >= 0 && callback)
callback->ShowDeleteFile((unsigned)pair.ArcIndex);
continue;
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[(unsigned)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);
}
operationChain.ReserveDown();
}

View File

@@ -0,0 +1,55 @@
// UpdateProduce.h
#ifndef __UPDATE_PRODUCE_H
#define __UPDATE_PRODUCE_H
#include "UpdatePair.h"
struct CUpdatePair2
{
bool NewData;
bool NewProps;
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(unsigned arcIndex) // int
{
NewData = NewProps = false;
UseArcProps = true;
IsAnti = false;
ArcIndex = (int)arcIndex;
}
bool ExistOnDisk() const { return DirIndex != -1; }
bool ExistInArchive() const { return ArcIndex != -1; }
CUpdatePair2():
NewData(false),
NewProps(false),
UseArcProps(false),
IsAnti(false),
DirIndex(-1),
ArcIndex(-1),
NewNameIndex(-1),
IsMainRenameItem(false)
{}
};
struct IUpdateProduceCallback
{
virtual HRESULT ShowDeleteFile(unsigned arcIndex) = 0;
};
void UpdateProduce(
const CRecordVector<CUpdatePair> &updatePairs,
const NUpdateArchive::CActionSet &actionSet,
CRecordVector<CUpdatePair2> &operationChain,
IUpdateProduceCallback *callback);
#endif

View File

@@ -0,0 +1,93 @@
// WorkDir.cpp
#include "StdAfx.h"
#include "../../../Common/StringConvert.h"
#include "../../../Common/Wildcard.h"
#include "../../../Windows/FileFind.h"
#include "../../../Windows/FileName.h"
#include "WorkDir.h"
using namespace NWindows;
using namespace NFile;
using namespace NDir;
FString GetWorkDir(const NWorkDir::CInfo &workDirInfo, const FString &path, FString &fileName)
{
NWorkDir::NMode::EEnum mode = workDirInfo.Mode;
#if defined(_WIN32) && !defined(UNDER_CE)
if (workDirInfo.ForRemovableOnly)
{
mode = NWorkDir::NMode::kCurrent;
FString prefix = path.Left(3);
if (prefix[1] == FTEXT(':') && prefix[2] == FTEXT('\\'))
{
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
int pos = path.ReverseFind_PathSepar() + 1;
fileName = path.Ptr((unsigned)pos);
switch (mode)
{
case NWorkDir::NMode::kCurrent:
{
return path.Left((unsigned)pos);
}
case NWorkDir::NMode::kSpecified:
{
FString tempDir = workDirInfo.Path;
NName::NormalizeDirPathPrefix(tempDir);
return tempDir;
}
default:
{
FString tempDir;
if (!MyGetTempPath(tempDir))
throw 141717;
return tempDir;
}
}
}
HRESULT CWorkDirTempFile::CreateTempFile(const FString &originalPath)
{
NWorkDir::CInfo workDirInfo;
workDirInfo.Load();
FString namePart;
FString workDir = GetWorkDir(workDirInfo, originalPath, namePart);
CreateComplexDir(workDir);
CTempFile tempFile;
_outStreamSpec = new COutFileStream;
OutStream = _outStreamSpec;
if (!_tempFile.Create(workDir + namePart, &_outStreamSpec->File))
{
return GetLastError_noZero_HRESULT();
}
_originalPath = originalPath;
return S_OK;
}
HRESULT CWorkDirTempFile::MoveToOriginal(bool deleteOriginal)
{
OutStream.Release();
if (!_tempFile.MoveTo(_originalPath, deleteOriginal))
{
return GetLastError_noZero_HRESULT();
}
return S_OK;
}

View File

@@ -0,0 +1,26 @@
// WorkDir.h
#ifndef __WORK_DIR_H
#define __WORK_DIR_H
#include "../../../Windows/FileDir.h"
#include "../../Common/FileStreams.h"
#include "ZipRegistry.h"
FString GetWorkDir(const NWorkDir::CInfo &workDirInfo, const FString &path, FString &fileName);
class CWorkDirTempFile
{
FString _originalPath;
NWindows::NFile::NDir::CTempFile _tempFile;
COutFileStream *_outStreamSpec;
public:
CMyComPtr<IOutStream> OutStream;
HRESULT CreateTempFile(const FString &originalPath);
HRESULT MoveToOriginal(bool deleteOriginal);
};
#endif

View File

@@ -0,0 +1,130 @@
// ZipRegistry.h
#ifndef __ZIP_REGISTRY_H
#define __ZIP_REGISTRY_H
#include "../../../Common/MyTypes.h"
#include "../../../Common/MyString.h"
#include "ExtractMode.h"
namespace NExtract
{
struct CInfo
{
NPathMode::EEnum PathMode;
NOverwriteMode::EEnum OverwriteMode;
bool PathMode_Force;
bool OverwriteMode_Force;
CBoolPair SplitDest;
CBoolPair ElimDup;
// CBoolPair AltStreams;
CBoolPair NtSecurity;
CBoolPair ShowPassword;
UStringVector Paths;
void Save() const;
void Load();
};
void Save_ShowPassword(bool showPassword);
bool Read_ShowPassword();
}
namespace NCompression
{
struct CFormatOptions
{
UInt32 Level;
UInt32 Dictionary;
UInt32 Order;
UInt32 BlockLogSize;
UInt32 NumThreads;
CSysString FormatID;
UString Method;
UString Options;
UString EncryptionMethod;
void Reset_BlockLogSize()
{
BlockLogSize = (UInt32)(Int32)-1;
}
void ResetForLevelChange()
{
BlockLogSize = NumThreads = Level = Dictionary = Order = (UInt32)(Int32)-1;
Method.Empty();
// Options.Empty();
// EncryptionMethod.Empty();
}
CFormatOptions() { ResetForLevelChange(); }
};
struct CInfo
{
UInt32 Level;
bool ShowPassword;
bool EncryptHeaders;
UString ArcType;
UStringVector ArcPaths;
CObjectVector<CFormatOptions> Formats;
CBoolPair NtSecurity;
CBoolPair AltStreams;
CBoolPair HardLinks;
CBoolPair SymLinks;
void Save() const;
void Load();
};
}
namespace NWorkDir
{
namespace NMode
{
enum EEnum
{
kSystem,
kCurrent,
kSpecified
};
}
struct CInfo
{
NMode::EEnum Mode;
FString Path;
bool ForRemovableOnly;
void SetForRemovableOnlyDefault() { ForRemovableOnly = true; }
void SetDefault()
{
Mode = NMode::kSystem;
Path.Empty();
SetForRemovableOnlyDefault();
}
void Save() const;
void Load();
};
}
struct CContextMenuInfo
{
CBoolPair Cascaded;
CBoolPair MenuIcons;
CBoolPair ElimDup;
bool Flags_Def;
UInt32 Flags;
void Save() const;
void Load();
};
#endif

View File

@@ -0,0 +1,41 @@
// BenchCon.cpp
#include "StdAfx.h"
#include "../Common/Bench.h"
#include "BenchCon.h"
#include "ConsoleClose.h"
struct CPrintBenchCallback: public IBenchPrintCallback
{
FILE *_file;
void Print(const char *s);
void NewLine();
HRESULT CheckBreak();
};
void CPrintBenchCallback::Print(const char *s)
{
fputs(s, _file);
}
void CPrintBenchCallback::NewLine()
{
fputc('\n', _file);
}
HRESULT CPrintBenchCallback::CheckBreak()
{
return NConsoleClose::TestBreakSignal() ? E_ABORT: S_OK;
}
HRESULT BenchCon(DECL_EXTERNAL_CODECS_LOC_VARS
const CObjectVector<CProperty> &props, UInt32 numIterations, FILE *f)
{
CPrintBenchCallback callback;
callback._file = f;
return Bench(EXTERNAL_CODECS_LOC_VARS
&callback, NULL, props, numIterations, true);
}

View File

@@ -0,0 +1,14 @@
// BenchCon.h
#ifndef __BENCH_CON_H
#define __BENCH_CON_H
#include <stdio.h>
#include "../../Common/CreateCoder.h"
#include "../../UI/Common/Property.h"
HRESULT BenchCon(DECL_EXTERNAL_CODECS_LOC_VARS
const CObjectVector<CProperty> &props, UInt32 numIterations, FILE *f);
#endif

View File

@@ -0,0 +1,43 @@
MY_CONSOLE = 1
!IFNDEF UNDER_CE
CFLAGS = $(CFLAGS) -DWIN_LONG_PATH -D_7ZIP_LARGE_PAGES -DSUPPORT_DEVICE_FILE
!ENDIF
CONSOLE_OBJS = \
$O\BenchCon.obj \
$O\ConsoleClose.obj \
$O\ExtractCallbackConsole.obj \
$O\HashCon.obj \
$O\List.obj \
$O\Main.obj \
$O\MainAr.obj \
$O\OpenCallbackConsole.obj \
$O\PercentPrinter.obj \
$O\UpdateCallbackConsole.obj \
$O\UserInputUtils.obj \
UI_COMMON_OBJS = \
$O\ArchiveCommandLine.obj \
$O\ArchiveExtractCallback.obj \
$O\ArchiveOpenCallback.obj \
$O\Bench.obj \
$O\DefaultName.obj \
$O\EnumDirItems.obj \
$O\Extract.obj \
$O\ExtractingFilePath.obj \
$O\HashCalc.obj \
$O\LoadCodecs.obj \
$O\OpenArchive.obj \
$O\PropIDUtils.obj \
$O\SetProperties.obj \
$O\SortUtils.obj \
$O\TempFiles.obj \
$O\Update.obj \
$O\UpdateAction.obj \
$O\UpdateCallback.obj \
$O\UpdatePair.obj \
$O\UpdateProduce.obj \
C_OBJS = $(C_OBJS) \
$O\DllSecur.obj \

View File

@@ -0,0 +1,13 @@
<assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0">
<assemblyIdentity version="1.0.0.0" processorArchitecture="*" name="7z" type="win32"></assemblyIdentity>
<trustInfo xmlns="urn:schemas-microsoft-com:asm.v2">
<security><requestedPrivileges><requestedExecutionLevel level="asInvoker" uiAccess="false">
</requestedExecutionLevel></requestedPrivileges></security></trustInfo>
<compatibility xmlns="urn:schemas-microsoft-com:compatibility.v1"><application>
<!-- Vista --> <supportedOS Id="{e2011457-1546-43c5-a5fe-008deee3d3f0}"/>
<!-- Win 7 --> <supportedOS Id="{35138b9a-5d96-4fbd-8e2d-a2440225f93a}"/>
<!-- Win 8 --> <supportedOS Id="{4a2f28e3-53b9-4441-ba9c-d69d4a4a6e38}"/>
<!-- Win 8.1 --> <supportedOS Id="{1f676c76-80e1-4239-95bb-83d0f6d0da78}"/>
<!-- Win 10 --> <supportedOS Id="{8e0f7a12-bfb3-4fe8-b9a5-48fd50a15a9a}"/>
</application></compatibility>
</assembly>

View File

@@ -0,0 +1,100 @@
// ConsoleClose.cpp
#include "StdAfx.h"
#include "ConsoleClose.h"
#ifndef UNDER_CE
#ifdef _WIN32
#include "../../../Common/MyWindows.h"
#else
#include <stdlib.h>
#include <signal.h>
#endif
namespace NConsoleClose {
unsigned g_BreakCounter = 0;
static const unsigned kBreakAbortThreshold = 2;
#ifdef _WIN32
static BOOL WINAPI HandlerRoutine(DWORD ctrlType)
{
if (ctrlType == CTRL_LOGOFF_EVENT)
{
// printf("\nCTRL_LOGOFF_EVENT\n");
return TRUE;
}
g_BreakCounter++;
if (g_BreakCounter < kBreakAbortThreshold)
return TRUE;
return FALSE;
/*
switch (ctrlType)
{
case CTRL_C_EVENT:
case CTRL_BREAK_EVENT:
if (g_BreakCounter < kBreakAbortThreshold)
return TRUE;
}
return FALSE;
*/
}
CCtrlHandlerSetter::CCtrlHandlerSetter()
{
if (!SetConsoleCtrlHandler(HandlerRoutine, TRUE))
throw "SetConsoleCtrlHandler fails";
}
CCtrlHandlerSetter::~CCtrlHandlerSetter()
{
if (!SetConsoleCtrlHandler(HandlerRoutine, FALSE))
{
// warning for throw in destructor.
// throw "SetConsoleCtrlHandler fails";
}
}
#else // _WIN32
static void HandlerRoutine(int)
{
g_BreakCounter++;
if (g_BreakCounter < kBreakAbortThreshold)
return;
exit(EXIT_FAILURE);
}
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}
}
#endif // _WIN32
/*
void CheckCtrlBreak()
{
if (TestBreakSignal())
throw CCtrlBreakException();
}
*/
}
#endif

View File

@@ -0,0 +1,39 @@
// ConsoleClose.h
#ifndef __CONSOLE_CLOSE_H
#define __CONSOLE_CLOSE_H
namespace NConsoleClose {
class CCtrlBreakException {};
#ifdef UNDER_CE
inline bool TestBreakSignal() { return false; }
struct CCtrlHandlerSetter {};
#else
extern unsigned g_BreakCounter;
inline bool TestBreakSignal()
{
return (g_BreakCounter != 0);
}
class CCtrlHandlerSetter
{
#ifndef _WIN32
void (*memo_sig_int)(int);
void (*memo_sig_term)(int);
#endif
public:
CCtrlHandlerSetter();
virtual ~CCtrlHandlerSetter();
};
#endif
}
#endif

View File

@@ -0,0 +1,834 @@
// ExtractCallbackConsole.cpp
#include "StdAfx.h"
#include "../../../Common/IntToString.h"
#include "../../../Common/Wildcard.h"
#include "../../../Windows/FileDir.h"
#include "../../../Windows/FileFind.h"
#include "../../../Windows/TimeUtils.h"
#include "../../../Windows/ErrorMsg.h"
#include "../../../Windows/PropVariantConv.h"
#ifndef _7ZIP_ST
#include "../../../Windows/Synchronization.h"
#endif
#include "../../Common/FilePathAutoRename.h"
#include "../Common/ExtractingFilePath.h"
#include "ConsoleClose.h"
#include "ExtractCallbackConsole.h"
#include "UserInputUtils.h"
using namespace NWindows;
using namespace NFile;
using namespace NDir;
static HRESULT CheckBreak2()
{
return NConsoleClose::TestBreakSignal() ? E_ABORT : S_OK;
}
static const char * const kError = "ERROR: ";
void CExtractScanConsole::StartScanning()
{
if (NeedPercents())
_percent.Command = "Scan";
}
HRESULT CExtractScanConsole::ScanProgress(const CDirItemsStat &st, const FString &path, bool /* isDir */)
{
if (NeedPercents())
{
_percent.Files = st.NumDirs + st.NumFiles;
_percent.Completed = st.GetTotalBytes();
_percent.FileName = fs2us(path);
_percent.Print();
}
return CheckBreak2();
}
HRESULT CExtractScanConsole::ScanError(const FString &path, DWORD systemError)
{
ClosePercentsAndFlush();
if (_se)
{
*_se << endl << kError << NError::MyFormatMessage(systemError) << endl;
_se->NormalizePrint_UString(fs2us(path));
*_se << endl << endl;
_se->Flush();
}
return HRESULT_FROM_WIN32(systemError);
}
void Print_UInt64_and_String(AString &s, UInt64 val, const char *name);
void Print_UInt64_and_String(AString &s, UInt64 val, const char *name)
{
char temp[32];
ConvertUInt64ToString(val, temp);
s += temp;
s.Add_Space();
s += name;
}
void PrintSize_bytes_Smart(AString &s, UInt64 val);
void PrintSize_bytes_Smart(AString &s, UInt64 val)
{
Print_UInt64_and_String(s, val, "bytes");
if (val == 0)
return;
unsigned numBits = 10;
char c = 'K';
char temp[4] = { 'K', 'i', 'B', 0 };
if (val >= ((UInt64)10 << 30)) { numBits = 30; c = 'G'; }
else if (val >= ((UInt64)10 << 20)) { numBits = 20; c = 'M'; }
temp[0] = c;
s += " (";
Print_UInt64_and_String(s, ((val + ((UInt64)1 << numBits) - 1) >> numBits), temp);
s += ')';
}
static void PrintSize_bytes_Smart_comma(AString &s, UInt64 val)
{
if (val == (UInt64)(Int64)-1)
return;
s += ", ";
PrintSize_bytes_Smart(s, val);
}
void Print_DirItemsStat(AString &s, const CDirItemsStat &st);
void Print_DirItemsStat(AString &s, const CDirItemsStat &st)
{
if (st.NumDirs != 0)
{
Print_UInt64_and_String(s, st.NumDirs, st.NumDirs == 1 ? "folder" : "folders");
s += ", ";
}
Print_UInt64_and_String(s, st.NumFiles, st.NumFiles == 1 ? "file" : "files");
PrintSize_bytes_Smart_comma(s, st.FilesSize);
if (st.NumAltStreams != 0)
{
s.Add_LF();
Print_UInt64_and_String(s, st.NumAltStreams, "alternate streams");
PrintSize_bytes_Smart_comma(s, st.AltStreamsSize);
}
}
void Print_DirItemsStat2(AString &s, const CDirItemsStat2 &st);
void Print_DirItemsStat2(AString &s, const CDirItemsStat2 &st)
{
Print_DirItemsStat(s, (CDirItemsStat &)st);
bool needLF = true;
if (st.Anti_NumDirs != 0)
{
if (needLF)
s.Add_LF();
needLF = false;
Print_UInt64_and_String(s, st.Anti_NumDirs, st.Anti_NumDirs == 1 ? "anti-folder" : "anti-folders");
}
if (st.Anti_NumFiles != 0)
{
if (needLF)
s.Add_LF();
else
s += ", ";
needLF = false;
Print_UInt64_and_String(s, st.Anti_NumFiles, st.Anti_NumFiles == 1 ? "anti-file" : "anti-files");
}
if (st.Anti_NumAltStreams != 0)
{
if (needLF)
s.Add_LF();
else
s += ", ";
needLF = false;
Print_UInt64_and_String(s, st.Anti_NumAltStreams, "anti-alternate-streams");
}
}
void CExtractScanConsole::PrintStat(const CDirItemsStat &st)
{
if (_so)
{
AString s;
Print_DirItemsStat(s, st);
*_so << s << endl;
}
}
#ifndef _7ZIP_ST
static NSynchronization::CCriticalSection g_CriticalSection;
#define MT_LOCK NSynchronization::CCriticalSectionLock lock(g_CriticalSection);
#else
#define MT_LOCK
#endif
static const char * const kTestString = "T";
static const char * const kExtractString = "-";
static const char * const kSkipString = ".";
// static const char * const kCantAutoRename = "cannot create file with auto name\n";
// static const char * const kCantRenameFile = "cannot rename existing file\n";
// static const char * const kCantDeleteOutputFile = "cannot delete output file ";
static const char * const kMemoryExceptionMessage = "Can't allocate required memory!";
static const char * const kExtracting = "Extracting archive: ";
static const char * const kTesting = "Testing archive: ";
static const char * const kEverythingIsOk = "Everything is Ok";
static const char * const kNoFiles = "No files to process";
static const char * const kUnsupportedMethod = "Unsupported Method";
static const char * const kCrcFailed = "CRC Failed";
static const char * const kCrcFailedEncrypted = "CRC Failed in encrypted file. Wrong password?";
static const char * const kDataError = "Data Error";
static const char * const kDataErrorEncrypted = "Data Error in encrypted file. Wrong password?";
static const char * const kUnavailableData = "Unavailable data";
static const char * const kUnexpectedEnd = "Unexpected end of data";
static const char * const kDataAfterEnd = "There are some data after the end of the payload data";
static const char * const kIsNotArc = "Is not archive";
static const char * const kHeadersError = "Headers Error";
static const char * const kWrongPassword = "Wrong password";
static const char * const k_ErrorFlagsMessages[] =
{
"Is not archive"
, "Headers Error"
, "Headers Error in encrypted archive. Wrong password?"
, "Unavailable start of archive"
, "Unconfirmed start of archive"
, "Unexpected end of archive"
, "There are data after the end of archive"
, "Unsupported method"
, "Unsupported feature"
, "Data Error"
, "CRC Error"
};
STDMETHODIMP CExtractCallbackConsole::SetTotal(UInt64 size)
{
MT_LOCK
if (NeedPercents())
{
_percent.Total = size;
_percent.Print();
}
return CheckBreak2();
}
STDMETHODIMP CExtractCallbackConsole::SetCompleted(const UInt64 *completeValue)
{
MT_LOCK
if (NeedPercents())
{
if (completeValue)
_percent.Completed = *completeValue;
_percent.Print();
}
return CheckBreak2();
}
static const char * const kTab = " ";
static void PrintFileInfo(CStdOutStream *_so, const wchar_t *path, const FILETIME *ft, const UInt64 *size)
{
*_so << kTab << "Path: ";
_so->NormalizePrint_wstr(path);
*_so << endl;
if (size && *size != (UInt64)(Int64)-1)
{
AString s;
PrintSize_bytes_Smart(s, *size);
*_so << kTab << "Size: " << s << endl;
}
if (ft)
{
char temp[64];
if (ConvertUtcFileTimeToString(*ft, temp, kTimestampPrintLevel_SEC))
*_so << kTab << "Modified: " << temp << endl;
}
}
STDMETHODIMP CExtractCallbackConsole::AskOverwrite(
const wchar_t *existName, const FILETIME *existTime, const UInt64 *existSize,
const wchar_t *newName, const FILETIME *newTime, const UInt64 *newSize,
Int32 *answer)
{
MT_LOCK
RINOK(CheckBreak2());
ClosePercentsAndFlush();
if (_so)
{
*_so << endl << "Would you like to replace the existing file:\n";
PrintFileInfo(_so, existName, existTime, existSize);
*_so << "with the file from archive:\n";
PrintFileInfo(_so, newName, newTime, newSize);
}
NUserAnswerMode::EEnum overwriteAnswer = ScanUserYesNoAllQuit(_so);
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;
case NUserAnswerMode::kEof: return E_ABORT;
case NUserAnswerMode::kError: return E_FAIL;
default: return E_FAIL;
}
if (_so)
{
*_so << endl;
if (NeedFlush)
_so->Flush();
}
return CheckBreak2();
}
STDMETHODIMP CExtractCallbackConsole::PrepareOperation(const wchar_t *name, Int32 /* isFolder */, Int32 askExtractMode, const UInt64 *position)
{
MT_LOCK
_currentName = name;
const char *s;
unsigned requiredLevel = 1;
switch (askExtractMode)
{
case NArchive::NExtract::NAskMode::kExtract: s = kExtractString; break;
case NArchive::NExtract::NAskMode::kTest: s = kTestString; break;
case NArchive::NExtract::NAskMode::kSkip: s = kSkipString; requiredLevel = 2; break;
default: s = "???"; requiredLevel = 2;
};
bool show2 = (LogLevel >= requiredLevel && _so);
if (show2)
{
ClosePercents_for_so();
_tempA = s;
if (name)
_tempA.Add_Space();
*_so << _tempA;
_tempU.Empty();
if (name)
{
_tempU = name;
_so->Normalize_UString(_tempU);
}
_so->PrintUString(_tempU, _tempA);
if (position)
*_so << " <" << *position << ">";
*_so << endl;
if (NeedFlush)
_so->Flush();
}
if (NeedPercents())
{
if (PercentsNameLevel >= 1)
{
_percent.FileName.Empty();
_percent.Command.Empty();
if (PercentsNameLevel > 1 || !show2)
{
_percent.Command = s;
if (name)
_percent.FileName = name;
}
}
_percent.Print();
}
return CheckBreak2();
}
STDMETHODIMP CExtractCallbackConsole::MessageError(const wchar_t *message)
{
MT_LOCK
RINOK(CheckBreak2());
NumFileErrors_in_Current++;
NumFileErrors++;
ClosePercentsAndFlush();
if (_se)
{
*_se << kError << message << endl;
_se->Flush();
}
return CheckBreak2();
}
void SetExtractErrorMessage(Int32 opRes, Int32 encrypted, AString &dest);
void SetExtractErrorMessage(Int32 opRes, Int32 encrypted, AString &dest)
{
dest.Empty();
const char *s = NULL;
switch (opRes)
{
case NArchive::NExtract::NOperationResult::kUnsupportedMethod:
s = kUnsupportedMethod;
break;
case NArchive::NExtract::NOperationResult::kCRCError:
s = (encrypted ? kCrcFailedEncrypted : kCrcFailed);
break;
case NArchive::NExtract::NOperationResult::kDataError:
s = (encrypted ? kDataErrorEncrypted : kDataError);
break;
case NArchive::NExtract::NOperationResult::kUnavailable:
s = kUnavailableData;
break;
case NArchive::NExtract::NOperationResult::kUnexpectedEnd:
s = kUnexpectedEnd;
break;
case NArchive::NExtract::NOperationResult::kDataAfterEnd:
s = kDataAfterEnd;
break;
case NArchive::NExtract::NOperationResult::kIsNotArc:
s = kIsNotArc;
break;
case NArchive::NExtract::NOperationResult::kHeadersError:
s = kHeadersError;
break;
case NArchive::NExtract::NOperationResult::kWrongPassword:
s = kWrongPassword;
break;
}
dest += kError;
if (s)
dest += s;
else
{
dest += "Error #";
dest.Add_UInt32((UInt32)opRes);
}
}
STDMETHODIMP CExtractCallbackConsole::SetOperationResult(Int32 opRes, Int32 encrypted)
{
MT_LOCK
if (opRes == NArchive::NExtract::NOperationResult::kOK)
{
if (NeedPercents())
{
_percent.Command.Empty();
_percent.FileName.Empty();
_percent.Files++;
}
}
else
{
NumFileErrors_in_Current++;
NumFileErrors++;
if (_se)
{
ClosePercentsAndFlush();
AString s;
SetExtractErrorMessage(opRes, encrypted, s);
*_se << s;
if (!_currentName.IsEmpty())
{
*_se << " : ";
_se->NormalizePrint_UString(_currentName);
}
*_se << endl;
_se->Flush();
}
}
return CheckBreak2();
}
STDMETHODIMP CExtractCallbackConsole::ReportExtractResult(Int32 opRes, Int32 encrypted, const wchar_t *name)
{
if (opRes != NArchive::NExtract::NOperationResult::kOK)
{
_currentName = name;
return SetOperationResult(opRes, encrypted);
}
return CheckBreak2();
}
#ifndef _NO_CRYPTO
HRESULT CExtractCallbackConsole::SetPassword(const UString &password)
{
PasswordIsDefined = true;
Password = password;
return S_OK;
}
STDMETHODIMP CExtractCallbackConsole::CryptoGetTextPassword(BSTR *password)
{
COM_TRY_BEGIN
MT_LOCK
return Open_CryptoGetTextPassword(password);
COM_TRY_END
}
#endif
HRESULT CExtractCallbackConsole::BeforeOpen(const wchar_t *name, bool testMode)
{
RINOK(CheckBreak2());
NumTryArcs++;
ThereIsError_in_Current = false;
ThereIsWarning_in_Current = false;
NumFileErrors_in_Current = 0;
ClosePercents_for_so();
if (_so)
{
*_so << endl << (testMode ? kTesting : kExtracting);
_so->NormalizePrint_wstr(name);
*_so << endl;
}
if (NeedPercents())
_percent.Command = "Open";
return S_OK;
}
HRESULT Print_OpenArchive_Props(CStdOutStream &so, const CCodecs *codecs, const CArchiveLink &arcLink);
HRESULT Print_OpenArchive_Error(CStdOutStream &so, const CCodecs *codecs, const CArchiveLink &arcLink);
static AString GetOpenArcErrorMessage(UInt32 errorFlags)
{
AString s;
for (unsigned i = 0; i < ARRAY_SIZE(k_ErrorFlagsMessages); i++)
{
UInt32 f = (1 << i);
if ((errorFlags & f) == 0)
continue;
const char *m = k_ErrorFlagsMessages[i];
if (!s.IsEmpty())
s.Add_LF();
s += m;
errorFlags &= ~f;
}
if (errorFlags != 0)
{
char sz[16];
sz[0] = '0';
sz[1] = 'x';
ConvertUInt32ToHex(errorFlags, sz + 2);
if (!s.IsEmpty())
s.Add_LF();
s += sz;
}
return s;
}
void PrintErrorFlags(CStdOutStream &so, const char *s, UInt32 errorFlags);
void PrintErrorFlags(CStdOutStream &so, const char *s, UInt32 errorFlags)
{
if (errorFlags == 0)
return;
so << s << endl << GetOpenArcErrorMessage(errorFlags) << endl;
}
static void Add_Messsage_Pre_ArcType(UString &s, const char *pre, const wchar_t *arcType)
{
s.Add_LF();
s += pre;
s += " as [";
s += arcType;
s += "] archive";
}
void Print_ErrorFormatIndex_Warning(CStdOutStream *_so, const CCodecs *codecs, const CArc &arc);
void Print_ErrorFormatIndex_Warning(CStdOutStream *_so, const CCodecs *codecs, const CArc &arc)
{
const CArcErrorInfo &er = arc.ErrorInfo;
*_so << "WARNING:\n";
_so->NormalizePrint_UString(arc.Path);
UString s;
if (arc.FormatIndex == er.ErrorFormatIndex)
{
s.Add_LF();
s += "The archive is open with offset";
}
else
{
Add_Messsage_Pre_ArcType(s, "Cannot open the file", codecs->GetFormatNamePtr(er.ErrorFormatIndex));
Add_Messsage_Pre_ArcType(s, "The file is open", codecs->GetFormatNamePtr(arc.FormatIndex));
}
*_so << s << endl << endl;
}
HRESULT CExtractCallbackConsole::OpenResult(
const CCodecs *codecs, const CArchiveLink &arcLink,
const wchar_t *name, HRESULT result)
{
ClosePercents();
if (NeedPercents())
{
_percent.Files = 0;
_percent.Command.Empty();
_percent.FileName.Empty();
}
ClosePercentsAndFlush();
FOR_VECTOR (level, arcLink.Arcs)
{
const CArc &arc = arcLink.Arcs[level];
const CArcErrorInfo &er = arc.ErrorInfo;
UInt32 errorFlags = er.GetErrorFlags();
if (errorFlags != 0 || !er.ErrorMessage.IsEmpty())
{
if (_se)
{
*_se << endl;
if (level != 0)
{
_se->NormalizePrint_UString(arc.Path);
*_se << endl;
}
}
if (errorFlags != 0)
{
if (_se)
PrintErrorFlags(*_se, "ERRORS:", errorFlags);
NumOpenArcErrors++;
ThereIsError_in_Current = true;
}
if (!er.ErrorMessage.IsEmpty())
{
if (_se)
*_se << "ERRORS:" << endl << er.ErrorMessage << endl;
NumOpenArcErrors++;
ThereIsError_in_Current = true;
}
if (_se)
{
*_se << endl;
_se->Flush();
}
}
UInt32 warningFlags = er.GetWarningFlags();
if (warningFlags != 0 || !er.WarningMessage.IsEmpty())
{
if (_so)
{
*_so << endl;
if (level != 0)
{
_so->NormalizePrint_UString(arc.Path);
*_so << endl;
}
}
if (warningFlags != 0)
{
if (_so)
PrintErrorFlags(*_so, "WARNINGS:", warningFlags);
NumOpenArcWarnings++;
ThereIsWarning_in_Current = true;
}
if (!er.WarningMessage.IsEmpty())
{
if (_so)
*_so << "WARNINGS:" << endl << er.WarningMessage << endl;
NumOpenArcWarnings++;
ThereIsWarning_in_Current = true;
}
if (_so)
{
*_so << endl;
if (NeedFlush)
_so->Flush();
}
}
if (er.ErrorFormatIndex >= 0)
{
if (_so)
{
Print_ErrorFormatIndex_Warning(_so, codecs, arc);
if (NeedFlush)
_so->Flush();
}
ThereIsWarning_in_Current = true;
}
}
if (result == S_OK)
{
if (_so)
{
RINOK(Print_OpenArchive_Props(*_so, codecs, arcLink));
*_so << endl;
}
}
else
{
NumCantOpenArcs++;
if (_so)
_so->Flush();
if (_se)
{
*_se << kError;
_se->NormalizePrint_wstr(name);
*_se << endl;
HRESULT res = Print_OpenArchive_Error(*_se, codecs, arcLink);
RINOK(res);
if (result == S_FALSE)
{
}
else
{
if (result == E_OUTOFMEMORY)
*_se << "Can't allocate required memory";
else
*_se << NError::MyFormatMessage(result);
*_se << endl;
}
_se->Flush();
}
}
return CheckBreak2();
}
HRESULT CExtractCallbackConsole::ThereAreNoFiles()
{
ClosePercents_for_so();
if (_so)
{
*_so << endl << kNoFiles << endl;
if (NeedFlush)
_so->Flush();
}
return CheckBreak2();
}
HRESULT CExtractCallbackConsole::ExtractResult(HRESULT result)
{
MT_LOCK
if (NeedPercents())
{
_percent.ClosePrint(true);
_percent.Command.Empty();
_percent.FileName.Empty();
}
if (_so)
_so->Flush();
if (result == S_OK)
{
if (NumFileErrors_in_Current == 0 && !ThereIsError_in_Current)
{
if (ThereIsWarning_in_Current)
NumArcsWithWarnings++;
else
NumOkArcs++;
if (_so)
*_so << kEverythingIsOk << endl;
}
else
{
NumArcsWithError++;
if (_so)
{
*_so << endl;
if (NumFileErrors_in_Current != 0)
*_so << "Sub items Errors: " << NumFileErrors_in_Current << endl;
}
}
if (_so && NeedFlush)
_so->Flush();
}
else
{
NumArcsWithError++;
if (result == E_ABORT
|| result == HRESULT_FROM_WIN32(ERROR_DISK_FULL)
)
return result;
if (_se)
{
*_se << endl << kError;
if (result == E_OUTOFMEMORY)
*_se << kMemoryExceptionMessage;
else
*_se << NError::MyFormatMessage(result);
*_se << endl;
_se->Flush();
}
}
return CheckBreak2();
}

View File

@@ -0,0 +1,167 @@
// ExtractCallbackConsole.h
#ifndef __EXTRACT_CALLBACK_CONSOLE_H
#define __EXTRACT_CALLBACK_CONSOLE_H
#include "../../../Common/StdOutStream.h"
#include "../../IPassword.h"
#include "../../Archive/IArchive.h"
#include "../Common/ArchiveExtractCallback.h"
#include "PercentPrinter.h"
#include "OpenCallbackConsole.h"
class CExtractScanConsole: public IDirItemsCallback
{
CStdOutStream *_so;
CStdOutStream *_se;
CPercentPrinter _percent;
bool NeedPercents() const { return _percent._so != NULL; }
void ClosePercentsAndFlush()
{
if (NeedPercents())
_percent.ClosePrint(true);
if (_so)
_so->Flush();
}
public:
virtual ~CExtractScanConsole() {}
void Init(CStdOutStream *outStream, CStdOutStream *errorStream, CStdOutStream *percentStream)
{
_so = outStream;
_se = errorStream;
_percent._so = percentStream;
}
void SetWindowWidth(unsigned width) { _percent.MaxLen = width - 1; }
void StartScanning();
INTERFACE_IDirItemsCallback(;)
void CloseScanning()
{
if (NeedPercents())
_percent.ClosePrint(true);
}
void PrintStat(const CDirItemsStat &st);
};
class CExtractCallbackConsole:
public IExtractCallbackUI,
// public IArchiveExtractCallbackMessage,
public IFolderArchiveExtractCallback2,
#ifndef _NO_CRYPTO
public ICryptoGetTextPassword,
#endif
public COpenCallbackConsole,
public CMyUnknownImp
{
AString _tempA;
UString _tempU;
UString _currentName;
void ClosePercents_for_so()
{
if (NeedPercents() && _so == _percent._so)
_percent.ClosePrint(false);
}
void ClosePercentsAndFlush()
{
if (NeedPercents())
_percent.ClosePrint(true);
if (_so)
_so->Flush();
}
public:
MY_QUERYINTERFACE_BEGIN2(IFolderArchiveExtractCallback)
// MY_QUERYINTERFACE_ENTRY(IArchiveExtractCallbackMessage)
MY_QUERYINTERFACE_ENTRY(IFolderArchiveExtractCallback2)
#ifndef _NO_CRYPTO
MY_QUERYINTERFACE_ENTRY(ICryptoGetTextPassword)
#endif
MY_QUERYINTERFACE_END
MY_ADDREF_RELEASE
STDMETHOD(SetTotal)(UInt64 total);
STDMETHOD(SetCompleted)(const UInt64 *completeValue);
INTERFACE_IFolderArchiveExtractCallback(;)
INTERFACE_IExtractCallbackUI(;)
// INTERFACE_IArchiveExtractCallbackMessage(;)
INTERFACE_IFolderArchiveExtractCallback2(;)
#ifndef _NO_CRYPTO
STDMETHOD(CryptoGetTextPassword)(BSTR *password);
#endif
UInt64 NumTryArcs;
bool ThereIsError_in_Current;
bool ThereIsWarning_in_Current;
UInt64 NumOkArcs;
UInt64 NumCantOpenArcs;
UInt64 NumArcsWithError;
UInt64 NumArcsWithWarnings;
UInt64 NumOpenArcErrors;
UInt64 NumOpenArcWarnings;
UInt64 NumFileErrors;
UInt64 NumFileErrors_in_Current;
bool NeedFlush;
unsigned PercentsNameLevel;
unsigned LogLevel;
CExtractCallbackConsole():
NeedFlush(false),
PercentsNameLevel(1),
LogLevel(0)
{}
void SetWindowWidth(unsigned width) { _percent.MaxLen = width - 1; }
void Init(CStdOutStream *outStream, CStdOutStream *errorStream, CStdOutStream *percentStream)
{
COpenCallbackConsole::Init(outStream, errorStream, percentStream);
NumTryArcs = 0;
ThereIsError_in_Current = false;
ThereIsWarning_in_Current = false;
NumOkArcs = 0;
NumCantOpenArcs = 0;
NumArcsWithError = 0;
NumArcsWithWarnings = 0;
NumOpenArcErrors = 0;
NumOpenArcWarnings = 0;
NumFileErrors = 0;
NumFileErrors_in_Current = 0;
}
};
#endif

View File

@@ -0,0 +1,363 @@
// HashCon.cpp
#include "StdAfx.h"
#include "../../../Common/IntToString.h"
#include "ConsoleClose.h"
#include "HashCon.h"
static const char * const kEmptyFileAlias = "[Content]";
static const char * const kScanningMessage = "Scanning";
static HRESULT CheckBreak2()
{
return NConsoleClose::TestBreakSignal() ? E_ABORT : S_OK;
}
HRESULT CHashCallbackConsole::CheckBreak()
{
return CheckBreak2();
}
HRESULT CHashCallbackConsole::StartScanning()
{
if (PrintHeaders && _so)
*_so << kScanningMessage << endl;
if (NeedPercents())
{
_percent.ClearCurState();
_percent.Command = "Scan";
}
return CheckBreak2();
}
HRESULT CHashCallbackConsole::ScanProgress(const CDirItemsStat &st, const FString &path, bool /* isDir */)
{
if (NeedPercents())
{
_percent.Files = st.NumDirs + st.NumFiles + st.NumAltStreams;
_percent.Completed = st.GetTotalBytes();
_percent.FileName = fs2us(path);
_percent.Print();
}
return CheckBreak2();
}
HRESULT CHashCallbackConsole::ScanError(const FString &path, DWORD systemError)
{
return ScanError_Base(path, systemError);
}
void Print_DirItemsStat(AString &s, const CDirItemsStat &st);
HRESULT CHashCallbackConsole::FinishScanning(const CDirItemsStat &st)
{
if (NeedPercents())
{
_percent.ClosePrint(true);
_percent.ClearCurState();
}
if (PrintHeaders && _so)
{
Print_DirItemsStat(_s, st);
*_so << _s << endl << endl;
}
return CheckBreak2();
}
HRESULT CHashCallbackConsole::SetNumFiles(UInt64 /* numFiles */)
{
return CheckBreak2();
}
HRESULT CHashCallbackConsole::SetTotal(UInt64 size)
{
if (NeedPercents())
{
_percent.Total = size;
_percent.Print();
}
return CheckBreak2();
}
HRESULT CHashCallbackConsole::SetCompleted(const UInt64 *completeValue)
{
if (completeValue && NeedPercents())
{
_percent.Completed = *completeValue;
_percent.Print();
}
return CheckBreak2();
}
static void AddMinuses(AString &s, unsigned num)
{
for (unsigned i = 0; i < num; i++)
s += '-';
}
static void AddSpaces_if_Positive(AString &s, int num)
{
for (int i = 0; i < num; i++)
s.Add_Space();
}
static void SetSpacesAndNul(char *s, unsigned num)
{
for (unsigned i = 0; i < num; i++)
s[i] = ' ';
s[num] = 0;
}
static const unsigned kSizeField_Len = 13;
static const unsigned kNameField_Len = 12;
static const unsigned kHashColumnWidth_Min = 4 * 2;
static unsigned GetColumnWidth(unsigned digestSize)
{
unsigned width = digestSize * 2;
return width < kHashColumnWidth_Min ? kHashColumnWidth_Min: width;
}
void CHashCallbackConsole::PrintSeparatorLine(const CObjectVector<CHasherState> &hashers)
{
_s.Empty();
for (unsigned i = 0; i < hashers.Size(); i++)
{
if (i != 0)
_s.Add_Space();
const CHasherState &h = hashers[i];
AddMinuses(_s, GetColumnWidth(h.DigestSize));
}
if (PrintSize)
{
_s.Add_Space();
AddMinuses(_s, kSizeField_Len);
}
if (PrintName)
{
AddSpacesBeforeName();
AddMinuses(_s, kNameField_Len);
}
*_so << _s << endl;
}
HRESULT CHashCallbackConsole::BeforeFirstFile(const CHashBundle &hb)
{
if (PrintHeaders && _so)
{
_s.Empty();
ClosePercents_for_so();
FOR_VECTOR (i, hb.Hashers)
{
if (i != 0)
_s.Add_Space();
const CHasherState &h = hb.Hashers[i];
_s += h.Name;
AddSpaces_if_Positive(_s, (int)GetColumnWidth(h.DigestSize) - (int)h.Name.Len());
}
if (PrintSize)
{
_s.Add_Space();
const AString s2 ("Size");
AddSpaces_if_Positive(_s, (int)kSizeField_Len - (int)s2.Len());
_s += s2;
}
if (PrintName)
{
AddSpacesBeforeName();
_s += "Name";
}
*_so << _s << endl;
PrintSeparatorLine(hb.Hashers);
}
return CheckBreak2();
}
HRESULT CHashCallbackConsole::OpenFileError(const FString &path, DWORD systemError)
{
return OpenFileError_Base(path, systemError);
}
HRESULT CHashCallbackConsole::GetStream(const wchar_t *name, bool /* isFolder */)
{
_fileName = name;
if (NeedPercents())
{
if (PrintNameInPercents)
{
_percent.FileName.Empty();
if (name)
_percent.FileName = name;
}
_percent.Print();
}
return CheckBreak2();
}
void CHashCallbackConsole::PrintResultLine(UInt64 fileSize,
const CObjectVector<CHasherState> &hashers, unsigned digestIndex, bool showHash)
{
ClosePercents_for_so();
_s.Empty();
FOR_VECTOR (i, hashers)
{
const CHasherState &h = hashers[i];
char s[k_HashCalc_DigestSize_Max * 2 + 64];
s[0] = 0;
if (showHash)
AddHashHexToString(s, h.Digests[digestIndex], h.DigestSize);
const unsigned pos = (unsigned)strlen(s);
SetSpacesAndNul(s + pos, GetColumnWidth(h.DigestSize) - pos);
if (i != 0)
_s.Add_Space();
_s += s;
}
if (PrintSize)
{
_s.Add_Space();
char s[kSizeField_Len + 32];
char *p = s;
SetSpacesAndNul(s, kSizeField_Len);
if (showHash)
{
p = s + kSizeField_Len;
ConvertUInt64ToString(fileSize, p);
int numSpaces = (int)kSizeField_Len - (int)strlen(p);
if (numSpaces > 0)
p -= (unsigned)numSpaces;
}
_s += p;
}
if (PrintName)
AddSpacesBeforeName();
*_so << _s;
}
HRESULT CHashCallbackConsole::SetOperationResult(UInt64 fileSize, const CHashBundle &hb, bool showHash)
{
if (_so)
{
PrintResultLine(fileSize, hb.Hashers, k_HashCalc_Index_Current, showHash);
if (PrintName)
{
if (_fileName.IsEmpty())
*_so << kEmptyFileAlias;
else
_so->NormalizePrint_UString(_fileName);
}
*_so << endl;
}
if (NeedPercents())
{
_percent.Files++;
_percent.Print();
}
return CheckBreak2();
}
static const char * const k_DigestTitles[] =
{
" : "
, " for data: "
, " for data and names: "
, " for streams and names: "
};
static void PrintSum(CStdOutStream &so, const CHasherState &h, unsigned digestIndex)
{
so << h.Name;
{
AString temp;
AddSpaces_if_Positive(temp, 6 - (int)h.Name.Len());
so << temp;
}
so << k_DigestTitles[digestIndex];
char s[k_HashCalc_DigestSize_Max * 2 + 64];
s[0] = 0;
AddHashHexToString(s, h.Digests[digestIndex], h.DigestSize);
so << s << endl;
}
void PrintHashStat(CStdOutStream &so, const CHashBundle &hb)
{
FOR_VECTOR (i, hb.Hashers)
{
const CHasherState &h = hb.Hashers[i];
PrintSum(so, h, k_HashCalc_Index_DataSum);
if (hb.NumFiles != 1 || hb.NumDirs != 0)
PrintSum(so, h, k_HashCalc_Index_NamesSum);
if (hb.NumAltStreams != 0)
PrintSum(so, h, k_HashCalc_Index_StreamsSum);
so << endl;
}
}
void CHashCallbackConsole::PrintProperty(const char *name, UInt64 value)
{
char s[32];
s[0] = ':';
s[1] = ' ';
ConvertUInt64ToString(value, s + 2);
*_so << name << s << endl;
}
HRESULT CHashCallbackConsole::AfterLastFile(CHashBundle &hb)
{
ClosePercents2();
if (PrintHeaders && _so)
{
PrintSeparatorLine(hb.Hashers);
PrintResultLine(hb.FilesSize, hb.Hashers, k_HashCalc_Index_DataSum, true);
*_so << endl << endl;
if (hb.NumFiles != 1 || hb.NumDirs != 0)
{
if (hb.NumDirs != 0)
PrintProperty("Folders", hb.NumDirs);
PrintProperty("Files", hb.NumFiles);
}
PrintProperty("Size", hb.FilesSize);
if (hb.NumAltStreams != 0)
{
PrintProperty("Alternate streams", hb.NumAltStreams);
PrintProperty("Alternate streams size", hb.AltStreamsSize);
}
*_so << endl;
PrintHashStat(*_so, hb);
}
return S_OK;
}

View File

@@ -0,0 +1,48 @@
// HashCon.h
#ifndef __HASH_CON_H
#define __HASH_CON_H
#include "../Common/HashCalc.h"
#include "UpdateCallbackConsole.h"
class CHashCallbackConsole: public IHashCallbackUI, public CCallbackConsoleBase
{
UString _fileName;
AString _s;
void AddSpacesBeforeName()
{
_s.Add_Space();
_s.Add_Space();
}
void PrintSeparatorLine(const CObjectVector<CHasherState> &hashers);
void PrintResultLine(UInt64 fileSize,
const CObjectVector<CHasherState> &hashers, unsigned digestIndex, bool showHash);
void PrintProperty(const char *name, UInt64 value);
public:
bool PrintNameInPercents;
bool PrintHeaders;
bool PrintSize;
bool PrintName;
CHashCallbackConsole():
PrintNameInPercents(true),
PrintHeaders(false),
PrintSize(true),
PrintName(true)
{}
virtual ~CHashCallbackConsole() {}
INTERFACE_IHashCallbackUI(;)
};
void PrintHashStat(CStdOutStream &so, const CHashBundle &hb);
#endif

1361
3rdparty/lzma/CPP/7zip/UI/Console/List.cpp vendored Normal file

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,27 @@
// List.h
#ifndef __LIST_H
#define __LIST_H
#include "../../../Common/Wildcard.h"
#include "../Common/LoadCodecs.h"
HRESULT ListArchives(CCodecs *codecs,
const CObjectVector<COpenType> &types,
const CIntVector &excludedFormats,
bool stdInMode,
UStringVector &archivePaths, UStringVector &archivePathsFull,
bool processAltStreams, bool showAltStreams,
const NWildcard::CCensorNode &wildcardCensor,
bool enableHeaders, bool techMode,
#ifndef _NO_CRYPTO
bool &passwordEnabled, UString &password,
#endif
#ifndef _SFX
const CObjectVector<CProperty> *props,
#endif
UInt64 &errors,
UInt64 &numWarnings);
#endif

1457
3rdparty/lzma/CPP/7zip/UI/Console/Main.cpp vendored Normal file

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,181 @@
// MainAr.cpp
#include "StdAfx.h"
#ifdef _WIN32
#include "../../../../C/DllSecur.h"
#endif
#include "../../../Common/MyException.h"
#include "../../../Common/StdOutStream.h"
#include "../../../Windows/ErrorMsg.h"
#include "../../../Windows/NtCheck.h"
#include "../Common/ArchiveCommandLine.h"
#include "../Common/ExitCode.h"
#include "ConsoleClose.h"
using namespace NWindows;
extern
CStdOutStream *g_StdStream;
CStdOutStream *g_StdStream = NULL;
extern
CStdOutStream *g_ErrStream;
CStdOutStream *g_ErrStream = NULL;
extern int Main2(
#ifndef _WIN32
int numArgs, char *args[]
#endif
);
static const char * const kException_CmdLine_Error_Message = "Command Line Error:";
static const char * const kExceptionErrorMessage = "ERROR:";
static const char * const kUserBreakMessage = "Break signaled";
static const char * const kMemoryExceptionMessage = "ERROR: Can't allocate required memory!";
static const char * const kUnknownExceptionMessage = "Unknown Error";
static const char * const kInternalExceptionMessage = "\n\nInternal Error #";
static void FlushStreams()
{
if (g_StdStream)
g_StdStream->Flush();
}
static void PrintError(const char *message)
{
FlushStreams();
if (g_ErrStream)
*g_ErrStream << "\n\n" << message << endl;
}
#if defined(_WIN32) && defined(_UNICODE) && !defined(_WIN64) && !defined(UNDER_CE)
#define NT_CHECK_FAIL_ACTION *g_StdStream << "Unsupported Windows version"; return NExitCode::kFatalError;
#endif
int MY_CDECL main
(
#ifndef _WIN32
int numArgs, char *args[]
#endif
)
{
g_ErrStream = &g_StdErr;
g_StdStream = &g_StdOut;
NT_CHECK
NConsoleClose::CCtrlHandlerSetter ctrlHandlerSetter;
int res = 0;
try
{
#ifdef _WIN32
My_SetDefaultDllDirectories();
#endif
res = Main2(
#ifndef _WIN32
numArgs, args
#endif
);
}
catch(const CNewException &)
{
PrintError(kMemoryExceptionMessage);
return (NExitCode::kMemoryError);
}
catch(const NConsoleClose::CCtrlBreakException &)
{
PrintError(kUserBreakMessage);
return (NExitCode::kUserBreak);
}
catch(const CMessagePathException &e)
{
PrintError(kException_CmdLine_Error_Message);
if (g_ErrStream)
*g_ErrStream << e << endl;
return (NExitCode::kUserError);
}
catch(const CSystemException &systemError)
{
if (systemError.ErrorCode == E_OUTOFMEMORY)
{
PrintError(kMemoryExceptionMessage);
return (NExitCode::kMemoryError);
}
if (systemError.ErrorCode == E_ABORT)
{
PrintError(kUserBreakMessage);
return (NExitCode::kUserBreak);
}
if (g_ErrStream)
{
PrintError("System ERROR:");
*g_ErrStream << NError::MyFormatMessage(systemError.ErrorCode) << endl;
}
return (NExitCode::kFatalError);
}
catch(NExitCode::EEnum &exitCode)
{
FlushStreams();
if (g_ErrStream)
*g_ErrStream << kInternalExceptionMessage << exitCode << endl;
return (exitCode);
}
catch(const UString &s)
{
if (g_ErrStream)
{
PrintError(kExceptionErrorMessage);
*g_ErrStream << s << endl;
}
return (NExitCode::kFatalError);
}
catch(const AString &s)
{
if (g_ErrStream)
{
PrintError(kExceptionErrorMessage);
*g_ErrStream << s << endl;
}
return (NExitCode::kFatalError);
}
catch(const char *s)
{
if (g_ErrStream)
{
PrintError(kExceptionErrorMessage);
*g_ErrStream << s << endl;
}
return (NExitCode::kFatalError);
}
catch(const wchar_t *s)
{
if (g_ErrStream)
{
PrintError(kExceptionErrorMessage);
*g_ErrStream << s << endl;
}
return (NExitCode::kFatalError);
}
catch(int t)
{
if (g_ErrStream)
{
FlushStreams();
*g_ErrStream << kInternalExceptionMessage << t << endl;
return (NExitCode::kFatalError);
}
}
catch(...)
{
PrintError(kUnknownExceptionMessage);
return (NExitCode::kFatalError);
}
return res;
}

View File

@@ -0,0 +1,115 @@
// OpenCallbackConsole.cpp
#include "StdAfx.h"
#include "OpenCallbackConsole.h"
#include "ConsoleClose.h"
#include "UserInputUtils.h"
static HRESULT CheckBreak2()
{
return NConsoleClose::TestBreakSignal() ? E_ABORT : S_OK;
}
HRESULT COpenCallbackConsole::Open_CheckBreak()
{
return CheckBreak2();
}
HRESULT COpenCallbackConsole::Open_SetTotal(const UInt64 *files, const UInt64 *bytes)
{
if (!MultiArcMode && NeedPercents())
{
if (files)
{
_totalFilesDefined = true;
// _totalFiles = *files;
_percent.Total = *files;
}
else
_totalFilesDefined = false;
if (bytes)
{
// _totalBytesDefined = true;
_totalBytes = *bytes;
if (!files)
_percent.Total = *bytes;
}
else
{
// _totalBytesDefined = false;
if (!files)
_percent.Total = _totalBytes;
}
}
return CheckBreak2();
}
HRESULT COpenCallbackConsole::Open_SetCompleted(const UInt64 *files, const UInt64 *bytes)
{
if (!MultiArcMode && NeedPercents())
{
if (files)
{
_percent.Files = *files;
if (_totalFilesDefined)
_percent.Completed = *files;
}
if (bytes)
{
if (!_totalFilesDefined)
_percent.Completed = *bytes;
}
_percent.Print();
}
return CheckBreak2();
}
HRESULT COpenCallbackConsole::Open_Finished()
{
ClosePercents();
return S_OK;
}
#ifndef _NO_CRYPTO
HRESULT COpenCallbackConsole::Open_CryptoGetTextPassword(BSTR *password)
{
*password = NULL;
RINOK(CheckBreak2());
if (!PasswordIsDefined)
{
ClosePercents();
RINOK(GetPassword_HRESULT(_so, Password));
PasswordIsDefined = true;
}
return StringToBstr(Password, password);
}
/*
HRESULT COpenCallbackConsole::Open_GetPasswordIfAny(bool &passwordIsDefined, UString &password)
{
passwordIsDefined = PasswordIsDefined;
password = Password;
return S_OK;
}
bool COpenCallbackConsole::Open_WasPasswordAsked()
{
return PasswordWasAsked;
}
void COpenCallbackConsole::Open_Clear_PasswordWasAsked_Flag ()
{
PasswordWasAsked = false;
}
*/
#endif

View File

@@ -0,0 +1,68 @@
// OpenCallbackConsole.h
#ifndef __OPEN_CALLBACK_CONSOLE_H
#define __OPEN_CALLBACK_CONSOLE_H
#include "../../../Common/StdOutStream.h"
#include "../Common/ArchiveOpenCallback.h"
#include "PercentPrinter.h"
class COpenCallbackConsole: public IOpenCallbackUI
{
protected:
CPercentPrinter _percent;
CStdOutStream *_so;
CStdOutStream *_se;
bool _totalFilesDefined;
// bool _totalBytesDefined;
// UInt64 _totalFiles;
UInt64 _totalBytes;
bool NeedPercents() const { return _percent._so != NULL; }
public:
bool MultiArcMode;
void ClosePercents()
{
if (NeedPercents())
_percent.ClosePrint(true);
}
COpenCallbackConsole():
_totalFilesDefined(false),
// _totalBytesDefined(false),
_totalBytes(0),
MultiArcMode(false)
#ifndef _NO_CRYPTO
, PasswordIsDefined(false)
// , PasswordWasAsked(false)
#endif
{}
virtual ~COpenCallbackConsole() {}
void Init(CStdOutStream *outStream, CStdOutStream *errorStream, CStdOutStream *percentStream)
{
_so = outStream;
_se = errorStream;
_percent._so = percentStream;
}
INTERFACE_IOpenCallbackUI(;)
#ifndef _NO_CRYPTO
bool PasswordIsDefined;
// bool PasswordWasAsked;
UString Password;
#endif
};
#endif

View File

@@ -0,0 +1,183 @@
// PercentPrinter.cpp
#include "StdAfx.h"
#include "../../../Common/IntToString.h"
#include "PercentPrinter.h"
static const unsigned kPercentsSize = 4;
CPercentPrinter::~CPercentPrinter()
{
ClosePrint(false);
}
void CPercentPrinterState::ClearCurState()
{
Completed = 0;
Total = ((UInt64)(Int64)-1);
Files = 0;
Command.Empty();
FileName.Empty();
}
void CPercentPrinter::ClosePrint(bool needFlush)
{
unsigned num = _printedString.Len();
if (num != 0)
{
unsigned i;
/* '\r' in old MAC OS means "new line".
So we can't use '\r' in some systems */
#ifdef _WIN32
char *start = _temp.GetBuf(num + 2);
char *p = start;
*p++ = '\r';
for (i = 0; i < num; i++) *p++ = ' ';
*p++ = '\r';
#else
char *start = _temp.GetBuf(num * 3);
char *p = start;
for (i = 0; i < num; i++) *p++ = '\b';
for (i = 0; i < num; i++) *p++ = ' ';
for (i = 0; i < num; i++) *p++ = '\b';
#endif
*p = 0;
_temp.ReleaseBuf_SetLen((unsigned)(p - start));
*_so << _temp;
}
if (needFlush)
_so->Flush();
_printedString.Empty();
}
void CPercentPrinter::GetPercents()
{
char s[32];
unsigned size;
{
char c = '%';
UInt64 val = 0;
if (Total == (UInt64)(Int64)-1)
{
val = Completed >> 20;
c = 'M';
}
else if (Total != 0)
val = Completed * 100 / Total;
ConvertUInt64ToString(val, s);
size = (unsigned)strlen(s);
s[size++] = c;
s[size] = 0;
}
while (size < kPercentsSize)
{
_s += ' ';
size++;
}
_s += s;
}
void CPercentPrinter::Print()
{
DWORD tick = 0;
if (_tickStep != 0)
tick = GetTickCount();
bool onlyPercentsChanged = false;
if (!_printedString.IsEmpty())
{
if (_tickStep != 0 && (UInt32)(tick - _prevTick) < _tickStep)
return;
CPercentPrinterState &st = *this;
if (_printedState.Command == st.Command
&& _printedState.FileName == st.FileName
&& _printedState.Files == st.Files)
{
if (_printedState.Total == st.Total
&& _printedState.Completed == st.Completed)
return;
onlyPercentsChanged = true;
}
}
_s.Empty();
GetPercents();
if (onlyPercentsChanged && _s == _printedPercents)
return;
_printedPercents = _s;
if (Files != 0)
{
char s[32];
ConvertUInt64ToString(Files, s);
// unsigned size = (unsigned)strlen(s);
// for (; size < 3; size++) _s += ' ';
_s += ' ';
_s += s;
// _s += "f";
}
if (!Command.IsEmpty())
{
_s += ' ';
_s += Command;
}
if (!FileName.IsEmpty() && _s.Len() < MaxLen)
{
_s += ' ';
_tempU = FileName;
_so->Normalize_UString(_tempU);
_so->Convert_UString_to_AString(_tempU, _temp);
if (_s.Len() + _temp.Len() > MaxLen)
{
unsigned len = FileName.Len();
for (; len != 0;)
{
unsigned delta = len / 8;
if (delta == 0)
delta = 1;
len -= delta;
_tempU = FileName;
_tempU.Delete(len / 2, _tempU.Len() - len);
_tempU.Insert(len / 2, L" . ");
_so->Normalize_UString(_tempU);
_so->Convert_UString_to_AString(_tempU, _temp);
if (_s.Len() + _temp.Len() <= MaxLen)
break;
}
if (len == 0)
_temp.Empty();
}
_s += _temp;
}
if (_printedString != _s)
{
ClosePrint(false);
*_so << _s;
if (NeedFlush)
_so->Flush();
_printedString = _s;
}
_printedState = *this;
if (_tickStep != 0)
_prevTick = tick;
}

View File

@@ -0,0 +1,62 @@
// PercentPrinter.h
#ifndef __PERCENT_PRINTER_H
#define __PERCENT_PRINTER_H
#include "../../../Common/StdOutStream.h"
struct CPercentPrinterState
{
UInt64 Completed;
UInt64 Total;
UInt64 Files;
AString Command;
UString FileName;
void ClearCurState();
CPercentPrinterState():
Completed(0),
Total((UInt64)(Int64)-1),
Files(0)
{}
};
class CPercentPrinter: public CPercentPrinterState
{
UInt32 _tickStep;
DWORD _prevTick;
AString _s;
AString _printedString;
AString _temp;
UString _tempU;
CPercentPrinterState _printedState;
AString _printedPercents;
void GetPercents();
public:
CStdOutStream *_so;
bool NeedFlush;
unsigned MaxLen;
CPercentPrinter(UInt32 tickStep = 200):
_tickStep(tickStep),
_prevTick(0),
NeedFlush(true),
MaxLen(80 - 1)
{}
~CPercentPrinter();
void ClosePrint(bool needFlush);
void Print();
};
#endif

View File

@@ -0,0 +1,3 @@
// StdAfx.cpp
#include "StdAfx.h"

View File

@@ -0,0 +1,8 @@
// StdAfx.h
#ifndef __STDAFX_H
#define __STDAFX_H
#include "../../../Common/Common.h"
#endif

View File

@@ -0,0 +1,709 @@
// UpdateCallbackConsole.cpp
#include "StdAfx.h"
#include "../../../Common/IntToString.h"
#include "../../../Windows/ErrorMsg.h"
#ifndef _7ZIP_ST
#include "../../../Windows/Synchronization.h"
#endif
#include "ConsoleClose.h"
#include "UserInputUtils.h"
#include "UpdateCallbackConsole.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 * const kEmptyFileAlias = L"[Content]";
static const char * const kOpenArchiveMessage = "Open archive: ";
static const char * const kCreatingArchiveMessage = "Creating archive: ";
static const char * const kUpdatingArchiveMessage = "Updating archive: ";
static const char * const kScanningMessage = "Scanning the drive:";
static const char * const kError = "ERROR: ";
static const char * const kWarning = "WARNING: ";
static HRESULT CheckBreak2()
{
return NConsoleClose::TestBreakSignal() ? E_ABORT : S_OK;
}
HRESULT Print_OpenArchive_Props(CStdOutStream &so, const CCodecs *codecs, const CArchiveLink &arcLink);
HRESULT Print_OpenArchive_Error(CStdOutStream &so, const CCodecs *codecs, const CArchiveLink &arcLink);
void PrintErrorFlags(CStdOutStream &so, const char *s, UInt32 errorFlags);
void Print_ErrorFormatIndex_Warning(CStdOutStream *_so, const CCodecs *codecs, const CArc &arc);
HRESULT CUpdateCallbackConsole::OpenResult(
const CCodecs *codecs, const CArchiveLink &arcLink,
const wchar_t *name, HRESULT result)
{
ClosePercents2();
FOR_VECTOR (level, arcLink.Arcs)
{
const CArc &arc = arcLink.Arcs[level];
const CArcErrorInfo &er = arc.ErrorInfo;
UInt32 errorFlags = er.GetErrorFlags();
if (errorFlags != 0 || !er.ErrorMessage.IsEmpty())
{
if (_se)
{
*_se << endl;
if (level != 0)
*_se << arc.Path << endl;
}
if (errorFlags != 0)
{
if (_se)
PrintErrorFlags(*_se, "ERRORS:", errorFlags);
}
if (!er.ErrorMessage.IsEmpty())
{
if (_se)
*_se << "ERRORS:" << endl << er.ErrorMessage << endl;
}
if (_se)
{
*_se << endl;
_se->Flush();
}
}
UInt32 warningFlags = er.GetWarningFlags();
if (warningFlags != 0 || !er.WarningMessage.IsEmpty())
{
if (_so)
{
*_so << endl;
if (level != 0)
*_so << arc.Path << endl;
}
if (warningFlags != 0)
{
if (_so)
PrintErrorFlags(*_so, "WARNINGS:", warningFlags);
}
if (!er.WarningMessage.IsEmpty())
{
if (_so)
*_so << "WARNINGS:" << endl << er.WarningMessage << endl;
}
if (_so)
{
*_so << endl;
if (NeedFlush)
_so->Flush();
}
}
if (er.ErrorFormatIndex >= 0)
{
if (_so)
{
Print_ErrorFormatIndex_Warning(_so, codecs, arc);
if (NeedFlush)
_so->Flush();
}
}
}
if (result == S_OK)
{
if (_so)
{
RINOK(Print_OpenArchive_Props(*_so, codecs, arcLink));
*_so << endl;
}
}
else
{
if (_so)
_so->Flush();
if (_se)
{
*_se << kError;
_se->NormalizePrint_wstr(name);
*_se << endl;
HRESULT res = Print_OpenArchive_Error(*_se, codecs, arcLink);
RINOK(res);
_se->Flush();
}
}
return S_OK;
}
HRESULT CUpdateCallbackConsole::StartScanning()
{
if (_so)
*_so << kScanningMessage << endl;
_percent.Command = "Scan ";
return S_OK;
}
HRESULT CUpdateCallbackConsole::ScanProgress(const CDirItemsStat &st, const FString &path, bool /* isDir */)
{
if (NeedPercents())
{
_percent.Files = st.NumDirs + st.NumFiles + st.NumAltStreams;
_percent.Completed = st.GetTotalBytes();
_percent.FileName = fs2us(path);
_percent.Print();
}
return CheckBreak();
}
void CCallbackConsoleBase::CommonError(const FString &path, DWORD systemError, bool isWarning)
{
ClosePercents2();
if (_se)
{
if (_so)
_so->Flush();
*_se << endl << (isWarning ? kWarning : kError)
<< NError::MyFormatMessage(systemError)
<< endl;
_se->NormalizePrint_UString(fs2us(path));
*_se << endl << endl;
_se->Flush();
}
}
HRESULT CCallbackConsoleBase::ScanError_Base(const FString &path, DWORD systemError)
{
MT_LOCK
ScanErrors.AddError(path, systemError);
CommonError(path, systemError, true);
return S_OK;
}
HRESULT CCallbackConsoleBase::OpenFileError_Base(const FString &path, DWORD systemError)
{
MT_LOCK
FailedFiles.AddError(path, systemError);
NumNonOpenFiles++;
/*
if (systemError == ERROR_SHARING_VIOLATION)
{
*/
CommonError(path, systemError, true);
return S_FALSE;
/*
}
return systemError;
*/
}
HRESULT CCallbackConsoleBase::ReadingFileError_Base(const FString &path, DWORD systemError)
{
MT_LOCK
CommonError(path, systemError, false);
return HRESULT_FROM_WIN32(systemError);
}
HRESULT CUpdateCallbackConsole::ScanError(const FString &path, DWORD systemError)
{
return ScanError_Base(path, systemError);
}
static void PrintPropPair(AString &s, const char *name, UInt64 val)
{
char temp[32];
ConvertUInt64ToString(val, temp);
s += name;
s += ": ";
s += temp;
}
void PrintSize_bytes_Smart(AString &s, UInt64 val);
void Print_DirItemsStat(AString &s, const CDirItemsStat &st);
void Print_DirItemsStat2(AString &s, const CDirItemsStat2 &st);
HRESULT CUpdateCallbackConsole::FinishScanning(const CDirItemsStat &st)
{
if (NeedPercents())
{
_percent.ClosePrint(true);
_percent.ClearCurState();
}
if (_so)
{
AString s;
Print_DirItemsStat(s, st);
*_so << s << endl << endl;
}
return S_OK;
}
static const char * const k_StdOut_ArcName = "StdOut";
HRESULT CUpdateCallbackConsole::StartOpenArchive(const wchar_t *name)
{
if (_so)
{
*_so << kOpenArchiveMessage;
if (name)
*_so << name;
else
*_so << k_StdOut_ArcName;
*_so << endl;
}
return S_OK;
}
HRESULT CUpdateCallbackConsole::StartArchive(const wchar_t *name, bool updating)
{
if (NeedPercents())
_percent.ClosePrint(true);
_percent.ClearCurState();
NumNonOpenFiles = 0;
if (_so)
{
*_so << (updating ? kUpdatingArchiveMessage : kCreatingArchiveMessage);
if (name)
_so->NormalizePrint_wstr(name);
else
*_so << k_StdOut_ArcName;
*_so << endl << endl;
}
return S_OK;
}
HRESULT CUpdateCallbackConsole::FinishArchive(const CFinishArchiveStat &st)
{
ClosePercents2();
if (_so)
{
AString s;
// Print_UInt64_and_String(s, _percent.Files == 1 ? "file" : "files", _percent.Files);
PrintPropPair(s, "Files read from disk", _percent.Files - NumNonOpenFiles);
s.Add_LF();
s += "Archive size: ";
PrintSize_bytes_Smart(s, st.OutArcFileSize);
s.Add_LF();
*_so << endl;
*_so << s;
// *_so << endl;
}
return S_OK;
}
HRESULT CUpdateCallbackConsole::WriteSfx(const wchar_t *name, UInt64 size)
{
if (_so)
{
*_so << "Write SFX: ";
*_so << name;
AString s (" : ");
PrintSize_bytes_Smart(s, size);
*_so << s << endl;
}
return S_OK;
}
HRESULT CUpdateCallbackConsole::DeletingAfterArchiving(const FString &path, bool /* isDir */)
{
if (LogLevel > 0 && _so)
{
ClosePercents_for_so();
if (!DeleteMessageWasShown)
{
if (_so)
*_so << endl << ": Removing files after including to archive" << endl;
}
{
{
_tempA = "Removing";
_tempA.Add_Space();
*_so << _tempA;
_tempU = fs2us(path);
_so->Normalize_UString(_tempU);
_so->PrintUString(_tempU, _tempA);
*_so << endl;
if (NeedFlush)
_so->Flush();
}
}
}
if (!DeleteMessageWasShown)
{
if (NeedPercents())
{
_percent.ClearCurState();
}
DeleteMessageWasShown = true;
}
else
{
_percent.Files++;
}
if (NeedPercents())
{
// if (!FullLog)
{
_percent.Command = "Removing";
_percent.FileName = fs2us(path);
}
_percent.Print();
}
return S_OK;
}
HRESULT CUpdateCallbackConsole::FinishDeletingAfterArchiving()
{
ClosePercents2();
if (_so && DeleteMessageWasShown)
*_so << endl;
return S_OK;
}
HRESULT CUpdateCallbackConsole::CheckBreak()
{
return CheckBreak2();
}
/*
HRESULT CUpdateCallbackConsole::Finalize()
{
// MT_LOCK
return S_OK;
}
*/
void static PrintToDoStat(CStdOutStream *_so, const CDirItemsStat2 &stat, const char *name)
{
AString s;
Print_DirItemsStat2(s, stat);
*_so << name << ": " << s << endl;
}
HRESULT CUpdateCallbackConsole::SetNumItems(const CArcToDoStat &stat)
{
if (_so)
{
ClosePercents_for_so();
if (!stat.DeleteData.IsEmpty())
{
*_so << endl;
PrintToDoStat(_so, stat.DeleteData, "Delete data from archive");
}
if (!stat.OldData.IsEmpty())
PrintToDoStat(_so, stat.OldData, "Keep old data in archive");
// if (!stat.NewData.IsEmpty())
{
PrintToDoStat(_so, stat.NewData, "Add new data to archive");
}
*_so << endl;
}
return S_OK;
}
HRESULT CUpdateCallbackConsole::SetTotal(UInt64 size)
{
MT_LOCK
if (NeedPercents())
{
_percent.Total = size;
_percent.Print();
}
return S_OK;
}
HRESULT CUpdateCallbackConsole::SetCompleted(const UInt64 *completeValue)
{
MT_LOCK
if (completeValue)
{
if (NeedPercents())
{
_percent.Completed = *completeValue;
_percent.Print();
}
}
return CheckBreak2();
}
HRESULT CUpdateCallbackConsole::SetRatioInfo(const UInt64 * /* inSize */, const UInt64 * /* outSize */)
{
return CheckBreak2();
}
HRESULT CCallbackConsoleBase::PrintProgress(const wchar_t *name, const char *command, bool showInLog)
{
MT_LOCK
bool show2 = (showInLog && _so);
if (show2)
{
ClosePercents_for_so();
_tempA = command;
if (name)
_tempA.Add_Space();
*_so << _tempA;
_tempU.Empty();
if (name)
{
_tempU = name;
_so->Normalize_UString(_tempU);
}
_so->PrintUString(_tempU, _tempA);
*_so << endl;
if (NeedFlush)
_so->Flush();
}
if (NeedPercents())
{
if (PercentsNameLevel >= 1)
{
_percent.FileName.Empty();
_percent.Command.Empty();
if (PercentsNameLevel > 1 || !show2)
{
_percent.Command = command;
if (name)
_percent.FileName = name;
}
}
_percent.Print();
}
return CheckBreak2();
}
HRESULT CUpdateCallbackConsole::GetStream(const wchar_t *name, bool /* isDir */, bool isAnti, UInt32 mode)
{
if (StdOutMode)
return S_OK;
if (!name || name[0] == 0)
name = kEmptyFileAlias;
unsigned requiredLevel = 1;
const char *s;
if (mode == NUpdateNotifyOp::kAdd ||
mode == NUpdateNotifyOp::kUpdate)
{
if (isAnti)
s = "Anti";
else if (mode == NUpdateNotifyOp::kAdd)
s = "+";
else
s = "U";
}
else
{
requiredLevel = 3;
if (mode == NUpdateNotifyOp::kAnalyze)
s = "A";
else
s = "Reading";
}
return PrintProgress(name, s, LogLevel >= requiredLevel);
}
HRESULT CUpdateCallbackConsole::OpenFileError(const FString &path, DWORD systemError)
{
return OpenFileError_Base(path, systemError);
}
HRESULT CUpdateCallbackConsole::ReadingFileError(const FString &path, DWORD systemError)
{
return ReadingFileError_Base(path, systemError);
}
HRESULT CUpdateCallbackConsole::SetOperationResult(Int32)
{
MT_LOCK
_percent.Files++;
return S_OK;
}
void SetExtractErrorMessage(Int32 opRes, Int32 encrypted, AString &dest);
HRESULT CUpdateCallbackConsole::ReportExtractResult(Int32 opRes, Int32 isEncrypted, const wchar_t *name)
{
// if (StdOutMode) return S_OK;
if (opRes != NArchive::NExtract::NOperationResult::kOK)
{
ClosePercents2();
if (_se)
{
if (_so)
_so->Flush();
AString s;
SetExtractErrorMessage(opRes, isEncrypted, s);
*_se << s << " : " << endl;
_se->NormalizePrint_wstr(name);
*_se << endl << endl;
_se->Flush();
}
return S_OK;
}
return S_OK;
}
HRESULT CUpdateCallbackConsole::ReportUpdateOpeartion(UInt32 op, const wchar_t *name, bool /* isDir */)
{
// if (StdOutMode) return S_OK;
char temp[16];
const char *s;
unsigned requiredLevel = 1;
switch (op)
{
case NUpdateNotifyOp::kAdd: s = "+"; break;
case NUpdateNotifyOp::kUpdate: s = "U"; break;
case NUpdateNotifyOp::kAnalyze: s = "A"; requiredLevel = 3; break;
case NUpdateNotifyOp::kReplicate: s = "="; requiredLevel = 3; break;
case NUpdateNotifyOp::kRepack: s = "R"; requiredLevel = 2; break;
case NUpdateNotifyOp::kSkip: s = "."; requiredLevel = 2; break;
case NUpdateNotifyOp::kDelete: s = "D"; requiredLevel = 3; break;
case NUpdateNotifyOp::kHeader: s = "Header creation"; requiredLevel = 100; break;
default:
{
temp[0] = 'o';
temp[1] = 'p';
ConvertUInt64ToString(op, temp + 2);
s = temp;
}
}
return PrintProgress(name, s, LogLevel >= requiredLevel);
}
/*
HRESULT CUpdateCallbackConsole::SetPassword(const UString &
#ifndef _NO_CRYPTO
password
#endif
)
{
#ifndef _NO_CRYPTO
PasswordIsDefined = true;
Password = password;
#endif
return S_OK;
}
*/
HRESULT CUpdateCallbackConsole::CryptoGetTextPassword2(Int32 *passwordIsDefined, BSTR *password)
{
COM_TRY_BEGIN
*password = NULL;
#ifdef _NO_CRYPTO
*passwordIsDefined = false;
return S_OK;
#else
if (!PasswordIsDefined)
{
if (AskPassword)
{
RINOK(GetPassword_HRESULT(_so, Password));
PasswordIsDefined = true;
}
}
*passwordIsDefined = BoolToInt(PasswordIsDefined);
return StringToBstr(Password, password);
#endif
COM_TRY_END
}
HRESULT CUpdateCallbackConsole::CryptoGetTextPassword(BSTR *password)
{
COM_TRY_BEGIN
*password = NULL;
#ifdef _NO_CRYPTO
return E_NOTIMPL;
#else
if (!PasswordIsDefined)
{
{
RINOK(GetPassword_HRESULT(_so, Password))
PasswordIsDefined = true;
}
}
return StringToBstr(Password, password);
#endif
COM_TRY_END
}
HRESULT CUpdateCallbackConsole::ShowDeleteFile(const wchar_t *name, bool /* isDir */)
{
if (StdOutMode)
return S_OK;
if (LogLevel > 7)
{
if (!name || name[0] == 0)
name = kEmptyFileAlias;
return PrintProgress(name, "D", true);
}
return S_OK;
}

View File

@@ -0,0 +1,127 @@
// UpdateCallbackConsole.h
#ifndef __UPDATE_CALLBACK_CONSOLE_H
#define __UPDATE_CALLBACK_CONSOLE_H
#include "../../../Common/StdOutStream.h"
#include "../Common/Update.h"
#include "PercentPrinter.h"
struct CErrorPathCodes
{
FStringVector Paths;
CRecordVector<DWORD> Codes;
void AddError(const FString &path, DWORD systemError)
{
Paths.Add(path);
Codes.Add(systemError);
}
void Clear()
{
Paths.Clear();
Codes.Clear();
}
};
class CCallbackConsoleBase
{
protected:
CPercentPrinter _percent;
CStdOutStream *_so;
CStdOutStream *_se;
void CommonError(const FString &path, DWORD systemError, bool isWarning);
HRESULT ScanError_Base(const FString &path, DWORD systemError);
HRESULT OpenFileError_Base(const FString &name, DWORD systemError);
HRESULT ReadingFileError_Base(const FString &name, DWORD systemError);
public:
bool NeedPercents() const { return _percent._so != NULL; };
bool StdOutMode;
bool NeedFlush;
unsigned PercentsNameLevel;
unsigned LogLevel;
AString _tempA;
UString _tempU;
CCallbackConsoleBase():
StdOutMode(false),
NeedFlush(false),
PercentsNameLevel(1),
LogLevel(0),
NumNonOpenFiles(0)
{}
void SetWindowWidth(unsigned width) { _percent.MaxLen = width - 1; }
void Init(CStdOutStream *outStream, CStdOutStream *errorStream, CStdOutStream *percentStream)
{
FailedFiles.Clear();
_so = outStream;
_se = errorStream;
_percent._so = percentStream;
}
void ClosePercents2()
{
if (NeedPercents())
_percent.ClosePrint(true);
}
void ClosePercents_for_so()
{
if (NeedPercents() && _so == _percent._so)
_percent.ClosePrint(false);
}
CErrorPathCodes FailedFiles;
CErrorPathCodes ScanErrors;
UInt64 NumNonOpenFiles;
HRESULT PrintProgress(const wchar_t *name, const char *command, bool showInLog);
};
class CUpdateCallbackConsole: public IUpdateCallbackUI2, public CCallbackConsoleBase
{
// void PrintPropPair(const char *name, const wchar_t *val);
public:
bool DeleteMessageWasShown;
#ifndef _NO_CRYPTO
bool PasswordIsDefined;
UString Password;
bool AskPassword;
#endif
CUpdateCallbackConsole():
DeleteMessageWasShown(false)
#ifndef _NO_CRYPTO
, PasswordIsDefined(false)
, AskPassword(false)
#endif
{}
virtual ~CUpdateCallbackConsole() {}
/*
void Init(CStdOutStream *outStream)
{
CCallbackConsoleBase::Init(outStream);
}
*/
// ~CUpdateCallbackConsole() { if (NeedPercents()) _percent.ClosePrint(); }
INTERFACE_IUpdateCallbackUI2(;)
};
#endif

View File

@@ -0,0 +1,110 @@
// UserInputUtils.cpp
#include "StdAfx.h"
#include "../../../Common/StdInStream.h"
#include "../../../Common/StringConvert.h"
#include "UserInputUtils.h"
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 * const kFirstQuestionMessage = "? ";
static const char * const 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)
{
if (outStream)
*outStream << kFirstQuestionMessage;
for (;;)
{
if (outStream)
{
*outStream << kHelpQuestionMessage;
outStream->Flush();
}
AString scannedString;
if (!g_StdIn.ScanAStringUntilNewLine(scannedString))
return NUserAnswerMode::kError;
if (g_StdIn.Error())
return NUserAnswerMode::kError;
scannedString.Trim();
if (scannedString.IsEmpty() && g_StdIn.Eof())
return NUserAnswerMode::kEof;
if (scannedString.Len() == 1)
switch (::MyCharLower_Ascii(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;
}
}
}
#ifdef _WIN32
#ifndef UNDER_CE
#define MY_DISABLE_ECHO
#endif
#endif
static bool GetPassword(CStdOutStream *outStream, UString &psw)
{
if (outStream)
{
*outStream << "\nEnter password"
#ifdef MY_DISABLE_ECHO
" (will not be echoed)"
#endif
":";
outStream->Flush();
}
#ifdef MY_DISABLE_ECHO
HANDLE console = GetStdHandle(STD_INPUT_HANDLE);
bool wasChanged = false;
DWORD mode = 0;
if (console != INVALID_HANDLE_VALUE && console != 0)
if (GetConsoleMode(console, &mode))
wasChanged = (SetConsoleMode(console, mode & ~(DWORD)ENABLE_ECHO_INPUT) != 0);
bool res = g_StdIn.ScanUStringUntilNewLine(psw);
if (wasChanged)
SetConsoleMode(console, mode);
#else
bool res = g_StdIn.ScanUStringUntilNewLine(psw);
#endif
if (outStream)
{
*outStream << endl;
outStream->Flush();
}
return res;
}
HRESULT GetPassword_HRESULT(CStdOutStream *outStream, UString &psw)
{
if (!GetPassword(outStream, psw))
return E_INVALIDARG;
if (g_StdIn.Error())
return E_FAIL;
if (g_StdIn.Eof() && psw.IsEmpty())
return E_ABORT;
return S_OK;
}

View File

@@ -0,0 +1,27 @@
// UserInputUtils.h
#ifndef __USER_INPUT_UTILS_H
#define __USER_INPUT_UTILS_H
#include "../../../Common/StdOutStream.h"
namespace NUserAnswerMode {
enum EEnum
{
kYes,
kNo,
kYesAll,
kNoAll,
kAutoRenameAll,
kQuit,
kEof,
kError
};
}
NUserAnswerMode::EEnum ScanUserYesNoAllQuit(CStdOutStream *outStream);
// bool GetPassword(CStdOutStream *outStream, UString &psw);
HRESULT GetPassword_HRESULT(CStdOutStream *outStream, UString &psw);
#endif

View File

@@ -0,0 +1,65 @@
PROG = 7z.exe
CFLAGS = $(CFLAGS) \
-DEXTERNAL_CODECS \
COMMON_OBJS = \
$O\CommandLineParser.obj \
$O\CRC.obj \
$O\IntToString.obj \
$O\ListFileUtils.obj \
$O\NewHandler.obj \
$O\StdInStream.obj \
$O\StdOutStream.obj \
$O\MyString.obj \
$O\StringConvert.obj \
$O\StringToInt.obj \
$O\UTFConvert.obj \
$O\MyVector.obj \
$O\Wildcard.obj \
WIN_OBJS = \
$O\DLL.obj \
$O\ErrorMsg.obj \
$O\FileDir.obj \
$O\FileFind.obj \
$O\FileIO.obj \
$O\FileLink.obj \
$O\FileName.obj \
$O\FileSystem.obj \
$O\MemoryLock.obj \
$O\PropVariant.obj \
$O\PropVariantConv.obj \
$O\Registry.obj \
$O\System.obj \
$O\SystemInfo.obj \
$O\TimeUtils.obj \
7ZIP_COMMON_OBJS = \
$O\CreateCoder.obj \
$O\FilePathAutoRename.obj \
$O\FileStreams.obj \
$O\FilterCoder.obj \
$O\LimitedStreams.obj \
$O\MethodProps.obj \
$O\ProgressUtils.obj \
$O\PropId.obj \
$O\StreamObjects.obj \
$O\StreamUtils.obj \
$O\UniqBlocks.obj \
AR_COMMON_OBJS = \
$O\OutStreamWithCRC.obj \
COMPRESS_OBJS = \
$O\CopyCoder.obj \
C_OBJS = $(C_OBJS) \
$O\Alloc.obj \
$O\CpuArch.obj \
$O\Sort.obj \
$O\Threads.obj \
!include "../../Crc.mak"
!include "Console.mak"
!include "../../7zip.mak"

View File

@@ -0,0 +1,171 @@
PROG = 7z
IS_NOT_STANDALONE = 1
# IS_X64 = 1
# USE_ASM = 1
# ST_MODE = 1
LOCAL_FLAGS_ST =
MT_OBJS =
ifdef ST_MODE
LOCAL_FLAGS_ST = -D_7ZIP_ST
ifdef SystemDrive
MT_OBJS = \
$O/Threads.o \
endif
else
MT_OBJS = \
$O/Synchronization.o \
$O/Threads.o \
endif
LOCAL_FLAGS_WIN=
ifdef SystemDrive
LOCAL_FLAGS_WIN = \
-D_7ZIP_LARGE_PAGES \
-DWIN_LONG_PATH \
-DSUPPORT_DEVICE_FILE \
SYS_OBJS = \
$O/FileSystem.o \
$O/Registry.o \
$O/MemoryLock.o \
$O/DllSecur.o \
$O/resource.o \
else
SYS_OBJS = \
$O/MyWindows.o \
endif
LOCAL_FLAGS = \
$(LOCAL_FLAGS_WIN) \
$(LOCAL_FLAGS_ST) \
-DEXTERNAL_CODECS \
CONSOLE_OBJS = \
$O/BenchCon.o \
$O/ConsoleClose.o \
$O/ExtractCallbackConsole.o \
$O/HashCon.o \
$O/List.o \
$O/Main.o \
$O/MainAr.o \
$O/OpenCallbackConsole.o \
$O/PercentPrinter.o \
$O/UpdateCallbackConsole.o \
$O/UserInputUtils.o \
UI_COMMON_OBJS = \
$O/ArchiveCommandLine.o \
$O/ArchiveExtractCallback.o \
$O/ArchiveOpenCallback.o \
$O/Bench.o \
$O/DefaultName.o \
$O/EnumDirItems.o \
$O/Extract.o \
$O/ExtractingFilePath.o \
$O/HashCalc.o \
$O/LoadCodecs.o \
$O/OpenArchive.o \
$O/PropIDUtils.o \
$O/SetProperties.o \
$O/SortUtils.o \
$O/TempFiles.o \
$O/Update.o \
$O/UpdateAction.o \
$O/UpdateCallback.o \
$O/UpdatePair.o \
$O/UpdateProduce.o \
COMMON_OBJS = \
$O/CommandLineParser.o \
$O/CRC.o \
$O/CrcReg.o \
$O/IntToString.o \
$O/ListFileUtils.o \
$O/NewHandler.o \
$O/StdInStream.o \
$O/StdOutStream.o \
$O/MyString.o \
$O/StringConvert.o \
$O/StringToInt.o \
$O/UTFConvert.o \
$O/MyVector.o \
$O/Wildcard.o \
WIN_OBJS = \
$O/DLL.o \
$O/ErrorMsg.o \
$O/FileDir.o \
$O/FileFind.o \
$O/FileIO.o \
$O/FileLink.o \
$O/FileName.o \
$O/PropVariant.o \
$O/PropVariantConv.o \
$O/System.o \
$O/SystemInfo.o \
$O/TimeUtils.o \
7ZIP_COMMON_OBJS = \
$O/CreateCoder.o \
$O/CWrappers.o \
$O/FilePathAutoRename.o \
$O/FileStreams.o \
$O/InBuffer.o \
$O/InOutTempBuffer.o \
$O/FilterCoder.o \
$O/LimitedStreams.o \
$O/MethodId.o \
$O/MethodProps.o \
$O/OffsetStream.o \
$O/OutBuffer.o \
$O/ProgressUtils.o \
$O/PropId.o \
$O/StreamObjects.o \
$O/StreamUtils.o \
$O/UniqBlocks.o \
COMPRESS_OBJS = \
$O/CopyCoder.o \
C_OBJS = \
$O/Alloc.o \
$O/CpuArch.o \
$O/Sort.o \
$O/7zCrc.o \
$O/7zCrcOpt.o \
OBJS = \
$(C_OBJS) \
$(MT_OBJS) \
$(COMMON_OBJS) \
$(WIN_OBJS) \
$(SYS_OBJS) \
$(COMPRESS_OBJS) \
$(7ZIP_COMMON_OBJS) \
$(UI_COMMON_OBJS) \
$(CONSOLE_OBJS) \
include ../../7zip_gcc.mak

View File

@@ -0,0 +1,7 @@
#include "../../MyVersionInfo.rc"
MY_VERSION_INFO_APP("7-Zip Console" , "7z")
#ifndef UNDER_CE
1 24 MOVEABLE PURE "Console.manifest"
#endif

View File

@@ -0,0 +1,37 @@
// MyMessages.cpp
#include "StdAfx.h"
#include "MyMessages.h"
#include "../../../Windows/ErrorMsg.h"
#include "../../../Windows/ResourceString.h"
#include "../FileManager/LangUtils.h"
using namespace NWindows;
void ShowErrorMessage(HWND window, LPCWSTR message)
{
::MessageBoxW(window, message, L"7-Zip", MB_OK | MB_ICONSTOP);
}
void ShowErrorMessageHwndRes(HWND window, UINT resID)
{
ShowErrorMessage(window, LangString(resID));
}
void ShowErrorMessageRes(UINT resID)
{
ShowErrorMessageHwndRes(0, resID);
}
static void ShowErrorMessageDWORD(HWND window, DWORD errorCode)
{
ShowErrorMessage(window, NError::MyFormatMessage(errorCode));
}
void ShowLastErrorMessage(HWND window)
{
ShowErrorMessageDWORD(window, ::GetLastError());
}

View File

@@ -0,0 +1,16 @@
// MyMessages.h
#ifndef __MY_MESSAGES_H
#define __MY_MESSAGES_H
#include "../../../Common/MyString.h"
void ShowErrorMessage(HWND window, LPCWSTR message);
inline void ShowErrorMessage(LPCWSTR message) { ShowErrorMessage(0, message); }
void ShowErrorMessageHwndRes(HWND window, UInt32 langID);
void ShowErrorMessageRes(UInt32 langID);
void ShowLastErrorMessage(HWND window = 0);
#endif

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,21 @@
// BrowseDialog.h
#ifndef __BROWSE_DIALOG_H
#define __BROWSE_DIALOG_H
#include "../../../Common/MyString.h"
bool MyBrowseForFolder(HWND owner, LPCWSTR title, LPCWSTR path, UString &resultPath);
bool MyBrowseForFile(HWND owner, LPCWSTR title, LPCWSTR path, LPCWSTR filterDescription, LPCWSTR filter, UString &resultPath);
/* CorrectFsPath removes undesirable characters in names (dots and spaces at the end of file)
But it doesn't change "bad" name in any of the following cases:
- path is Super Path (with \\?\ prefix)
- path is relative and relBase is Super Path
- there is file or dir in filesystem with specified "bad" name */
bool CorrectFsPath(const UString &relBase, const UString &path, UString &result);
bool Dlg_CreateFolder(HWND wnd, UString &destName);
#endif

View File

@@ -0,0 +1,9 @@
#define IDD_BROWSE 95
#define IDL_BROWSE 100
#define IDT_BROWSE_FOLDER 101
#define IDE_BROWSE_PATH 102
#define IDC_BROWSE_FILTER 103
#define IDB_BROWSE_PARENT 110
#define IDB_BROWSE_CREATE_DIR 112

View File

@@ -0,0 +1,64 @@
// ComboDialog.cpp
#include "StdAfx.h"
#include "ComboDialog.h"
#include "../../../Windows/Control/Static.h"
#ifdef LANG
#include "LangUtils.h"
#endif
using namespace NWindows;
bool CComboDialog::OnInit()
{
#ifdef LANG
LangSetDlgItems(*this, NULL, 0);
#endif
_comboBox.Attach(GetItem(IDC_COMBO));
/*
// why it doesn't work ?
DWORD style = _comboBox.GetStyle();
if (Sorted)
style |= CBS_SORT;
else
style &= ~CBS_SORT;
_comboBox.SetStyle(style);
*/
SetText(Title);
NControl::CStatic staticContol;
staticContol.Attach(GetItem(IDT_COMBO));
staticContol.SetText(Static);
_comboBox.SetText(Value);
FOR_VECTOR (i, Strings)
_comboBox.AddString(Strings[i]);
NormalizeSize();
return CModalDialog::OnInit();
}
bool CComboDialog::OnSize(WPARAM /* wParam */, int xSize, int ySize)
{
int mx, my;
GetMargins(8, mx, my);
int bx1, bx2, by;
GetItemSizes(IDCANCEL, bx1, by);
GetItemSizes(IDOK, bx2, by);
int y = ySize - my - by;
int x = xSize - mx - bx1;
InvalidateRect(NULL);
MoveItem(IDCANCEL, x, y, bx1, by);
MoveItem(IDOK, x - mx - bx2, y, bx2, by);
ChangeSubWindowSizeX(_comboBox, xSize - mx * 2);
return false;
}
void CComboDialog::OnOK()
{
_comboBox.GetText(Value);
CModalDialog::OnOK();
}

View File

@@ -0,0 +1,28 @@
// ComboDialog.h
#ifndef __COMBO_DIALOG_H
#define __COMBO_DIALOG_H
#include "../../../Windows/Control/ComboBox.h"
#include "../../../Windows/Control/Dialog.h"
#include "ComboDialogRes.h"
class CComboDialog: public NWindows::NControl::CModalDialog
{
NWindows::NControl::CComboBox _comboBox;
virtual void OnOK();
virtual bool OnInit();
virtual bool OnSize(WPARAM wParam, int xSize, int ySize);
public:
// bool Sorted;
UString Title;
UString Static;
UString Value;
UStringVector Strings;
// CComboDialog(): Sorted(false) {};
INT_PTR Create(HWND parentWindow = 0) { return CModalDialog::Create(IDD_COMBO, parentWindow); }
};
#endif

View File

@@ -0,0 +1,4 @@
#define IDD_COMBO 98
#define IDT_COMBO 100
#define IDC_COMBO 101

View File

@@ -0,0 +1,16 @@
// DialogSize.h
#ifndef __DIALOG_SIZE_H
#define __DIALOG_SIZE_H
#include "../../../Windows/Control/Dialog.h"
#ifdef UNDER_CE
#define BIG_DIALOG_SIZE(x, y) bool isBig = NWindows::NControl::IsDialogSizeOK(x, y);
#define SIZED_DIALOG(big) (isBig ? big : big ## _2)
#else
#define BIG_DIALOG_SIZE(x, y)
#define SIZED_DIALOG(big) big
#endif
#endif

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,326 @@
// ExtractCallback.h
#ifndef __EXTRACT_CALLBACK_H
#define __EXTRACT_CALLBACK_H
#include "../../../../C/Alloc.h"
#include "../../../Common/MyCom.h"
#include "../../../Common/StringConvert.h"
#ifndef _SFX
#include "../Agent/IFolderArchive.h"
#endif
#include "../Common/ArchiveExtractCallback.h"
#include "../Common/ArchiveOpenCallback.h"
#ifndef _NO_CRYPTO
#include "../../IPassword.h"
#endif
#ifndef _SFX
#include "IFolder.h"
#endif
#include "ProgressDialog2.h"
#ifdef LANG
#include "LangUtils.h"
#endif
#ifndef _SFX
class CGrowBuf
{
Byte *_items;
size_t _size;
CLASS_NO_COPY(CGrowBuf);
public:
bool ReAlloc_KeepData(size_t newSize, size_t keepSize)
{
void *buf = MyAlloc(newSize);
if (!buf)
return false;
if (keepSize != 0)
memcpy(buf, _items, keepSize);
MyFree(_items);
_items = (Byte *)buf;
_size = newSize;
return true;
}
CGrowBuf(): _items(0), _size(0) {}
~CGrowBuf() { MyFree(_items); }
operator Byte *() { return _items; }
operator const Byte *() const { return _items; }
size_t Size() const { return _size; }
};
struct CVirtFile
{
CGrowBuf Data;
UInt64 Size; // real size
UInt64 ExpectedSize; // the size from props request. 0 if unknown
UString Name;
bool CTimeDefined;
bool ATimeDefined;
bool MTimeDefined;
bool AttribDefined;
bool IsDir;
bool IsAltStream;
DWORD Attrib;
FILETIME CTime;
FILETIME ATime;
FILETIME MTime;
CVirtFile():
CTimeDefined(false),
ATimeDefined(false),
MTimeDefined(false),
AttribDefined(false),
IsDir(false),
IsAltStream(false) {}
};
class CVirtFileSystem:
public ISequentialOutStream,
public CMyUnknownImp
{
UInt64 _totalAllocSize;
size_t _pos;
unsigned _numFlushed;
bool _fileIsOpen;
bool _fileMode;
COutFileStream *_outFileStreamSpec;
CMyComPtr<ISequentialOutStream> _outFileStream;
public:
CObjectVector<CVirtFile> Files;
UInt64 MaxTotalAllocSize;
FString DirPrefix;
CVirtFile &AddNewFile()
{
if (!Files.IsEmpty())
{
MaxTotalAllocSize -= Files.Back().Data.Size();
}
return Files.AddNew();
}
HRESULT CloseMemFile()
{
if (_fileMode)
{
return FlushToDisk(true);
}
CVirtFile &file = Files.Back();
if (file.Data.Size() != file.Size)
{
file.Data.ReAlloc_KeepData((size_t)file.Size, (size_t)file.Size);
}
return S_OK;
}
bool IsStreamInMem() const
{
if (_fileMode)
return false;
if (Files.Size() < 1 || /* Files[0].IsAltStream || */ Files[0].IsDir)
return false;
return true;
}
size_t GetMemStreamWrittenSize() const { return _pos; }
CVirtFileSystem(): _outFileStreamSpec(NULL), MaxTotalAllocSize((UInt64)0 - 1) {}
void Init()
{
_totalAllocSize = 0;
_fileMode = false;
_pos = 0;
_numFlushed = 0;
_fileIsOpen = false;
}
HRESULT CloseFile(const FString &path);
HRESULT FlushToDisk(bool closeLast);
size_t GetPos() const { return _pos; }
MY_UNKNOWN_IMP
STDMETHOD(Write)(const void *data, UInt32 size, UInt32 *processedSize);
};
#endif
class CExtractCallbackImp:
public IExtractCallbackUI, // it includes IFolderArchiveExtractCallback
public IOpenCallbackUI,
public IFolderArchiveExtractCallback2,
#ifndef _SFX
public IFolderOperationsExtractCallback,
public IFolderExtractToStreamCallback,
public ICompressProgressInfo,
#endif
#ifndef _NO_CRYPTO
public ICryptoGetTextPassword,
#endif
public CMyUnknownImp
{
HRESULT MessageError(const char *message, const FString &path);
void Add_ArchiveName_Error();
public:
MY_QUERYINTERFACE_BEGIN2(IFolderArchiveExtractCallback)
MY_QUERYINTERFACE_ENTRY(IFolderArchiveExtractCallback2)
#ifndef _SFX
MY_QUERYINTERFACE_ENTRY(IFolderOperationsExtractCallback)
MY_QUERYINTERFACE_ENTRY(IFolderExtractToStreamCallback)
MY_QUERYINTERFACE_ENTRY(ICompressProgressInfo)
#endif
#ifndef _NO_CRYPTO
MY_QUERYINTERFACE_ENTRY(ICryptoGetTextPassword)
#endif
MY_QUERYINTERFACE_END
MY_ADDREF_RELEASE
INTERFACE_IProgress(;)
INTERFACE_IOpenCallbackUI(;)
INTERFACE_IFolderArchiveExtractCallback(;)
INTERFACE_IFolderArchiveExtractCallback2(;)
// STDMETHOD(SetTotalFiles)(UInt64 total);
// STDMETHOD(SetCompletedFiles)(const UInt64 *value);
INTERFACE_IExtractCallbackUI(;)
#ifndef _SFX
// IFolderOperationsExtractCallback
STDMETHOD(AskWrite)(
const wchar_t *srcPath,
Int32 srcIsFolder,
const FILETIME *srcTime,
const UInt64 *srcSize,
const wchar_t *destPathRequest,
BSTR *destPathResult,
Int32 *writeAnswer);
STDMETHOD(ShowMessage)(const wchar_t *message);
STDMETHOD(SetCurrentFilePath)(const wchar_t *filePath);
STDMETHOD(SetNumFiles)(UInt64 numFiles);
INTERFACE_IFolderExtractToStreamCallback(;)
STDMETHOD(SetRatioInfo)(const UInt64 *inSize, const UInt64 *outSize);
#endif
// ICryptoGetTextPassword
#ifndef _NO_CRYPTO
STDMETHOD(CryptoGetTextPassword)(BSTR *password);
#endif
private:
UString _currentArchivePath;
bool _needWriteArchivePath;
UString _currentFilePath;
bool _isFolder;
bool _isAltStream;
UInt64 _curSize;
bool _curSizeDefined;
UString _filePath;
// bool _extractMode;
// bool _testMode;
bool _newVirtFileWasAdded;
bool _needUpdateStat;
HRESULT SetCurrentFilePath2(const wchar_t *filePath);
void AddError_Message(LPCWSTR message);
#ifndef _SFX
bool _hashStreamWasUsed;
COutStreamWithHash *_hashStreamSpec;
CMyComPtr<ISequentialOutStream> _hashStream;
IHashCalc *_hashCalc; // it's for stat in Test operation
#endif
public:
#ifndef _SFX
CVirtFileSystem *VirtFileSystemSpec;
CMyComPtr<ISequentialOutStream> VirtFileSystem;
#endif
bool ProcessAltStreams;
bool StreamMode;
CProgressDialog *ProgressDialog;
#ifndef _SFX
UInt64 NumFolders;
UInt64 NumFiles;
bool NeedAddFile;
#endif
UInt32 NumArchiveErrors;
bool ThereAreMessageErrors;
NExtract::NOverwriteMode::EEnum OverwriteMode;
#ifndef _NO_CRYPTO
bool PasswordIsDefined;
bool PasswordWasAsked;
UString Password;
#endif
UString _lang_Extracting;
UString _lang_Testing;
UString _lang_Skipping;
UString _lang_Empty;
bool _totalFilesDefined;
bool _totalBytesDefined;
bool MultiArcMode;
CExtractCallbackImp():
#ifndef _SFX
_hashCalc(NULL),
#endif
ProcessAltStreams(true),
StreamMode(false),
OverwriteMode(NExtract::NOverwriteMode::kAsk),
#ifndef _NO_CRYPTO
PasswordIsDefined(false),
PasswordWasAsked(false),
#endif
_totalFilesDefined(false),
_totalBytesDefined(false),
MultiArcMode(false)
{}
~CExtractCallbackImp();
void Init();
#ifndef _SFX
void SetHashCalc(IHashCalc *hashCalc) { _hashCalc = hashCalc; }
void SetHashMethods(IHashCalc *hash)
{
if (!hash)
return;
_hashStreamSpec = new COutStreamWithHash;
_hashStream = _hashStreamSpec;
_hashStreamSpec->_hash = hash;
}
#endif
bool IsOK() const { return NumArchiveErrors == 0 && !ThereAreMessageErrors; }
};
#endif

View File

@@ -0,0 +1,28 @@
// FormatUtils.cpp
#include "StdAfx.h"
#include "../../../Common/IntToString.h"
#include "FormatUtils.h"
#include "LangUtils.h"
UString NumberToString(UInt64 number)
{
wchar_t numberString[32];
ConvertUInt64ToString(number, numberString);
return numberString;
}
UString MyFormatNew(const UString &format, const UString &argument)
{
UString result = format;
result.Replace(L"{0}", argument);
return result;
}
UString MyFormatNew(UINT resourceID, const UString &argument)
{
return MyFormatNew(LangString(resourceID), argument);
}

View File

@@ -0,0 +1,14 @@
// FormatUtils.h
#ifndef __FORMAT_UTILS_H
#define __FORMAT_UTILS_H
#include "../../../Common/MyTypes.h"
#include "../../../Common/MyString.h"
UString NumberToString(UInt64 number);
UString MyFormatNew(const UString &format, const UString &argument);
UString MyFormatNew(UINT resourceID, const UString &argument);
#endif

View File

@@ -0,0 +1,40 @@
// LangUtils.h
#ifndef __LANG_UTILS_H
#define __LANG_UTILS_H
#include "../../../Windows/ResourceString.h"
#ifdef LANG
extern UString g_LangID;
struct CIDLangPair
{
UInt32 ControlID;
UInt32 LangID;
};
void ReloadLang();
void LoadLangOneTime();
FString GetLangDirPrefix();
void LangSetDlgItemText(HWND dialog, UInt32 controlID, UInt32 langID);
void LangSetDlgItems(HWND dialog, const UInt32 *ids, unsigned numItems);
void LangSetDlgItems_Colon(HWND dialog, const UInt32 *ids, unsigned numItems);
void LangSetWindowText(HWND window, UInt32 langID);
UString LangString(UInt32 langID);
void AddLangString(UString &s, UInt32 langID);
void LangString(UInt32 langID, UString &dest);
void LangString_OnlyFromLangFile(UInt32 langID, UString &dest);
#else
inline UString LangString(UInt32 langID) { return NWindows::MyLoadString(langID); }
inline void LangString(UInt32 langID, UString &dest) { NWindows::MyLoadString(langID, dest); }
inline void AddLangString(UString &s, UInt32 langID) { s += NWindows::MyLoadString(langID); }
#endif
#endif

Some files were not shown because too many files have changed in this diff Show More