chore: initial commit (extracted from Launchers monorepo)
Plugin: ns7zip v2.0.0 Architectures: x86-ansi, x86-unicode, amd64-unicode License: LGPL-2.1-or-later
This commit is contained in:
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,170 @@
|
||||
// ArchiveCommandLine.h
|
||||
|
||||
#ifndef ZIP7_INC_ARCHIVE_COMMAND_LINE_H
|
||||
#define ZIP7_INC_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 CaseSensitive_Change;
|
||||
bool CaseSensitive;
|
||||
|
||||
bool IsInTerminal;
|
||||
bool IsStdOutTerminal;
|
||||
bool IsStdErrTerminal;
|
||||
bool StdInMode;
|
||||
bool StdOutMode;
|
||||
bool EnableHeaders;
|
||||
bool DisablePercents;
|
||||
|
||||
|
||||
bool YesToAll;
|
||||
bool ShowDialog;
|
||||
bool TechMode;
|
||||
bool ShowTime;
|
||||
CBoolPair ListPathSeparatorSlash;
|
||||
|
||||
CBoolPair NtSecurity;
|
||||
CBoolPair AltStreams;
|
||||
CBoolPair HardLinks;
|
||||
CBoolPair SymLinks;
|
||||
|
||||
CBoolPair StoreOwnerId;
|
||||
CBoolPair StoreOwnerName;
|
||||
|
||||
AString ListFields;
|
||||
|
||||
int ConsoleCodePage;
|
||||
|
||||
NWildcard::CCensor Censor;
|
||||
|
||||
CArcCommand Command;
|
||||
UString ArchiveName;
|
||||
|
||||
#ifndef Z7_NO_CRYPTO
|
||||
bool PasswordEnabled;
|
||||
UString Password;
|
||||
#endif
|
||||
|
||||
UStringVector HashMethods;
|
||||
// UString HashFilePath;
|
||||
|
||||
// bool AppendName;
|
||||
// UStringVector ArchivePathsSorted;
|
||||
// UStringVector ArchivePathsFullSorted;
|
||||
NWildcard::CCensor arcCensor;
|
||||
UString ArcName_for_StdInMode;
|
||||
|
||||
CObjectVector<CProperty> Properties;
|
||||
|
||||
CExtractOptionsBase ExtractOptions;
|
||||
|
||||
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),
|
||||
CaseSensitive_Change(false),
|
||||
CaseSensitive(false),
|
||||
|
||||
IsInTerminal(false),
|
||||
IsStdOutTerminal(false),
|
||||
IsStdErrTerminal(false),
|
||||
|
||||
StdInMode(false),
|
||||
StdOutMode(false),
|
||||
|
||||
EnableHeaders(false),
|
||||
DisablePercents(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)
|
||||
{
|
||||
ListPathSeparatorSlash.Val =
|
||||
#ifdef _WIN32
|
||||
false;
|
||||
#else
|
||||
true;
|
||||
#endif
|
||||
}
|
||||
};
|
||||
|
||||
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
@@ -0,0 +1,641 @@
|
||||
// ArchiveExtractCallback.h
|
||||
|
||||
#ifndef ZIP7_INC_ARCHIVE_EXTRACT_CALLBACK_H
|
||||
#define ZIP7_INC_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 Z7_SFX
|
||||
|
||||
Z7_CLASS_IMP_NOQIB_1(
|
||||
COutStreamWithHash
|
||||
, ISequentialOutStream
|
||||
)
|
||||
bool _calculate;
|
||||
CMyComPtr<ISequentialOutStream> _stream;
|
||||
UInt64 _size;
|
||||
public:
|
||||
IHashCalc *_hash;
|
||||
|
||||
void SetStream(ISequentialOutStream *stream) { _stream = stream; }
|
||||
void ReleaseStream() { _stream.Release(); }
|
||||
void Init(bool calculate = true)
|
||||
{
|
||||
InitCRC();
|
||||
_size = 0;
|
||||
_calculate = calculate;
|
||||
}
|
||||
void EnableCalc(bool calculate) { _calculate = calculate; }
|
||||
void InitCRC() { _hash->InitForNewFile(); }
|
||||
UInt64 GetSize() const { return _size; }
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
struct CExtractNtOptions
|
||||
{
|
||||
CBoolPair NtSecurity;
|
||||
CBoolPair SymLinks;
|
||||
CBoolPair HardLinks;
|
||||
CBoolPair AltStreams;
|
||||
bool ReplaceColonForAltStream;
|
||||
bool WriteToAltStreamIfColon;
|
||||
|
||||
bool ExtractOwner;
|
||||
|
||||
bool PreAllocateOutFile;
|
||||
|
||||
// used for hash arcs only, when we open external files
|
||||
bool PreserveATime;
|
||||
bool OpenShareForWrite;
|
||||
|
||||
unsigned SymLinks_DangerousLevel;
|
||||
|
||||
UInt64 MemLimit;
|
||||
|
||||
CExtractNtOptions():
|
||||
ReplaceColonForAltStream(false),
|
||||
WriteToAltStreamIfColon(false),
|
||||
ExtractOwner(false),
|
||||
PreserveATime(false),
|
||||
OpenShareForWrite(false),
|
||||
SymLinks_DangerousLevel(5),
|
||||
MemLimit((UInt64)(Int64)-1)
|
||||
{
|
||||
SymLinks.Val = true;
|
||||
HardLinks.Val = true;
|
||||
AltStreams.Val = true;
|
||||
|
||||
PreAllocateOutFile =
|
||||
#ifdef _WIN32
|
||||
true;
|
||||
#else
|
||||
false;
|
||||
#endif
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
#ifndef Z7_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 CFiTimesCAM
|
||||
{
|
||||
CFiTime CTime;
|
||||
CFiTime ATime;
|
||||
CFiTime MTime;
|
||||
|
||||
bool CTime_Defined;
|
||||
bool ATime_Defined;
|
||||
bool MTime_Defined;
|
||||
|
||||
bool IsSomeTimeDefined() const
|
||||
{
|
||||
return
|
||||
CTime_Defined |
|
||||
ATime_Defined |
|
||||
MTime_Defined;
|
||||
}
|
||||
bool SetDirTime_to_FS(CFSTR path) const;
|
||||
#ifdef SUPPORT_LINKS
|
||||
bool SetLinkFileTime_to_FS(CFSTR path) const;
|
||||
#endif
|
||||
};
|
||||
|
||||
struct CDirPathTime: public CFiTimesCAM
|
||||
{
|
||||
FString Path;
|
||||
|
||||
bool SetDirTime_to_FS_2() const { return SetDirTime_to_FS(Path); }
|
||||
};
|
||||
|
||||
|
||||
#ifdef SUPPORT_LINKS
|
||||
|
||||
enum ELinkType
|
||||
{
|
||||
k_LinkType_HardLink,
|
||||
k_LinkType_PureSymLink,
|
||||
k_LinkType_Junction,
|
||||
k_LinkType_WSL
|
||||
// , k_LinkType_CopyLink;
|
||||
};
|
||||
|
||||
|
||||
struct CLinkInfo
|
||||
{
|
||||
ELinkType LinkType;
|
||||
bool isRelative;
|
||||
// if (isRelative == false), then (LinkPath) is relative to root folder of archive
|
||||
// if (isRelative == true ), then (LinkPath) is relative to current item
|
||||
bool isWindowsPath;
|
||||
UString LinkPath;
|
||||
|
||||
bool Is_HardLink() const { return LinkType == k_LinkType_HardLink; }
|
||||
bool Is_AnySymLink() const { return LinkType != k_LinkType_HardLink; }
|
||||
|
||||
bool Is_WSL() const { return LinkType == k_LinkType_WSL; }
|
||||
|
||||
CLinkInfo():
|
||||
LinkType(k_LinkType_PureSymLink),
|
||||
isRelative(false),
|
||||
isWindowsPath(false)
|
||||
{}
|
||||
|
||||
void Clear()
|
||||
{
|
||||
LinkType = k_LinkType_PureSymLink;
|
||||
isRelative = false;
|
||||
isWindowsPath = false;
|
||||
LinkPath.Empty();
|
||||
}
|
||||
|
||||
bool Parse_from_WindowsReparseData(const Byte *data, size_t dataSize);
|
||||
bool Parse_from_LinuxData(const Byte *data, size_t dataSize);
|
||||
void Normalize_to_RelativeSafe(UStringVector &removePathParts);
|
||||
private:
|
||||
void Remove_AbsPathPrefixes();
|
||||
};
|
||||
|
||||
#endif // SUPPORT_LINKS
|
||||
|
||||
|
||||
|
||||
struct CProcessedFileInfo
|
||||
{
|
||||
CArcTime CTime;
|
||||
CArcTime ATime;
|
||||
CArcTime MTime;
|
||||
UInt32 Attrib;
|
||||
bool Attrib_Defined;
|
||||
|
||||
#ifndef _WIN32
|
||||
|
||||
struct COwnerInfo
|
||||
{
|
||||
bool Id_Defined;
|
||||
UInt32 Id;
|
||||
AString Name;
|
||||
|
||||
void Clear()
|
||||
{
|
||||
Id_Defined = false;
|
||||
Id = 0;
|
||||
Name.Empty();
|
||||
}
|
||||
};
|
||||
|
||||
COwnerInfo Owner;
|
||||
COwnerInfo Group;
|
||||
#endif
|
||||
|
||||
void Clear()
|
||||
{
|
||||
#ifndef _WIN32
|
||||
Attrib_Defined = false;
|
||||
Owner.Clear();
|
||||
#endif
|
||||
}
|
||||
|
||||
bool IsReparse() const
|
||||
{
|
||||
return (Attrib_Defined && (Attrib & FILE_ATTRIBUTE_REPARSE_POINT) != 0);
|
||||
}
|
||||
|
||||
bool IsLinuxSymLink() const
|
||||
{
|
||||
return (Attrib_Defined && 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;
|
||||
// 22.00 : we need type bits for (MY_LIN_S_IFLNK) for IsLinuxSymLink()
|
||||
a &= MY_LIN_S_IFMT;
|
||||
if (a == MY_LIN_S_IFLNK)
|
||||
Attrib |= (a << 16);
|
||||
#else
|
||||
Attrib = (a << 16) | FILE_ATTRIBUTE_UNIX_EXTENSION;
|
||||
#endif
|
||||
Attrib_Defined = true;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
#ifdef SUPPORT_LINKS
|
||||
|
||||
struct CPostLink
|
||||
{
|
||||
UInt32 Index_in_Arc;
|
||||
bool item_IsDir; // _item.IsDir
|
||||
UString item_Path; // _item.Path;
|
||||
UStringVector item_PathParts; // _item.PathParts;
|
||||
CProcessedFileInfo item_FileInfo; // _fi
|
||||
FString fullProcessedPath_from; // full file path in FS
|
||||
CLinkInfo LinkInfo;
|
||||
};
|
||||
|
||||
/*
|
||||
struct CPostLinks
|
||||
{
|
||||
void Clear()
|
||||
{
|
||||
Links.Clear();
|
||||
}
|
||||
};
|
||||
*/
|
||||
|
||||
#endif // SUPPORT_LINKS
|
||||
|
||||
|
||||
|
||||
class CArchiveExtractCallback Z7_final:
|
||||
public IArchiveExtractCallback,
|
||||
public IArchiveExtractCallbackMessage2,
|
||||
public ICryptoGetTextPassword,
|
||||
public ICompressProgressInfo,
|
||||
#ifndef Z7_SFX
|
||||
public IArchiveUpdateCallbackFile,
|
||||
public IArchiveGetDiskProperty,
|
||||
public IArchiveRequestMemoryUseCallback,
|
||||
#endif
|
||||
public CMyUnknownImp
|
||||
{
|
||||
/* IArchiveExtractCallback, */
|
||||
Z7_COM_QI_BEGIN2(IArchiveExtractCallbackMessage2)
|
||||
Z7_COM_QI_ENTRY(ICryptoGetTextPassword)
|
||||
Z7_COM_QI_ENTRY(ICompressProgressInfo)
|
||||
#ifndef Z7_SFX
|
||||
Z7_COM_QI_ENTRY(IArchiveUpdateCallbackFile)
|
||||
Z7_COM_QI_ENTRY(IArchiveGetDiskProperty)
|
||||
Z7_COM_QI_ENTRY(IArchiveRequestMemoryUseCallback)
|
||||
#endif
|
||||
Z7_COM_QI_END
|
||||
Z7_COM_ADDREF_RELEASE
|
||||
|
||||
Z7_IFACE_COM7_IMP(IProgress)
|
||||
Z7_IFACE_COM7_IMP(IArchiveExtractCallback)
|
||||
Z7_IFACE_COM7_IMP(IArchiveExtractCallbackMessage2)
|
||||
Z7_IFACE_COM7_IMP(ICryptoGetTextPassword)
|
||||
Z7_IFACE_COM7_IMP(ICompressProgressInfo)
|
||||
#ifndef Z7_SFX
|
||||
Z7_IFACE_COM7_IMP(IArchiveUpdateCallbackFile)
|
||||
Z7_IFACE_COM7_IMP(IArchiveGetDiskProperty)
|
||||
Z7_IFACE_COM7_IMP(IArchiveRequestMemoryUseCallback)
|
||||
#endif
|
||||
|
||||
// bool Write_CTime;
|
||||
// bool Write_ATime;
|
||||
// bool Write_MTime;
|
||||
bool _stdOutMode;
|
||||
bool _testMode;
|
||||
bool _removePartsForAltStreams;
|
||||
public:
|
||||
bool Is_elimPrefix_Mode;
|
||||
private:
|
||||
|
||||
const CArc *_arc;
|
||||
public:
|
||||
CExtractNtOptions _ntOptions;
|
||||
private:
|
||||
bool _encrypted;
|
||||
bool _isSplit;
|
||||
bool _curSize_Defined;
|
||||
bool _fileLength_WasSet;
|
||||
|
||||
bool _isRenamed;
|
||||
bool _extractMode;
|
||||
bool _is_SymLink_in_Data_Linux; // false = WIN32, true = LINUX.
|
||||
// _is_SymLink_in_Data_Linux is detected from Windows/Linux part of attributes of file.
|
||||
bool _needSetAttrib;
|
||||
bool _isSymLinkCreated;
|
||||
bool _itemFailure;
|
||||
bool _some_pathParts_wereRemoved;
|
||||
|
||||
bool _multiArchives;
|
||||
bool _keepAndReplaceEmptyDirPrefixes; // replace them to "_";
|
||||
#if defined(_WIN32) && !defined(UNDER_CE) && !defined(Z7_SFX)
|
||||
bool _saclEnabled;
|
||||
#endif
|
||||
|
||||
NExtract::NPathMode::EEnum _pathMode;
|
||||
NExtract::NOverwriteMode::EEnum _overwriteMode;
|
||||
|
||||
CMyComPtr<IFolderArchiveExtractCallback> _extractCallback2;
|
||||
const NWildcard::CCensorNode *_wildcardCensor; // we need wildcard for single pass mode (stdin)
|
||||
// CMyComPtr<ICompressProgressInfo> _compressProgress;
|
||||
// CMyComPtr<IArchiveExtractCallbackMessage2> _callbackMessage;
|
||||
CMyComPtr<IFolderArchiveExtractCallback2> _folderArchiveExtractCallback2;
|
||||
CMyComPtr<ICryptoGetTextPassword> _cryptoGetTextPassword;
|
||||
|
||||
FString _dirPathPrefix;
|
||||
public:
|
||||
FString _dirPathPrefix_Full;
|
||||
private:
|
||||
|
||||
#ifndef Z7_SFX
|
||||
|
||||
CMyComPtr<IFolderExtractToStreamCallback> ExtractToStreamCallback;
|
||||
CMyComPtr<IArchiveRequestMemoryUseCallback> _requestMemoryUseCallback;
|
||||
|
||||
#endif
|
||||
|
||||
CReadArcItem _item;
|
||||
FString _diskFilePath;
|
||||
|
||||
CProcessedFileInfo _fi;
|
||||
|
||||
UInt64 _position;
|
||||
UInt64 _curSize;
|
||||
UInt64 _fileLength_that_WasSet;
|
||||
UInt32 _index;
|
||||
|
||||
// #ifdef SUPPORT_ALT_STREAMS
|
||||
#if defined(_WIN32) && !defined(UNDER_CE)
|
||||
DWORD _altStream_NeedRestore_AttribVal;
|
||||
FString _altStream_NeedRestore_Attrib_for_parentFsPath;
|
||||
#endif
|
||||
// #endif
|
||||
|
||||
COutFileStream *_outFileStreamSpec;
|
||||
CMyComPtr<ISequentialOutStream> _outFileStream;
|
||||
|
||||
CByteBuffer _outMemBuf;
|
||||
CBufPtrSeqOutStream *_bufPtrSeqOutStream_Spec;
|
||||
CMyComPtr<ISequentialOutStream> _bufPtrSeqOutStream;
|
||||
|
||||
#ifndef Z7_SFX
|
||||
COutStreamWithHash *_hashStreamSpec;
|
||||
CMyComPtr<ISequentialOutStream> _hashStream;
|
||||
bool _hashStreamWasUsed;
|
||||
|
||||
bool _use_baseParentFolder_mode;
|
||||
UInt32 _baseParentFolder;
|
||||
#endif
|
||||
|
||||
UStringVector _removePathParts;
|
||||
|
||||
UInt64 _packTotal;
|
||||
UInt64 _progressTotal;
|
||||
// bool _progressTotal_Defined;
|
||||
|
||||
CObjectVector<CDirPathTime> _extractedFolders;
|
||||
|
||||
#ifndef _WIN32
|
||||
// CObjectVector<NWindows::NFile::NDir::CDelayedSymLink> _delayedSymLinks;
|
||||
#endif
|
||||
|
||||
void CreateComplexDirectory(
|
||||
const UStringVector &dirPathParts, bool isFinal, FString &fullPath);
|
||||
HRESULT GetTime(UInt32 index, PROPID propID, CArcTime &ft);
|
||||
HRESULT GetUnpackSize();
|
||||
|
||||
FString Hash_GetFullFilePath();
|
||||
|
||||
void SetAttrib() const;
|
||||
|
||||
public:
|
||||
HRESULT SendMessageError(const char *message, const FString &path) const;
|
||||
HRESULT SendMessageError_with_Error(HRESULT errorCode, const char *message, const FString &path) const;
|
||||
HRESULT SendMessageError_with_LastError(const char *message, const FString &path) const;
|
||||
HRESULT SendMessageError2(HRESULT errorCode, const char *message, const FString &path1, const FString &path2) const;
|
||||
HRESULT SendMessageError2_with_LastError(const char *message, const FString &path1, const FString &path2) const;
|
||||
|
||||
#if defined(_WIN32) && !defined(UNDER_CE) && !defined(Z7_SFX)
|
||||
NExtract::NZoneIdMode::EEnum ZoneMode;
|
||||
CByteBuffer ZoneBuf;
|
||||
#endif
|
||||
|
||||
CMyComPtr2_Create<ICompressProgressInfo, CLocalProgress> LocalProgressSpec;
|
||||
|
||||
UInt64 NumFolders;
|
||||
UInt64 NumFiles;
|
||||
UInt64 NumAltStreams;
|
||||
UInt64 UnpackSize;
|
||||
UInt64 AltStreams_UnpackSize;
|
||||
|
||||
FString DirPathPrefix_for_HashFiles;
|
||||
|
||||
CArchiveExtractCallback();
|
||||
|
||||
void InitForMulti(bool multiArchives,
|
||||
NExtract::NPathMode::EEnum pathMode,
|
||||
NExtract::NOverwriteMode::EEnum overwriteMode,
|
||||
NExtract::NZoneIdMode::EEnum zoneMode,
|
||||
bool keepAndReplaceEmptyDirPrefixes)
|
||||
{
|
||||
_multiArchives = multiArchives;
|
||||
_pathMode = pathMode;
|
||||
_overwriteMode = overwriteMode;
|
||||
#if defined(_WIN32) && !defined(UNDER_CE) && !defined(Z7_SFX)
|
||||
ZoneMode = zoneMode;
|
||||
#else
|
||||
UNUSED_VAR(zoneMode)
|
||||
#endif
|
||||
_keepAndReplaceEmptyDirPrefixes = keepAndReplaceEmptyDirPrefixes;
|
||||
NumFolders = NumFiles = NumAltStreams = UnpackSize = AltStreams_UnpackSize = 0;
|
||||
}
|
||||
|
||||
#ifndef Z7_SFX
|
||||
|
||||
void SetHashMethods(IHashCalc *hash)
|
||||
{
|
||||
if (!hash)
|
||||
return;
|
||||
_hashStreamSpec = new COutStreamWithHash;
|
||||
_hashStream = _hashStreamSpec;
|
||||
_hashStreamSpec->_hash = hash;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
void InitBeforeNewArchive();
|
||||
|
||||
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;
|
||||
CObjectVector<CPostLink> _postLinks;
|
||||
CLinkInfo _link;
|
||||
// const void *NtReparse_Data;
|
||||
// UInt32 NtReparse_Size;
|
||||
|
||||
// FString _copyFile_Path;
|
||||
// HRESULT MyCopyFile(ISequentialOutStream *outStream);
|
||||
HRESULT ReadLink();
|
||||
HRESULT SetLink(
|
||||
const FString &fullProcessedPath_from,
|
||||
const CLinkInfo &linkInfo,
|
||||
bool &linkWasSet);
|
||||
HRESULT SetPostLinks() const;
|
||||
|
||||
public:
|
||||
HRESULT CreateHardLink2(const FString &newFilePath,
|
||||
const FString &existFilePath, bool &link_was_Created) const;
|
||||
HRESULT DeleteLinkFileAlways_or_RemoveEmptyDir(const FString &path, bool checkThatFileIsEmpty) const;
|
||||
HRESULT PrepareHardLinks(const CRecordVector<UInt32> *realIndices); // NULL means all items
|
||||
#endif
|
||||
|
||||
private:
|
||||
|
||||
#ifdef SUPPORT_ALT_STREAMS
|
||||
CObjectVector<CIndexToPathPair> _renamedFiles;
|
||||
#endif
|
||||
|
||||
// call it after Init()
|
||||
|
||||
public:
|
||||
#ifndef Z7_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();
|
||||
|
||||
HRESULT CheckExistFile(FString &fullProcessedPath, bool &needExit);
|
||||
HRESULT GetExtractStream(CMyComPtr<ISequentialOutStream> &outStreamLoc, bool &needExit);
|
||||
HRESULT GetItem(UInt32 index);
|
||||
|
||||
HRESULT CloseFile();
|
||||
HRESULT CloseReparseAndFile();
|
||||
HRESULT SetDirsTimes();
|
||||
HRESULT SetSecurityInfo(UInt32 indexInArc, const FString &path) const;
|
||||
};
|
||||
|
||||
|
||||
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);
|
||||
|
||||
bool Is_ZoneId_StreamName(const wchar_t *s);
|
||||
void ReadZoneFile_Of_BaseFile(CFSTR fileName, CByteBuffer &buf);
|
||||
bool WriteZoneFile_To_BaseFile(CFSTR fileName, const CByteBuffer &buf);
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,176 @@
|
||||
// ArchiveName.cpp
|
||||
|
||||
#include "StdAfx.h"
|
||||
|
||||
#include "../../../../C/Sort.h"
|
||||
|
||||
#include "../../../Common/Wildcard.h"
|
||||
#include "../../../Common/StringToInt.h"
|
||||
|
||||
#include "../../../Windows/FileDir.h"
|
||||
#include "../../../Windows/FileName.h"
|
||||
|
||||
#include "ArchiveName.h"
|
||||
#include "ExtractingFilePath.h"
|
||||
|
||||
using namespace NWindows;
|
||||
using namespace NFile;
|
||||
|
||||
|
||||
static const char * const g_ArcExts =
|
||||
"7z"
|
||||
"\0" "zip"
|
||||
"\0" "tar"
|
||||
"\0" "wim"
|
||||
"\0";
|
||||
|
||||
static const char * const g_HashExts =
|
||||
"sha256"
|
||||
"\0";
|
||||
|
||||
|
||||
UString CreateArchiveName(
|
||||
const UStringVector &paths,
|
||||
bool isHash,
|
||||
const NFind::CFileInfo *fi,
|
||||
UString &baseName)
|
||||
{
|
||||
bool keepName = isHash;
|
||||
/*
|
||||
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 ("Archive");
|
||||
NFind::CFileInfo fi3;
|
||||
if (paths.Size() > 1)
|
||||
fi = NULL;
|
||||
if (!fi && paths.Size() != 0)
|
||||
{
|
||||
const UString &path = paths.Front();
|
||||
if (paths.Size() == 1)
|
||||
{
|
||||
if (fi3.Find(us2fs(path)))
|
||||
fi = &fi3;
|
||||
}
|
||||
else
|
||||
{
|
||||
// we try to use name of parent folder
|
||||
FString dirPrefix;
|
||||
if (NDir::GetOnlyDirPrefix(us2fs(path), dirPrefix))
|
||||
{
|
||||
if (!dirPrefix.IsEmpty() && IsPathSepar(dirPrefix.Back()))
|
||||
{
|
||||
#if defined(_WIN32) && !defined(UNDER_CE)
|
||||
if (NName::IsDriveRootPath_SuperAllowed(dirPrefix))
|
||||
{
|
||||
if (path != fs2us(dirPrefix))
|
||||
name = dirPrefix[dirPrefix.Len() - 3]; // only letter
|
||||
}
|
||||
else
|
||||
#endif
|
||||
{
|
||||
dirPrefix.DeleteBack();
|
||||
if (!dirPrefix.IsEmpty())
|
||||
{
|
||||
const int slash = dirPrefix.ReverseFind_PathSepar();
|
||||
if (slash >= 0 && slash != (int)dirPrefix.Len() - 1)
|
||||
name = dirPrefix.Ptr(slash + 1);
|
||||
else if (fi3.Find(dirPrefix))
|
||||
name = fs2us(fi3.Name);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (fi)
|
||||
{
|
||||
name = fs2us(fi->Name);
|
||||
if (!fi->IsDir() && !keepName)
|
||||
{
|
||||
const int dotPos = name.Find(L'.');
|
||||
if (dotPos > 0 && name.Find(L'.', (unsigned)dotPos + 1) < 0)
|
||||
name.DeleteFrom((unsigned)dotPos);
|
||||
}
|
||||
}
|
||||
name = Get_Correct_FsFile_Name(name);
|
||||
|
||||
CRecordVector<UInt32> ids;
|
||||
bool simple_IsAllowed = true;
|
||||
// for (int y = 0; y < 10000; y++) // for debug
|
||||
{
|
||||
// ids.Clear();
|
||||
UString n;
|
||||
|
||||
FOR_VECTOR (i, paths)
|
||||
{
|
||||
const UString &a = paths[i];
|
||||
const int slash = a.ReverseFind_PathSepar();
|
||||
// if (name.Len() >= a.Len() - slash + 1) continue;
|
||||
const wchar_t *s = a.Ptr(slash + 1);
|
||||
if (!IsPath1PrefixedByPath2(s, name))
|
||||
continue;
|
||||
s += name.Len();
|
||||
const char *exts = isHash ? g_HashExts : g_ArcExts;
|
||||
|
||||
for (;;)
|
||||
{
|
||||
const char *ext = exts;
|
||||
const unsigned len = MyStringLen(ext);
|
||||
if (len == 0)
|
||||
break;
|
||||
exts += len + 1;
|
||||
n = s;
|
||||
if (n.Len() <= len)
|
||||
continue;
|
||||
if (!StringsAreEqualNoCase_Ascii(n.RightPtr(len), ext))
|
||||
continue;
|
||||
n.DeleteFrom(n.Len() - len);
|
||||
if (n.Back() != '.')
|
||||
continue;
|
||||
n.DeleteBack();
|
||||
if (n.IsEmpty())
|
||||
{
|
||||
simple_IsAllowed = false;
|
||||
break;
|
||||
}
|
||||
if (n.Len() < 2)
|
||||
continue;
|
||||
if (n[0] != '_')
|
||||
continue;
|
||||
const wchar_t *end;
|
||||
const UInt32 v = ConvertStringToUInt32(n.Ptr(1), &end);
|
||||
if (*end != 0)
|
||||
continue;
|
||||
ids.Add(v);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
baseName = name;
|
||||
if (!simple_IsAllowed)
|
||||
{
|
||||
HeapSort(ids.NonConstData(), ids.Size());
|
||||
UInt32 v = 2;
|
||||
const unsigned num = ids.Size();
|
||||
for (unsigned i = 0; i < num; i++)
|
||||
{
|
||||
const UInt32 id = ids[i];
|
||||
if (id > v)
|
||||
break;
|
||||
if (id == v)
|
||||
v = id + 1;
|
||||
}
|
||||
name.Add_Char('_');
|
||||
name.Add_UInt32(v);
|
||||
}
|
||||
return name;
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
// ArchiveName.h
|
||||
|
||||
#ifndef ZIP7_INC_ARCHIVE_NAME_H
|
||||
#define ZIP7_INC_ARCHIVE_NAME_H
|
||||
|
||||
#include "../../../Windows/FileFind.h"
|
||||
|
||||
/* (fi != NULL) only if (paths.Size() == 1) */
|
||||
|
||||
UString CreateArchiveName(
|
||||
const UStringVector &paths,
|
||||
bool isHash,
|
||||
const NWindows::NFile::NFind::CFileInfo *fi,
|
||||
UString &baseName);
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,398 @@
|
||||
// ArchiveOpenCallback.cpp
|
||||
|
||||
#include "StdAfx.h"
|
||||
|
||||
#include "../../../Common/ComTry.h"
|
||||
|
||||
#include "../../../Windows/FileName.h"
|
||||
#include "../../../Windows/PropVariant.h"
|
||||
#include "../../../Windows/System.h"
|
||||
|
||||
#include "../../Common/StreamUtils.h"
|
||||
|
||||
#include "ArchiveOpenCallback.h"
|
||||
|
||||
// #define DEBUG_VOLUMES
|
||||
|
||||
#ifdef DEBUG_VOLUMES
|
||||
#include <stdio.h>
|
||||
#endif
|
||||
|
||||
|
||||
#ifdef DEBUG_VOLUMES
|
||||
#define PRF(x) x
|
||||
#else
|
||||
#define PRF(x)
|
||||
#endif
|
||||
|
||||
using namespace NWindows;
|
||||
|
||||
HRESULT COpenCallbackImp::Init2(const FString &folderPrefix, const FString &fileName)
|
||||
{
|
||||
Volumes.Init();
|
||||
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;
|
||||
}
|
||||
|
||||
Z7_COM7F_IMF(COpenCallbackImp::SetSubArchiveName(const wchar_t *name))
|
||||
{
|
||||
_subArchiveMode = true;
|
||||
_subArchiveName = name;
|
||||
// TotalSize = 0;
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
Z7_COM7F_IMF(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
|
||||
}
|
||||
|
||||
Z7_COM7F_IMF(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
|
||||
}
|
||||
|
||||
|
||||
Z7_COM7F_IMF(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
|
||||
default: break;
|
||||
}
|
||||
else
|
||||
switch (propID)
|
||||
{
|
||||
case kpidName: prop = fs2us(_fileInfo.Name); break;
|
||||
case kpidIsDir: prop = _fileInfo.IsDir(); break;
|
||||
case kpidSize: prop = _fileInfo.Size; break;
|
||||
case kpidAttrib: prop = (UInt32)_fileInfo.GetWinAttrib(); break;
|
||||
case kpidPosixAttrib: prop = (UInt32)_fileInfo.GetPosixAttrib(); break;
|
||||
case kpidCTime: PropVariant_SetFrom_FiTime(prop, _fileInfo.CTime); break;
|
||||
case kpidATime: PropVariant_SetFrom_FiTime(prop, _fileInfo.ATime); break;
|
||||
case kpidMTime: PropVariant_SetFrom_FiTime(prop, _fileInfo.MTime); break;
|
||||
default: break;
|
||||
}
|
||||
prop.Detach(value);
|
||||
return S_OK;
|
||||
COM_TRY_END
|
||||
}
|
||||
|
||||
|
||||
// ---------- CInFileStreamVol ----------
|
||||
|
||||
Z7_class_final(CInFileStreamVol):
|
||||
public IInStream
|
||||
, public IStreamGetSize
|
||||
, public CMyUnknownImp
|
||||
{
|
||||
Z7_IFACES_IMP_UNK_3(
|
||||
IInStream,
|
||||
ISequentialInStream,
|
||||
IStreamGetSize)
|
||||
public:
|
||||
unsigned FileIndex;
|
||||
COpenCallbackImp *OpenCallbackImp;
|
||||
CMyComPtr<IArchiveOpenCallback> OpenCallbackRef;
|
||||
|
||||
HRESULT EnsureOpen()
|
||||
{
|
||||
return OpenCallbackImp->Volumes.EnsureOpen(FileIndex);
|
||||
}
|
||||
|
||||
~CInFileStreamVol()
|
||||
{
|
||||
if (OpenCallbackRef)
|
||||
OpenCallbackImp->AtCloseFile(FileIndex);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
void CMultiStreams::InsertToList(unsigned index)
|
||||
{
|
||||
{
|
||||
CSubStream &s = Streams[index];
|
||||
s.Next = Head;
|
||||
s.Prev = -1;
|
||||
}
|
||||
if (Head != -1)
|
||||
Streams[(unsigned)Head].Prev = (int)index;
|
||||
else
|
||||
{
|
||||
// if (Tail != -1) throw 1;
|
||||
Tail = (int)index;
|
||||
}
|
||||
Head = (int)index;
|
||||
NumListItems++;
|
||||
}
|
||||
|
||||
// s must bee in List
|
||||
void CMultiStreams::RemoveFromList(CSubStream &s)
|
||||
{
|
||||
if (s.Next != -1) Streams[(unsigned)s.Next].Prev = s.Prev; else Tail = s.Prev;
|
||||
if (s.Prev != -1) Streams[(unsigned)s.Prev].Next = s.Next; else Head = s.Next;
|
||||
s.Next = -1; // optional
|
||||
s.Prev = -1; // optional
|
||||
NumListItems--;
|
||||
}
|
||||
|
||||
void CMultiStreams::CloseFile(unsigned index)
|
||||
{
|
||||
CSubStream &s = Streams[index];
|
||||
if (s.Stream)
|
||||
{
|
||||
s.Stream.Release();
|
||||
RemoveFromList(s);
|
||||
// s.InFile->Close();
|
||||
// s.IsOpen = false;
|
||||
#ifdef DEBUG_VOLUMES
|
||||
static int numClosing = 0;
|
||||
numClosing++;
|
||||
printf("\nCloseFile %u, total_closes = %u, num_open_files = %u\n", index, numClosing, NumListItems);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
void CMultiStreams::Init()
|
||||
{
|
||||
Head = -1;
|
||||
Tail = -1;
|
||||
NumListItems = 0;
|
||||
Streams.Clear();
|
||||
}
|
||||
|
||||
CMultiStreams::CMultiStreams():
|
||||
Head(-1),
|
||||
Tail(-1),
|
||||
NumListItems(0)
|
||||
{
|
||||
NumOpenFiles_AllowedMax = NSystem::Get_File_OPEN_MAX_Reduced_for_3_tasks();
|
||||
PRF(printf("\nNumOpenFiles_Limit = %u\n", NumOpenFiles_AllowedMax));
|
||||
}
|
||||
|
||||
|
||||
HRESULT CMultiStreams::PrepareToOpenNew()
|
||||
{
|
||||
if (NumListItems < NumOpenFiles_AllowedMax)
|
||||
return S_OK;
|
||||
if (Tail == -1)
|
||||
return E_FAIL;
|
||||
CMultiStreams::CSubStream &tailStream = Streams[(unsigned)Tail];
|
||||
RINOK(InStream_GetPos(tailStream.Stream, tailStream.LocalPos))
|
||||
CloseFile((unsigned)Tail);
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
|
||||
HRESULT CMultiStreams::EnsureOpen(unsigned index)
|
||||
{
|
||||
CMultiStreams::CSubStream &s = Streams[index];
|
||||
if (s.Stream)
|
||||
{
|
||||
if ((int)index != Head)
|
||||
{
|
||||
RemoveFromList(s);
|
||||
InsertToList(index);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
RINOK(PrepareToOpenNew())
|
||||
{
|
||||
CInFileStream *inFile = new CInFileStream;
|
||||
CMyComPtr<IInStream> inStreamTemp = inFile;
|
||||
if (!inFile->Open(s.Path))
|
||||
return GetLastError_noZero_HRESULT();
|
||||
s.FileSpec = inFile;
|
||||
s.Stream = s.FileSpec;
|
||||
InsertToList(index);
|
||||
}
|
||||
// s.IsOpen = true;
|
||||
if (s.LocalPos != 0)
|
||||
{
|
||||
RINOK(s.Stream->Seek((Int64)s.LocalPos, STREAM_SEEK_SET, &s.LocalPos))
|
||||
}
|
||||
#ifdef DEBUG_VOLUMES
|
||||
static int numOpens = 0;
|
||||
numOpens++;
|
||||
printf("\n-- %u, ReOpen, total_reopens = %u, num_open_files = %u\n", index, numOpens, NumListItems);
|
||||
#endif
|
||||
}
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
|
||||
Z7_COM7F_IMF(CInFileStreamVol::Read(void *data, UInt32 size, UInt32 *processedSize))
|
||||
{
|
||||
if (processedSize)
|
||||
*processedSize = 0;
|
||||
if (size == 0)
|
||||
return S_OK;
|
||||
RINOK(EnsureOpen())
|
||||
CMultiStreams::CSubStream &s = OpenCallbackImp->Volumes.Streams[FileIndex];
|
||||
PRF(printf("\n== %u, Read =%u \n", FileIndex, size));
|
||||
return s.Stream->Read(data, size, processedSize);
|
||||
}
|
||||
|
||||
Z7_COM7F_IMF(CInFileStreamVol::Seek(Int64 offset, UInt32 seekOrigin, UInt64 *newPosition))
|
||||
{
|
||||
// if (seekOrigin >= 3) return STG_E_INVALIDFUNCTION;
|
||||
RINOK(EnsureOpen())
|
||||
CMultiStreams::CSubStream &s = OpenCallbackImp->Volumes.Streams[FileIndex];
|
||||
PRF(printf("\n-- %u, Seek seekOrigin=%u Seek =%u\n", FileIndex, seekOrigin, (unsigned)offset));
|
||||
return s.Stream->Seek(offset, seekOrigin, newPosition);
|
||||
}
|
||||
|
||||
Z7_COM7F_IMF(CInFileStreamVol::GetSize(UInt64 *size))
|
||||
{
|
||||
RINOK(EnsureOpen())
|
||||
CMultiStreams::CSubStream &s = OpenCallbackImp->Volumes.Streams[FileIndex];
|
||||
return s.FileSpec->GetSize(size);
|
||||
}
|
||||
|
||||
|
||||
// from ArchiveExtractCallback.cpp
|
||||
bool IsSafePath(const UString &path);
|
||||
|
||||
Z7_COM7F_IMF(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 Z7_SFX
|
||||
|
||||
#ifdef _WIN32
|
||||
name2.Replace(L'/', WCHAR_PATH_SEPARATOR);
|
||||
#endif
|
||||
|
||||
// if (!allowAbsVolPaths)
|
||||
if (!IsSafePath(name2))
|
||||
return S_FALSE;
|
||||
|
||||
#ifdef _WIN32
|
||||
/* WIN32 allows wildcards in Find() function
|
||||
and doesn't allow wildcard in File.Open()
|
||||
so we can work without the following wildcard check here */
|
||||
if (name2.Find(L'*') >= 0)
|
||||
return S_FALSE;
|
||||
{
|
||||
unsigned startPos = 0;
|
||||
if (name2.IsPrefixedBy_Ascii_NoCase("\\\\?\\"))
|
||||
startPos = 3;
|
||||
if (name2.Find(L'?', startPos) >= 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;
|
||||
|
||||
CMultiStreams::CSubStream s;
|
||||
|
||||
{
|
||||
CInFileStream *inFile = new CInFileStream;
|
||||
CMyComPtr<IInStream> inStreamTemp = inFile;
|
||||
if (!inFile->Open(fullPath))
|
||||
return GetLastError_noZero_HRESULT();
|
||||
RINOK(Volumes.PrepareToOpenNew())
|
||||
s.FileSpec = inFile;
|
||||
s.Stream = s.FileSpec;
|
||||
s.Path = fullPath;
|
||||
// s.Size = _fileInfo.Size;
|
||||
// s.IsOpen = true;
|
||||
}
|
||||
|
||||
const unsigned fileIndex = Volumes.Streams.Add(s);
|
||||
Volumes.InsertToList(fileIndex);
|
||||
|
||||
FileSizes.Add(_fileInfo.Size);
|
||||
FileNames.Add(name2);
|
||||
FileNames_WasUsed.Add(true);
|
||||
|
||||
CInFileStreamVol *inFile = new CInFileStreamVol;
|
||||
CMyComPtr<IInStream> inStreamTemp = inFile;
|
||||
inFile->FileIndex = fileIndex;
|
||||
inFile->OpenCallbackImp = this;
|
||||
inFile->OpenCallbackRef = this;
|
||||
// TotalSize += _fileInfo.Size;
|
||||
*inStream = inStreamTemp.Detach();
|
||||
return S_OK;
|
||||
COM_TRY_END
|
||||
}
|
||||
|
||||
|
||||
#ifndef Z7_NO_CRYPTO
|
||||
Z7_COM7F_IMF(COpenCallbackImp::CryptoGetTextPassword(BSTR *password))
|
||||
{
|
||||
COM_TRY_BEGIN
|
||||
if (ReOpenCallback)
|
||||
{
|
||||
Z7_DECL_CMyComPtr_QI_FROM(
|
||||
ICryptoGetTextPassword,
|
||||
getTextPassword, ReOpenCallback)
|
||||
if (getTextPassword)
|
||||
return getTextPassword->CryptoGetTextPassword(password);
|
||||
}
|
||||
if (!Callback)
|
||||
return E_NOTIMPL;
|
||||
PasswordWasAsked = true;
|
||||
return Callback->Open_CryptoGetTextPassword(password);
|
||||
COM_TRY_END
|
||||
}
|
||||
#endif
|
||||
|
||||
// IProgress
|
||||
Z7_COM7F_IMF(COpenCallbackImp::SetTotal(const UInt64 /* total */))
|
||||
{
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
Z7_COM7F_IMF(COpenCallbackImp::SetCompleted(const UInt64 * /* completed */))
|
||||
{
|
||||
return S_OK;
|
||||
}
|
||||
@@ -0,0 +1,182 @@
|
||||
// ArchiveOpenCallback.h
|
||||
|
||||
#ifndef ZIP7_INC_ARCHIVE_OPEN_CALLBACK_H
|
||||
#define ZIP7_INC_ARCHIVE_OPEN_CALLBACK_H
|
||||
|
||||
#include "../../../Common/MyCom.h"
|
||||
|
||||
#include "../../../Windows/FileFind.h"
|
||||
|
||||
#include "../../Common/FileStreams.h"
|
||||
|
||||
#ifndef Z7_NO_CRYPTO
|
||||
#include "../../IPassword.h"
|
||||
#endif
|
||||
#include "../../Archive/IArchive.h"
|
||||
|
||||
Z7_PURE_INTERFACES_BEGIN
|
||||
|
||||
#ifdef Z7_NO_CRYPTO
|
||||
|
||||
#define Z7_IFACEM_IOpenCallbackUI_Crypto(x)
|
||||
|
||||
#else
|
||||
|
||||
#define Z7_IFACEM_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 Z7_IFACEN_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 \
|
||||
Z7_IFACEM_IOpenCallbackUI_Crypto(x)
|
||||
|
||||
Z7_IFACE_DECL_PURE(IOpenCallbackUI)
|
||||
|
||||
Z7_PURE_INTERFACES_END
|
||||
|
||||
|
||||
class CMultiStreams Z7_final
|
||||
{
|
||||
public:
|
||||
struct CSubStream
|
||||
{
|
||||
CMyComPtr<IInStream> Stream;
|
||||
CInFileStream *FileSpec;
|
||||
FString Path;
|
||||
// UInt64 Size;
|
||||
UInt64 LocalPos;
|
||||
int Next; // next older
|
||||
int Prev; // prev newer
|
||||
// bool IsOpen;
|
||||
|
||||
CSubStream():
|
||||
FileSpec(NULL),
|
||||
// Size(0),
|
||||
LocalPos(0),
|
||||
Next(-1),
|
||||
Prev(-1)
|
||||
// IsOpen(false)
|
||||
{}
|
||||
};
|
||||
|
||||
CObjectVector<CSubStream> Streams;
|
||||
private:
|
||||
// we must use critical section here, if we want to access from different volumnes simultaneously
|
||||
int Head; // newest
|
||||
int Tail; // oldest
|
||||
unsigned NumListItems;
|
||||
unsigned NumOpenFiles_AllowedMax;
|
||||
public:
|
||||
|
||||
CMultiStreams();
|
||||
void Init();
|
||||
HRESULT PrepareToOpenNew();
|
||||
void InsertToList(unsigned index);
|
||||
void RemoveFromList(CSubStream &s);
|
||||
void CloseFile(unsigned index);
|
||||
HRESULT EnsureOpen(unsigned index);
|
||||
};
|
||||
|
||||
|
||||
/*
|
||||
We need COpenCallbackImp class for multivolume processing.
|
||||
Also we use it as proxy from COM interfaces (IArchiveOpenCallback) to internal (IOpenCallbackUI) interfaces.
|
||||
If archive is multivolume:
|
||||
COpenCallbackImp object will exist after Open stage.
|
||||
COpenCallbackImp object will be deleted when last reference
|
||||
from each volume object (CInFileStreamVol) will be closed (when archive will be closed).
|
||||
*/
|
||||
|
||||
class COpenCallbackImp Z7_final:
|
||||
public IArchiveOpenCallback,
|
||||
public IArchiveOpenVolumeCallback,
|
||||
public IArchiveOpenSetSubArchiveName,
|
||||
#ifndef Z7_NO_CRYPTO
|
||||
public ICryptoGetTextPassword,
|
||||
#endif
|
||||
public IProgress, // IProgress is used for 7zFM
|
||||
public CMyUnknownImp
|
||||
{
|
||||
Z7_COM_QI_BEGIN2(IArchiveOpenCallback)
|
||||
Z7_COM_QI_ENTRY(IArchiveOpenVolumeCallback)
|
||||
Z7_COM_QI_ENTRY(IArchiveOpenSetSubArchiveName)
|
||||
#ifndef Z7_NO_CRYPTO
|
||||
Z7_COM_QI_ENTRY(ICryptoGetTextPassword)
|
||||
#endif
|
||||
// Z7_COM_QI_ENTRY(IProgress) // the code doesn't require it
|
||||
Z7_COM_QI_END
|
||||
Z7_COM_ADDREF_RELEASE
|
||||
|
||||
Z7_IFACE_COM7_IMP(IArchiveOpenCallback)
|
||||
Z7_IFACE_COM7_IMP(IArchiveOpenVolumeCallback)
|
||||
Z7_IFACE_COM7_IMP(IProgress)
|
||||
public:
|
||||
Z7_IFACE_COM7_IMP(IArchiveOpenSetSubArchiveName)
|
||||
private:
|
||||
#ifndef Z7_NO_CRYPTO
|
||||
Z7_IFACE_COM7_IMP(ICryptoGetTextPassword)
|
||||
#endif
|
||||
|
||||
bool _subArchiveMode;
|
||||
|
||||
public:
|
||||
bool PasswordWasAsked;
|
||||
UStringVector FileNames;
|
||||
CBoolVector FileNames_WasUsed;
|
||||
CRecordVector<UInt64> FileSizes;
|
||||
|
||||
void AtCloseFile(unsigned fileIndex)
|
||||
{
|
||||
FileNames_WasUsed[fileIndex] = false;
|
||||
Volumes.CloseFile(fileIndex);
|
||||
}
|
||||
|
||||
/* we have two ways to Callback from this object
|
||||
1) IArchiveOpenCallback * ReOpenCallback - for ReOpen function, when IOpenCallbackUI is not available
|
||||
2) IOpenCallbackUI *Callback - for usual callback
|
||||
we can't transfer IOpenCallbackUI pointer via internal interface,
|
||||
so we use ReOpenCallback to callback without IOpenCallbackUI.
|
||||
*/
|
||||
|
||||
/* we use Callback/ReOpenCallback only at Open stage.
|
||||
So the CMyComPtr reference counter is not required,
|
||||
and we don't want additional reference to unused object,
|
||||
if COpenCallbackImp is not closed
|
||||
*/
|
||||
IArchiveOpenCallback *ReOpenCallback;
|
||||
// CMyComPtr<IArchiveOpenCallback> ReOpenCallback;
|
||||
IOpenCallbackUI *Callback;
|
||||
// CMyComPtr<IUnknown> Callback_Ref;
|
||||
|
||||
private:
|
||||
FString _folderPrefix;
|
||||
UString _subArchiveName;
|
||||
NWindows::NFile::NFind::CFileInfo _fileInfo;
|
||||
|
||||
public:
|
||||
CMultiStreams Volumes;
|
||||
|
||||
// UInt64 TotalSize;
|
||||
|
||||
COpenCallbackImp():
|
||||
_subArchiveMode(false),
|
||||
PasswordWasAsked(false),
|
||||
ReOpenCallback(NULL),
|
||||
Callback(NULL) {}
|
||||
|
||||
HRESULT Init2(const FString &folderPrefix, const FString &fileName);
|
||||
|
||||
bool SetSecondFileInfo(CFSTR newName)
|
||||
{
|
||||
return _fileInfo.Find_FollowLink(newName) && !_fileInfo.IsDir();
|
||||
}
|
||||
};
|
||||
|
||||
#endif
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,121 @@
|
||||
// Bench.h
|
||||
|
||||
#ifndef ZIP7_INC_7ZIP_BENCH_H
|
||||
#define ZIP7_INC_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);
|
||||
};
|
||||
|
||||
|
||||
const unsigned kBenchMinDicLogSize = 18;
|
||||
|
||||
UInt64 GetBenchMemoryUsage(UInt32 numThreads, int level, UInt64 dictionary, bool totalBench);
|
||||
|
||||
Z7_PURE_INTERFACES_BEGIN
|
||||
DECLARE_INTERFACE(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;
|
||||
};
|
||||
|
||||
DECLARE_INTERFACE(IBenchPrintCallback)
|
||||
{
|
||||
virtual void Print(const char *s) = 0;
|
||||
virtual void NewLine() = 0;
|
||||
virtual HRESULT CheckBreak() = 0;
|
||||
};
|
||||
|
||||
DECLARE_INTERFACE(IBenchFreqCallback)
|
||||
{
|
||||
virtual HRESULT AddCpuFreq(unsigned numThreads, UInt64 freq, UInt64 usage) = 0;
|
||||
virtual HRESULT FreqsFinished(unsigned numThreads) = 0;
|
||||
};
|
||||
Z7_PURE_INTERFACES_END
|
||||
|
||||
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 Z7_LARGE_PAGES
|
||||
void Add_LargePages_String(AString &s);
|
||||
#else
|
||||
// #define Add_LargePages_String
|
||||
#endif
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,343 @@
|
||||
// CompressCall.cpp
|
||||
|
||||
#include "StdAfx.h"
|
||||
|
||||
#include <wchar.h>
|
||||
|
||||
#include "../../../Common/IntToString.h"
|
||||
#include "../../../Common/MyCom.h"
|
||||
#include "../../../Common/Random.h"
|
||||
#include "../../../Common/StringConvert.h"
|
||||
|
||||
#include "../../../Windows/DLL.h"
|
||||
#include "../../../Windows/ErrorMsg.h"
|
||||
#include "../../../Windows/FileDir.h"
|
||||
#include "../../../Windows/FileMapping.h"
|
||||
#include "../../../Windows/MemoryLock.h"
|
||||
#include "../../../Windows/ProcessUtils.h"
|
||||
#include "../../../Windows/Synchronization.h"
|
||||
|
||||
#include "../FileManager/RegistryUtils.h"
|
||||
|
||||
#include "CompressCall.h"
|
||||
|
||||
using namespace NWindows;
|
||||
|
||||
#define MY_TRY_BEGIN try {
|
||||
|
||||
#define MY_TRY_FINISH } \
|
||||
catch(...) { ErrorMessageHRESULT(E_FAIL); return E_FAIL; }
|
||||
|
||||
#define MY_TRY_FINISH_VOID } \
|
||||
catch(...) { ErrorMessageHRESULT(E_FAIL); }
|
||||
|
||||
#define k7zGui "7zG.exe"
|
||||
|
||||
// 21.07 : we can disable wildcard
|
||||
// #define ISWITCH_NO_WILDCARD_POSTFIX "w-"
|
||||
#define ISWITCH_NO_WILDCARD_POSTFIX
|
||||
|
||||
#define kShowDialogSwitch " -ad"
|
||||
#define kEmailSwitch " -seml."
|
||||
#define kArchiveTypeSwitch " -t"
|
||||
#define kIncludeSwitch " -i" ISWITCH_NO_WILDCARD_POSTFIX
|
||||
#define kArcIncludeSwitches " -an -ai" ISWITCH_NO_WILDCARD_POSTFIX
|
||||
#define kHashIncludeSwitches kIncludeSwitch
|
||||
#define kStopSwitchParsing " --"
|
||||
|
||||
extern HWND g_HWND;
|
||||
|
||||
UString GetQuotedString(const UString &s)
|
||||
{
|
||||
UString s2 ('\"');
|
||||
s2 += s;
|
||||
s2.Add_Char('\"');
|
||||
return s2;
|
||||
}
|
||||
|
||||
static void ErrorMessage(LPCWSTR message)
|
||||
{
|
||||
MessageBoxW(g_HWND, message, L"7-Zip", MB_ICONERROR | MB_OK);
|
||||
}
|
||||
|
||||
static void ErrorMessageHRESULT(HRESULT res, LPCWSTR s = NULL)
|
||||
{
|
||||
UString s2 = NError::MyFormatMessage(res);
|
||||
if (s)
|
||||
{
|
||||
s2.Add_LF();
|
||||
s2 += s;
|
||||
}
|
||||
ErrorMessage(s2);
|
||||
}
|
||||
|
||||
static HRESULT Call7zGui(const UString ¶ms,
|
||||
// LPCWSTR curDir,
|
||||
bool waitFinish,
|
||||
NSynchronization::CBaseEvent *event)
|
||||
{
|
||||
UString imageName = fs2us(NWindows::NDLL::GetModuleDirPrefix());
|
||||
imageName += k7zGui;
|
||||
|
||||
CProcess process;
|
||||
const WRes wres = process.Create(imageName, params, NULL); // curDir);
|
||||
if (wres != 0)
|
||||
{
|
||||
const HRESULT hres = HRESULT_FROM_WIN32(wres);
|
||||
ErrorMessageHRESULT(hres, imageName);
|
||||
return hres;
|
||||
}
|
||||
if (waitFinish)
|
||||
process.Wait();
|
||||
else if (event != NULL)
|
||||
{
|
||||
HANDLE handles[] = { process, *event };
|
||||
::WaitForMultipleObjects(Z7_ARRAY_SIZE(handles), handles, FALSE, INFINITE);
|
||||
}
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
static void AddLagePagesSwitch(UString ¶ms)
|
||||
{
|
||||
if (ReadLockMemoryEnable())
|
||||
#ifndef UNDER_CE
|
||||
if (NSecurity::Get_LargePages_RiskLevel() == 0)
|
||||
#endif
|
||||
params += " -slp";
|
||||
}
|
||||
|
||||
class CRandNameGenerator
|
||||
{
|
||||
CRandom _random;
|
||||
public:
|
||||
CRandNameGenerator() { _random.Init(); }
|
||||
void GenerateName(UString &s, const char *prefix)
|
||||
{
|
||||
s += prefix;
|
||||
s.Add_UInt32((UInt32)(unsigned)_random.Generate());
|
||||
}
|
||||
};
|
||||
|
||||
static HRESULT CreateMap(const UStringVector &names,
|
||||
CFileMapping &fileMapping, NSynchronization::CManualResetEvent &event,
|
||||
UString ¶ms)
|
||||
{
|
||||
size_t totalSize = 1;
|
||||
{
|
||||
FOR_VECTOR (i, names)
|
||||
totalSize += (names[i].Len() + 1);
|
||||
}
|
||||
totalSize *= sizeof(wchar_t);
|
||||
|
||||
CRandNameGenerator random;
|
||||
|
||||
UString mappingName;
|
||||
for (;;)
|
||||
{
|
||||
random.GenerateName(mappingName, "7zMap");
|
||||
const WRes wres = fileMapping.Create(PAGE_READWRITE, totalSize, GetSystemString(mappingName));
|
||||
if (fileMapping.IsCreated() && wres == 0)
|
||||
break;
|
||||
if (wres != ERROR_ALREADY_EXISTS)
|
||||
return HRESULT_FROM_WIN32(wres);
|
||||
fileMapping.Close();
|
||||
}
|
||||
|
||||
UString eventName;
|
||||
for (;;)
|
||||
{
|
||||
random.GenerateName(eventName, "7zEvent");
|
||||
const WRes wres = event.CreateWithName(false, GetSystemString(eventName));
|
||||
if (event.IsCreated() && wres == 0)
|
||||
break;
|
||||
if (wres != ERROR_ALREADY_EXISTS)
|
||||
return HRESULT_FROM_WIN32(wres);
|
||||
event.Close();
|
||||
}
|
||||
|
||||
params.Add_Char('#');
|
||||
params += mappingName;
|
||||
params.Add_Colon();
|
||||
char temp[32];
|
||||
ConvertUInt64ToString(totalSize, temp);
|
||||
params += temp;
|
||||
|
||||
params.Add_Colon();
|
||||
params += eventName;
|
||||
|
||||
LPVOID data = fileMapping.Map(FILE_MAP_WRITE, 0, totalSize);
|
||||
if (!data)
|
||||
return E_FAIL;
|
||||
CFileUnmapper unmapper(data);
|
||||
{
|
||||
wchar_t *cur = (wchar_t *)data;
|
||||
*cur++ = 0; // it means wchar_t strings (UTF-16 in WIN32)
|
||||
FOR_VECTOR (i, names)
|
||||
{
|
||||
const UString &s = names[i];
|
||||
const unsigned len = s.Len() + 1;
|
||||
wmemcpy(cur, (const wchar_t *)s, len);
|
||||
cur += len;
|
||||
}
|
||||
}
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
HRESULT CompressFiles(
|
||||
const UString &arcPathPrefix,
|
||||
const UString &arcName,
|
||||
const UString &arcType,
|
||||
bool addExtension,
|
||||
const UStringVector &names,
|
||||
bool email, bool showDialog, bool waitFinish)
|
||||
{
|
||||
MY_TRY_BEGIN
|
||||
UString params ('a');
|
||||
|
||||
CFileMapping fileMapping;
|
||||
NSynchronization::CManualResetEvent event;
|
||||
params += kIncludeSwitch;
|
||||
RINOK(CreateMap(names, fileMapping, event, params))
|
||||
|
||||
if (!arcType.IsEmpty())
|
||||
{
|
||||
params += kArchiveTypeSwitch;
|
||||
params += arcType;
|
||||
}
|
||||
|
||||
if (email)
|
||||
params += kEmailSwitch;
|
||||
|
||||
if (showDialog)
|
||||
params += kShowDialogSwitch;
|
||||
|
||||
AddLagePagesSwitch(params);
|
||||
|
||||
if (arcName.IsEmpty())
|
||||
params += " -an";
|
||||
|
||||
if (addExtension)
|
||||
params += " -saa";
|
||||
else
|
||||
params += " -sae";
|
||||
|
||||
params += kStopSwitchParsing;
|
||||
params.Add_Space();
|
||||
|
||||
if (!arcName.IsEmpty())
|
||||
{
|
||||
params += GetQuotedString(
|
||||
// #ifdef UNDER_CE
|
||||
arcPathPrefix +
|
||||
// #endif
|
||||
arcName);
|
||||
}
|
||||
|
||||
return Call7zGui(params,
|
||||
// (arcPathPrefix.IsEmpty()? 0: (LPCWSTR)arcPathPrefix),
|
||||
waitFinish, &event);
|
||||
MY_TRY_FINISH
|
||||
}
|
||||
|
||||
static void ExtractGroupCommand(const UStringVector &arcPaths, UString ¶ms, bool isHash)
|
||||
{
|
||||
AddLagePagesSwitch(params);
|
||||
params += (isHash ? kHashIncludeSwitches : kArcIncludeSwitches);
|
||||
CFileMapping fileMapping;
|
||||
NSynchronization::CManualResetEvent event;
|
||||
HRESULT result = CreateMap(arcPaths, fileMapping, event, params);
|
||||
if (result == S_OK)
|
||||
result = Call7zGui(params, false, &event);
|
||||
if (result != S_OK)
|
||||
ErrorMessageHRESULT(result);
|
||||
}
|
||||
|
||||
void ExtractArchives(const UStringVector &arcPaths, const UString &outFolder, bool showDialog, bool elimDup, UInt32 writeZone)
|
||||
{
|
||||
MY_TRY_BEGIN
|
||||
UString params ('x');
|
||||
if (!outFolder.IsEmpty())
|
||||
{
|
||||
params += " -o";
|
||||
params += GetQuotedString(outFolder);
|
||||
}
|
||||
if (elimDup)
|
||||
params += " -spe";
|
||||
if (writeZone != (UInt32)(Int32)-1)
|
||||
{
|
||||
params += " -snz";
|
||||
params.Add_UInt32(writeZone);
|
||||
}
|
||||
if (showDialog)
|
||||
params += kShowDialogSwitch;
|
||||
ExtractGroupCommand(arcPaths, params, false);
|
||||
MY_TRY_FINISH_VOID
|
||||
}
|
||||
|
||||
|
||||
void TestArchives(const UStringVector &arcPaths, bool hashMode)
|
||||
{
|
||||
MY_TRY_BEGIN
|
||||
UString params ('t');
|
||||
if (hashMode)
|
||||
{
|
||||
params += kArchiveTypeSwitch;
|
||||
params += "hash";
|
||||
}
|
||||
ExtractGroupCommand(arcPaths, params, false);
|
||||
MY_TRY_FINISH_VOID
|
||||
}
|
||||
|
||||
|
||||
void CalcChecksum(const UStringVector &paths,
|
||||
const UString &methodName,
|
||||
const UString &arcPathPrefix,
|
||||
const UString &arcFileName)
|
||||
{
|
||||
MY_TRY_BEGIN
|
||||
|
||||
if (!arcFileName.IsEmpty())
|
||||
{
|
||||
CompressFiles(
|
||||
arcPathPrefix,
|
||||
arcFileName,
|
||||
UString("hash"),
|
||||
false, // addExtension,
|
||||
paths,
|
||||
false, // email,
|
||||
false, // showDialog,
|
||||
false // waitFinish
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
UString params ('h');
|
||||
if (!methodName.IsEmpty())
|
||||
{
|
||||
params += " -scrc";
|
||||
params += methodName;
|
||||
/*
|
||||
if (!arcFileName.IsEmpty())
|
||||
{
|
||||
// not used alternate method of generating file
|
||||
params += " -scrf=";
|
||||
params += GetQuotedString(arcPathPrefix + arcFileName);
|
||||
}
|
||||
*/
|
||||
}
|
||||
ExtractGroupCommand(paths, params, true);
|
||||
MY_TRY_FINISH_VOID
|
||||
}
|
||||
|
||||
void Benchmark(bool totalMode)
|
||||
{
|
||||
MY_TRY_BEGIN
|
||||
UString params ('b');
|
||||
if (totalMode)
|
||||
params += " -mm=*";
|
||||
AddLagePagesSwitch(params);
|
||||
const HRESULT result = Call7zGui(params, false, NULL);
|
||||
if (result != S_OK)
|
||||
ErrorMessageHRESULT(result);
|
||||
MY_TRY_FINISH_VOID
|
||||
}
|
||||
@@ -0,0 +1,28 @@
|
||||
// CompressCall.h
|
||||
|
||||
#ifndef ZIP7_INC_COMPRESS_CALL_H
|
||||
#define ZIP7_INC_COMPRESS_CALL_H
|
||||
|
||||
#include "../../../Common/MyString.h"
|
||||
|
||||
UString GetQuotedString(const UString &s);
|
||||
|
||||
HRESULT CompressFiles(
|
||||
const UString &arcPathPrefix,
|
||||
const UString &arcName,
|
||||
const UString &arcType,
|
||||
bool addExtension,
|
||||
const UStringVector &names,
|
||||
bool email, bool showDialog, bool waitFinish);
|
||||
|
||||
void ExtractArchives(const UStringVector &arcPaths, const UString &outFolder, bool showDialog, bool elimDup, UInt32 writeZone);
|
||||
void TestArchives(const UStringVector &arcPaths, bool hashMode = false);
|
||||
|
||||
void CalcChecksum(const UStringVector &paths,
|
||||
const UString &methodName,
|
||||
const UString &arcPathPrefix,
|
||||
const UString &arcFileName);
|
||||
|
||||
void Benchmark(bool totalMode);
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,327 @@
|
||||
// CompressCall2.cpp
|
||||
|
||||
#include "StdAfx.h"
|
||||
|
||||
#ifndef Z7_EXTERNAL_CODECS
|
||||
|
||||
#include "../../../Common/MyException.h"
|
||||
|
||||
#include "../../UI/Common/EnumDirItems.h"
|
||||
|
||||
#include "../../UI/FileManager/LangUtils.h"
|
||||
|
||||
#include "../../UI/GUI/BenchmarkDialog.h"
|
||||
#include "../../UI/GUI/ExtractGUI.h"
|
||||
#include "../../UI/GUI/UpdateGUI.h"
|
||||
#include "../../UI/GUI/HashGUI.h"
|
||||
|
||||
#include "../../UI/GUI/ExtractRes.h"
|
||||
|
||||
#include "CompressCall.h"
|
||||
|
||||
extern HWND g_HWND;
|
||||
|
||||
#define MY_TRY_BEGIN HRESULT result; try {
|
||||
#define MY_TRY_FINISH } \
|
||||
catch(CSystemException &e) { result = e.ErrorCode; } \
|
||||
catch(UString &s) { ErrorMessage(s); result = E_FAIL; } \
|
||||
catch(...) { result = E_FAIL; } \
|
||||
if (result != S_OK && result != E_ABORT) \
|
||||
ErrorMessageHRESULT(result);
|
||||
|
||||
static void ThrowException_if_Error(HRESULT res)
|
||||
{
|
||||
if (res != S_OK)
|
||||
throw CSystemException(res);
|
||||
}
|
||||
|
||||
#ifdef Z7_EXTERNAL_CODECS
|
||||
|
||||
#define CREATE_CODECS \
|
||||
CCodecs *codecs = new CCodecs; \
|
||||
CMyComPtr<ICompressCodecsInfo> compressCodecsInfo = codecs; \
|
||||
ThrowException_if_Error(codecs->Load()); \
|
||||
Codecs_AddHashArcHandler(codecs);
|
||||
|
||||
#define LOAD_EXTERNAL_CODECS \
|
||||
CExternalCodecs _externalCodecs; \
|
||||
_externalCodecs.GetCodecs = codecs; \
|
||||
_externalCodecs.GetHashers = codecs; \
|
||||
ThrowException_if_Error(_externalCodecs.Load());
|
||||
|
||||
#else
|
||||
|
||||
#define CREATE_CODECS \
|
||||
CCodecs *codecs = new CCodecs; \
|
||||
CMyComPtr<IUnknown> compressCodecsInfo = codecs; \
|
||||
ThrowException_if_Error(codecs->Load()); \
|
||||
Codecs_AddHashArcHandler(codecs);
|
||||
|
||||
#define LOAD_EXTERNAL_CODECS
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
|
||||
UString GetQuotedString(const UString &s)
|
||||
{
|
||||
UString s2 ('\"');
|
||||
s2 += s;
|
||||
s2.Add_Char('\"');
|
||||
return s2;
|
||||
}
|
||||
|
||||
static void ErrorMessage(LPCWSTR message)
|
||||
{
|
||||
MessageBoxW(g_HWND, message, L"7-Zip", MB_ICONERROR);
|
||||
}
|
||||
|
||||
static void ErrorMessageHRESULT(HRESULT res)
|
||||
{
|
||||
ErrorMessage(HResultToMessage(res));
|
||||
}
|
||||
|
||||
static void ErrorLangMessage(UINT resourceID)
|
||||
{
|
||||
ErrorMessage(LangString(resourceID));
|
||||
}
|
||||
|
||||
HRESULT CompressFiles(
|
||||
const UString &arcPathPrefix,
|
||||
const UString &arcName,
|
||||
const UString &arcType,
|
||||
bool addExtension,
|
||||
const UStringVector &names,
|
||||
bool email, bool showDialog, bool /* waitFinish */)
|
||||
{
|
||||
MY_TRY_BEGIN
|
||||
|
||||
CREATE_CODECS
|
||||
|
||||
CUpdateCallbackGUI callback;
|
||||
|
||||
callback.Init();
|
||||
|
||||
CUpdateOptions uo;
|
||||
uo.EMailMode = email;
|
||||
uo.SetActionCommand_Add();
|
||||
|
||||
uo.ArcNameMode = (addExtension ? k_ArcNameMode_Add : k_ArcNameMode_Exact);
|
||||
|
||||
CObjectVector<COpenType> formatIndices;
|
||||
if (!ParseOpenTypes(*codecs, arcType, formatIndices))
|
||||
{
|
||||
ErrorLangMessage(IDS_UNSUPPORTED_ARCHIVE_TYPE);
|
||||
return E_FAIL;
|
||||
}
|
||||
const UString arcPath = arcPathPrefix + arcName;
|
||||
if (!uo.InitFormatIndex(codecs, formatIndices, arcPath) ||
|
||||
!uo.SetArcPath(codecs, arcPath))
|
||||
{
|
||||
ErrorLangMessage(IDS_UPDATE_NOT_SUPPORTED);
|
||||
return E_FAIL;
|
||||
}
|
||||
|
||||
NWildcard::CCensor censor;
|
||||
FOR_VECTOR (i, names)
|
||||
{
|
||||
censor.AddPreItem_NoWildcard(names[i]);
|
||||
}
|
||||
|
||||
bool messageWasDisplayed = false;
|
||||
|
||||
result = UpdateGUI(codecs,
|
||||
formatIndices, arcPath,
|
||||
censor, uo, showDialog, messageWasDisplayed, &callback, g_HWND);
|
||||
|
||||
if (result != S_OK)
|
||||
{
|
||||
if (result != E_ABORT && messageWasDisplayed)
|
||||
return E_FAIL;
|
||||
throw CSystemException(result);
|
||||
}
|
||||
if (callback.FailedFiles.Size() > 0)
|
||||
{
|
||||
if (!messageWasDisplayed)
|
||||
throw CSystemException(E_FAIL);
|
||||
return E_FAIL;
|
||||
}
|
||||
|
||||
MY_TRY_FINISH
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
|
||||
static HRESULT ExtractGroupCommand(const UStringVector &arcPaths,
|
||||
bool showDialog, CExtractOptions &eo, const char *kType = NULL)
|
||||
{
|
||||
MY_TRY_BEGIN
|
||||
|
||||
CREATE_CODECS
|
||||
|
||||
CExtractCallbackImp *ecs = new CExtractCallbackImp;
|
||||
CMyComPtr<IFolderArchiveExtractCallback> extractCallback = ecs;
|
||||
|
||||
ecs->Init();
|
||||
|
||||
// eo.CalcCrc = options.CalcCrc;
|
||||
|
||||
UStringVector arcPathsSorted;
|
||||
UStringVector arcFullPathsSorted;
|
||||
{
|
||||
NWildcard::CCensor arcCensor;
|
||||
FOR_VECTOR (i, arcPaths)
|
||||
{
|
||||
arcCensor.AddPreItem_NoWildcard(arcPaths[i]);
|
||||
}
|
||||
arcCensor.AddPathsToCensor(NWildcard::k_RelatPath);
|
||||
CDirItemsStat st;
|
||||
EnumerateDirItemsAndSort(arcCensor, NWildcard::k_RelatPath, UString(),
|
||||
arcPathsSorted, arcFullPathsSorted,
|
||||
st,
|
||||
NULL // &scan: change it!!!!
|
||||
);
|
||||
}
|
||||
|
||||
CObjectVector<COpenType> formatIndices;
|
||||
if (kType)
|
||||
{
|
||||
if (!ParseOpenTypes(*codecs, UString(kType), formatIndices))
|
||||
{
|
||||
throw CSystemException(E_INVALIDARG);
|
||||
// ErrorLangMessage(IDS_UNSUPPORTED_ARCHIVE_TYPE);
|
||||
// return E_INVALIDARG;
|
||||
}
|
||||
}
|
||||
|
||||
NWildcard::CCensor censor;
|
||||
{
|
||||
censor.AddPreItem_Wildcard();
|
||||
}
|
||||
|
||||
censor.AddPathsToCensor(NWildcard::k_RelatPath);
|
||||
|
||||
bool messageWasDisplayed = false;
|
||||
|
||||
ecs->MultiArcMode = (arcPathsSorted.Size() > 1);
|
||||
|
||||
result = ExtractGUI(codecs,
|
||||
formatIndices, CIntVector(),
|
||||
arcPathsSorted, arcFullPathsSorted,
|
||||
censor.Pairs.Front().Head, eo, NULL, showDialog, messageWasDisplayed, ecs, g_HWND);
|
||||
|
||||
if (result != S_OK)
|
||||
{
|
||||
if (result != E_ABORT && messageWasDisplayed)
|
||||
return E_FAIL;
|
||||
throw CSystemException(result);
|
||||
}
|
||||
return ecs->IsOK() ? S_OK : E_FAIL;
|
||||
|
||||
MY_TRY_FINISH
|
||||
return result;
|
||||
}
|
||||
|
||||
void ExtractArchives(const UStringVector &arcPaths, const UString &outFolder,
|
||||
bool showDialog, bool elimDup, UInt32 writeZone)
|
||||
{
|
||||
CExtractOptions eo;
|
||||
eo.OutputDir = us2fs(outFolder);
|
||||
eo.TestMode = false;
|
||||
eo.ElimDup.Val = elimDup;
|
||||
eo.ElimDup.Def = elimDup;
|
||||
if (writeZone != (UInt32)(Int32)-1)
|
||||
eo.ZoneMode = (NExtract::NZoneIdMode::EEnum)writeZone;
|
||||
ExtractGroupCommand(arcPaths, showDialog, eo);
|
||||
}
|
||||
|
||||
void TestArchives(const UStringVector &arcPaths, bool hashMode)
|
||||
{
|
||||
CExtractOptions eo;
|
||||
eo.TestMode = true;
|
||||
ExtractGroupCommand(arcPaths,
|
||||
true, // showDialog
|
||||
eo,
|
||||
hashMode ? "hash" : NULL);
|
||||
}
|
||||
|
||||
void CalcChecksum(const UStringVector &paths,
|
||||
const UString &methodName,
|
||||
const UString &arcPathPrefix,
|
||||
const UString &arcFileName)
|
||||
{
|
||||
MY_TRY_BEGIN
|
||||
|
||||
if (!arcFileName.IsEmpty())
|
||||
{
|
||||
CompressFiles(
|
||||
arcPathPrefix,
|
||||
arcFileName,
|
||||
UString("hash"),
|
||||
false, // addExtension,
|
||||
paths,
|
||||
false, // email,
|
||||
false, // showDialog,
|
||||
false // waitFinish
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
CREATE_CODECS
|
||||
LOAD_EXTERNAL_CODECS
|
||||
|
||||
NWildcard::CCensor censor;
|
||||
FOR_VECTOR (i, paths)
|
||||
{
|
||||
censor.AddPreItem_NoWildcard(paths[i]);
|
||||
}
|
||||
|
||||
censor.AddPathsToCensor(NWildcard::k_RelatPath);
|
||||
bool messageWasDisplayed = false;
|
||||
|
||||
CHashOptions options;
|
||||
options.Methods.Add(methodName);
|
||||
|
||||
/*
|
||||
if (!arcFileName.IsEmpty())
|
||||
options.HashFilePath = arcPathPrefix + arcFileName;
|
||||
*/
|
||||
|
||||
result = HashCalcGUI(EXTERNAL_CODECS_VARS_L censor, options, messageWasDisplayed);
|
||||
if (result != S_OK)
|
||||
{
|
||||
if (result != E_ABORT && messageWasDisplayed)
|
||||
return; // E_FAIL;
|
||||
throw CSystemException(result);
|
||||
}
|
||||
|
||||
MY_TRY_FINISH
|
||||
return; // result;
|
||||
}
|
||||
|
||||
void Benchmark(bool totalMode)
|
||||
{
|
||||
MY_TRY_BEGIN
|
||||
|
||||
CREATE_CODECS
|
||||
LOAD_EXTERNAL_CODECS
|
||||
|
||||
CObjectVector<CProperty> props;
|
||||
if (totalMode)
|
||||
{
|
||||
CProperty prop;
|
||||
prop.Name = "m";
|
||||
prop.Value = "*";
|
||||
props.Add(prop);
|
||||
}
|
||||
result = Benchmark(
|
||||
EXTERNAL_CODECS_VARS_L
|
||||
props,
|
||||
k_NumBenchIterations_Default,
|
||||
g_HWND);
|
||||
|
||||
MY_TRY_FINISH
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -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;
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
// DefaultName.h
|
||||
|
||||
#ifndef ZIP7_INC_DEFAULT_NAME_H
|
||||
#define ZIP7_INC_DEFAULT_NAME_H
|
||||
|
||||
#include "../../../Common/MyString.h"
|
||||
|
||||
UString GetDefaultName2(const UString &fileName,
|
||||
const UString &extension, const UString &addSubExtension);
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,407 @@
|
||||
// DirItem.h
|
||||
|
||||
#ifndef ZIP7_INC_DIR_ITEM_H
|
||||
#define ZIP7_INC_DIR_ITEM_H
|
||||
|
||||
#ifdef _WIN32
|
||||
#include "../../../Common/MyLinux.h"
|
||||
#endif
|
||||
|
||||
#include "../../../Common/MyString.h"
|
||||
|
||||
#include "../../../Windows/FileFind.h"
|
||||
#include "../../../Windows/PropVariant.h"
|
||||
#include "../../../Windows/TimeUtils.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)
|
||||
{}
|
||||
};
|
||||
|
||||
|
||||
Z7_PURE_INTERFACES_BEGIN
|
||||
|
||||
#define Z7_IFACEN_IDirItemsCallback(x) \
|
||||
virtual HRESULT ScanError(const FString &path, DWORD systemError) x \
|
||||
virtual HRESULT ScanProgress(const CDirItemsStat &st, const FString &path, bool isDir) x \
|
||||
|
||||
Z7_IFACE_DECL_PURE(IDirItemsCallback)
|
||||
|
||||
Z7_PURE_INTERFACES_END
|
||||
|
||||
|
||||
struct CArcTime
|
||||
{
|
||||
FILETIME FT;
|
||||
UInt16 Prec;
|
||||
Byte Ns100;
|
||||
bool Def;
|
||||
|
||||
CArcTime()
|
||||
{
|
||||
Clear();
|
||||
}
|
||||
|
||||
void Clear()
|
||||
{
|
||||
FT.dwHighDateTime = FT.dwLowDateTime = 0;
|
||||
Prec = 0;
|
||||
Ns100 = 0;
|
||||
Def = false;
|
||||
}
|
||||
|
||||
bool IsZero() const
|
||||
{
|
||||
return FT.dwLowDateTime == 0 && FT.dwHighDateTime == 0 && Ns100 == 0;
|
||||
}
|
||||
|
||||
int CompareWith(const CArcTime &a) const
|
||||
{
|
||||
const int res = CompareFileTime(&FT, &a.FT);
|
||||
if (res != 0)
|
||||
return res;
|
||||
if (Ns100 < a.Ns100) return -1;
|
||||
if (Ns100 > a.Ns100) return 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
UInt64 Get_FILETIME_as_UInt64() const
|
||||
{
|
||||
return (((UInt64)FT.dwHighDateTime) << 32) + FT.dwLowDateTime;
|
||||
}
|
||||
|
||||
UInt32 Get_DosTime() const
|
||||
{
|
||||
FILETIME ft2 = FT;
|
||||
if ((Prec == k_PropVar_TimePrec_Base + 8 ||
|
||||
Prec == k_PropVar_TimePrec_Base + 9)
|
||||
&& Ns100 != 0)
|
||||
{
|
||||
UInt64 u64 = Get_FILETIME_as_UInt64();
|
||||
// we round up even small (ns < 100ns) as FileTimeToDosTime()
|
||||
if (u64 % 20000000 == 0)
|
||||
{
|
||||
u64++;
|
||||
ft2.dwHighDateTime = (DWORD)(u64 >> 32);
|
||||
ft2.dwHighDateTime = (DWORD)u64;
|
||||
}
|
||||
}
|
||||
// FileTimeToDosTime() is expected to round up in Windows
|
||||
UInt32 dosTime;
|
||||
// we use simplified code with utctime->dos.
|
||||
// do we need local time instead here?
|
||||
NWindows::NTime::FileTime_To_DosTime(ft2, dosTime);
|
||||
return dosTime;
|
||||
}
|
||||
|
||||
int GetNumDigits() const
|
||||
{
|
||||
if (Prec == k_PropVar_TimePrec_Unix ||
|
||||
Prec == k_PropVar_TimePrec_DOS)
|
||||
return 0;
|
||||
if (Prec == k_PropVar_TimePrec_HighPrec)
|
||||
return 9;
|
||||
if (Prec == k_PropVar_TimePrec_0)
|
||||
return 7;
|
||||
int digits = (int)Prec - (int)k_PropVar_TimePrec_Base;
|
||||
if (digits < 0)
|
||||
digits = 0;
|
||||
return digits;
|
||||
}
|
||||
|
||||
void Write_To_FiTime(CFiTime &dest) const
|
||||
{
|
||||
#ifdef _WIN32
|
||||
dest = FT;
|
||||
#else
|
||||
if (FILETIME_To_timespec(FT, dest))
|
||||
if ((Prec == k_PropVar_TimePrec_Base + 8 ||
|
||||
Prec == k_PropVar_TimePrec_Base + 9)
|
||||
&& Ns100 != 0)
|
||||
{
|
||||
dest.tv_nsec += Ns100;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
// (Def) is not set
|
||||
void Set_From_FILETIME(const FILETIME &ft)
|
||||
{
|
||||
FT = ft;
|
||||
// Prec = k_PropVar_TimePrec_CompatNTFS;
|
||||
Prec = k_PropVar_TimePrec_Base + 7;
|
||||
Ns100 = 0;
|
||||
}
|
||||
|
||||
// (Def) is not set
|
||||
// it set full form precision: k_PropVar_TimePrec_Base + numDigits
|
||||
void Set_From_FiTime(const CFiTime &ts)
|
||||
{
|
||||
#ifdef _WIN32
|
||||
FT = ts;
|
||||
Prec = k_PropVar_TimePrec_Base + 7;
|
||||
// Prec = k_PropVar_TimePrec_Base; // for debug
|
||||
// Prec = 0; // for debug
|
||||
Ns100 = 0;
|
||||
#else
|
||||
unsigned ns100;
|
||||
FiTime_To_FILETIME_ns100(ts, FT, ns100);
|
||||
Ns100 = (Byte)ns100;
|
||||
Prec = k_PropVar_TimePrec_Base + 9;
|
||||
#endif
|
||||
}
|
||||
|
||||
void Set_From_Prop(const PROPVARIANT &prop)
|
||||
{
|
||||
FT = prop.filetime;
|
||||
unsigned prec = 0;
|
||||
unsigned ns100 = 0;
|
||||
const unsigned prec_Temp = prop.wReserved1;
|
||||
if (prec_Temp != 0
|
||||
&& prec_Temp <= k_PropVar_TimePrec_1ns
|
||||
&& prop.wReserved3 == 0)
|
||||
{
|
||||
const unsigned ns100_Temp = prop.wReserved2;
|
||||
if (ns100_Temp < 100)
|
||||
{
|
||||
ns100 = ns100_Temp;
|
||||
prec = prec_Temp;
|
||||
}
|
||||
}
|
||||
Prec = (UInt16)prec;
|
||||
Ns100 = (Byte)ns100;
|
||||
Def = true;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
struct CDirItem: public NWindows::NFile::NFind::CFileInfoBase
|
||||
{
|
||||
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
|
||||
|
||||
void Copy_From_FileInfoBase(const NWindows::NFile::NFind::CFileInfoBase &fi)
|
||||
{
|
||||
(NWindows::NFile::NFind::CFileInfoBase &)*this = fi;
|
||||
}
|
||||
|
||||
int PhyParent;
|
||||
int LogParent;
|
||||
int SecureIndex;
|
||||
|
||||
#ifdef _WIN32
|
||||
#else
|
||||
int OwnerNameIndex;
|
||||
int OwnerGroupIndex;
|
||||
#endif
|
||||
|
||||
// bool Attrib_IsDefined;
|
||||
|
||||
CDirItem():
|
||||
PhyParent(-1)
|
||||
, LogParent(-1)
|
||||
, SecureIndex(-1)
|
||||
#ifdef _WIN32
|
||||
#else
|
||||
, OwnerNameIndex(-1)
|
||||
, OwnerGroupIndex(-1)
|
||||
#endif
|
||||
// , Attrib_IsDefined(true)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
CDirItem(const NWindows::NFile::NFind::CFileInfo &fi,
|
||||
int phyParent, int logParent, int secureIndex):
|
||||
CFileInfoBase(fi)
|
||||
, Name(fs2us(fi.Name))
|
||||
#if defined(_WIN32) && !defined(UNDER_CE)
|
||||
// , ShortName(fs2us(fi.ShortName))
|
||||
#endif
|
||||
, PhyParent(phyParent)
|
||||
, LogParent(logParent)
|
||||
, SecureIndex(secureIndex)
|
||||
#ifdef _WIN32
|
||||
#else
|
||||
, OwnerNameIndex(-1)
|
||||
, OwnerGroupIndex(-1)
|
||||
#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;
|
||||
bool ExcludeDirItems;
|
||||
bool ExcludeFileItems;
|
||||
bool ShareForWrite;
|
||||
|
||||
/* it must be called after anotrher checks */
|
||||
bool CanIncludeItem(bool isDir) const
|
||||
{
|
||||
return isDir ? !ExcludeDirItems : !ExcludeFileItems;
|
||||
}
|
||||
|
||||
|
||||
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
|
||||
|
||||
#ifndef _WIN32
|
||||
|
||||
C_UInt32_UString_Map OwnerNameMap;
|
||||
C_UInt32_UString_Map OwnerGroupMap;
|
||||
bool StoreOwnerName;
|
||||
|
||||
HRESULT FillDeviceSizes();
|
||||
|
||||
#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;
|
||||
UString Name;
|
||||
CArcTime MTime; // it can be mtime of archive file, if MTime is not defined for item in archive
|
||||
bool IsDir;
|
||||
bool IsAltStream;
|
||||
bool Size_Defined;
|
||||
bool Censored;
|
||||
UInt32 IndexInServer;
|
||||
|
||||
CArcItem():
|
||||
IsDir(false),
|
||||
IsAltStream(false),
|
||||
Size_Defined(false),
|
||||
Censored(false)
|
||||
{}
|
||||
};
|
||||
|
||||
#endif
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,38 @@
|
||||
// EnumDirItems.h
|
||||
|
||||
#ifndef ZIP7_INC_ENUM_DIR_ITEMS_H
|
||||
#define ZIP7_INC_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
|
||||
@@ -0,0 +1,27 @@
|
||||
// ExitCode.h
|
||||
|
||||
#ifndef ZIP7_INC_EXIT_CODE_H
|
||||
#define ZIP7_INC_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
|
||||
@@ -0,0 +1,575 @@
|
||||
// Extract.cpp
|
||||
|
||||
#include "StdAfx.h"
|
||||
|
||||
#include "../../../Common/StringConvert.h"
|
||||
|
||||
#include "../../../Windows/FileDir.h"
|
||||
#include "../../../Windows/FileName.h"
|
||||
#include "../../../Windows/ErrorMsg.h"
|
||||
#include "../../../Windows/PropVariant.h"
|
||||
#include "../../../Windows/PropVariantConv.h"
|
||||
|
||||
#include "../Common/ExtractingFilePath.h"
|
||||
#include "../Common/HashCalc.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,
|
||||
IFolderArchiveExtractCallback *callbackFAE,
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const 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
|
||||
|| options.ExcludeDirItems
|
||||
|| options.ExcludeFileItems)
|
||||
{
|
||||
RINOK(arc.GetItem(i, item))
|
||||
if (item.IsDir ? options.ExcludeDirItems : options.ExcludeFileItems)
|
||||
continue;
|
||||
}
|
||||
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,
|
||||
callbackFAE,
|
||||
options.StdOutMode, options.TestMode,
|
||||
outDir,
|
||||
removePathParts, false,
|
||||
packSize);
|
||||
|
||||
ecs->Is_elimPrefix_Mode = elimIsPossible;
|
||||
|
||||
|
||||
#ifdef SUPPORT_LINKS
|
||||
|
||||
if (!options.StdInMode &&
|
||||
!options.TestMode &&
|
||||
options.NtOptions.HardLinks.Val)
|
||||
{
|
||||
RINOK(ecs->PrepareHardLinks(&realIndices))
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
HRESULT result;
|
||||
const 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
|
||||
{
|
||||
// v23.02: we reset completed value that could be set by Open() operation
|
||||
IArchiveExtractCallback *aec = ecs;
|
||||
const UInt64 val = 0;
|
||||
RINOK(aec->SetCompleted(&val))
|
||||
result = archive->Extract(realIndices.ConstData(), realIndices.Size(), testMode, aec);
|
||||
}
|
||||
|
||||
const 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 &fileNames, const UString &name);
|
||||
int Find_FileName_InSortedVector(const UStringVector &fileNames, const UString &name)
|
||||
{
|
||||
unsigned left = 0, right = fileNames.Size();
|
||||
while (left != right)
|
||||
{
|
||||
const unsigned mid = (unsigned)(((size_t)left + (size_t)right) / 2);
|
||||
const UString &midVal = fileNames[mid];
|
||||
const int comp = CompareFileNames(name, midVal);
|
||||
if (comp == 0)
|
||||
return (int)mid;
|
||||
if (comp < 0)
|
||||
right = mid;
|
||||
else
|
||||
left = mid + 1;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
|
||||
HRESULT Extract(
|
||||
// DECL_EXTERNAL_CODECS_LOC_VARS
|
||||
CCodecs *codecs,
|
||||
const CObjectVector<COpenType> &types,
|
||||
const CIntVector &excludedFormats,
|
||||
UStringVector &arcPaths, UStringVector &arcPathsFull,
|
||||
const NWildcard::CCensorNode &wildcardCensor,
|
||||
const CExtractOptions &options,
|
||||
IOpenCallbackUI *openCallback,
|
||||
IExtractCallbackUI *extractCallback,
|
||||
IFolderArchiveExtractCallback *faeCallback,
|
||||
#ifndef Z7_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);
|
||||
|
||||
const bool multi = (numArcs > 1);
|
||||
|
||||
ecs->InitForMulti(multi,
|
||||
options.PathMode,
|
||||
options.OverwriteMode,
|
||||
options.ZoneMode,
|
||||
false // keepEmptyDirParts
|
||||
);
|
||||
#ifndef Z7_SFX
|
||||
ecs->SetHashMethods(hash);
|
||||
#endif
|
||||
|
||||
if (multi)
|
||||
{
|
||||
RINOK(faeCallback->SetTotal(totalPackSize))
|
||||
}
|
||||
|
||||
UInt64 totalPackProcessed = 0;
|
||||
bool thereAreNotOpenArcs = false;
|
||||
|
||||
for (i = 0; i < numArcs; i++)
|
||||
{
|
||||
if (skipArcs[i])
|
||||
continue;
|
||||
|
||||
ecs->InitBeforeNewArchive();
|
||||
|
||||
const UString &arcPath = arcPaths[i];
|
||||
NFind::CFileInfo fi;
|
||||
if (options.StdInMode)
|
||||
{
|
||||
// do we need ctime and mtime?
|
||||
// fi.ClearBase();
|
||||
// fi.Size = 0; // (UInt64)(Int64)-1;
|
||||
if (!fi.SetAs_StdInFile())
|
||||
return GetLastError_noZero_HRESULT();
|
||||
}
|
||||
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 Z7_NO_CRYPTO
|
||||
openCallback->Open_Clear_PasswordWasAsked_Flag();
|
||||
#endif
|
||||
*/
|
||||
|
||||
RINOK(extractCallback->BeforeOpen(arcPath, options.TestMode))
|
||||
CArchiveLink arcLink;
|
||||
|
||||
CObjectVector<COpenType> types2 = types;
|
||||
/*
|
||||
#ifndef Z7_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.IsEqualTo("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 Z7_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 defined(_WIN32) && !defined(UNDER_CE) && !defined(Z7_SFX)
|
||||
if (options.ZoneMode != NExtract::NZoneIdMode::kNone
|
||||
&& !options.StdInMode)
|
||||
{
|
||||
ReadZoneFile_Of_BaseFile(us2fs(arcPath), ecs->ZoneBuf);
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
if (arcLink.Arcs.Size() != 0)
|
||||
{
|
||||
if (arcLink.GetArc()->IsHashHandler(op))
|
||||
{
|
||||
if (!options.TestMode)
|
||||
{
|
||||
/* real Extracting to files is possible.
|
||||
But user can think that hash archive contains real files.
|
||||
So we block extracting here. */
|
||||
// v23.00 : we don't break process.
|
||||
RINOK(extractCallback->OpenResult(codecs, arcLink, arcPath, E_NOTIMPL))
|
||||
thereAreNotOpenArcs = true;
|
||||
if (!options.StdInMode)
|
||||
totalPackProcessed += fi.Size;
|
||||
continue;
|
||||
// return E_NOTIMPL; // before v23
|
||||
}
|
||||
FString dirPrefix = us2fs(options.HashDir);
|
||||
if (dirPrefix.IsEmpty())
|
||||
{
|
||||
if (!NFile::NDir::GetOnlyDirPrefix(us2fs(arcPath), dirPrefix))
|
||||
{
|
||||
// return GetLastError_noZero_HRESULT();
|
||||
}
|
||||
}
|
||||
if (!dirPrefix.IsEmpty())
|
||||
NName::NormalizeDirPathPrefix(dirPrefix);
|
||||
ecs->DirPathPrefix_for_HashFiles = dirPrefix;
|
||||
}
|
||||
}
|
||||
|
||||
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(faeCallback->SetTotal(totalPackSize))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
// Now openCallback and extractCallback use same object. So we don't need to send password.
|
||||
|
||||
#ifndef Z7_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.MTime.Def = !options.StdInMode
|
||||
#ifdef _WIN32
|
||||
&& !fi.IsDevice
|
||||
#endif
|
||||
;
|
||||
if (arc.MTime.Def)
|
||||
arc.MTime.Set_From_FiTime(fi.MTime);
|
||||
|
||||
UInt64 packProcessed;
|
||||
const bool calcCrc =
|
||||
#ifndef Z7_SFX
|
||||
(hash != NULL);
|
||||
#else
|
||||
false;
|
||||
#endif
|
||||
|
||||
RINOK(DecompressArchive(
|
||||
codecs,
|
||||
arcLink,
|
||||
fi.Size + arcLink.VolumesSize,
|
||||
wildcardCensor,
|
||||
options,
|
||||
calcCrc,
|
||||
extractCallback, faeCallback, 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(faeCallback->SetTotal(totalPackSize))
|
||||
RINOK(faeCallback->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;
|
||||
}
|
||||
@@ -0,0 +1,107 @@
|
||||
// Extract.h
|
||||
|
||||
#ifndef ZIP7_INC_EXTRACT_H
|
||||
#define ZIP7_INC_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 ExcludeDirItems;
|
||||
bool ExcludeFileItems;
|
||||
|
||||
bool PathMode_Force;
|
||||
bool OverwriteMode_Force;
|
||||
NExtract::NPathMode::EEnum PathMode;
|
||||
NExtract::NOverwriteMode::EEnum OverwriteMode;
|
||||
NExtract::NZoneIdMode::EEnum ZoneMode;
|
||||
|
||||
CExtractNtOptions NtOptions;
|
||||
|
||||
FString OutputDir;
|
||||
UString HashDir;
|
||||
|
||||
CExtractOptionsBase():
|
||||
ExcludeDirItems(false),
|
||||
ExcludeFileItems(false),
|
||||
PathMode_Force(false),
|
||||
OverwriteMode_Force(false),
|
||||
PathMode(NExtract::NPathMode::kFullPaths),
|
||||
OverwriteMode(NExtract::NOverwriteMode::kAsk),
|
||||
ZoneMode(NExtract::NZoneIdMode::kNone)
|
||||
{}
|
||||
};
|
||||
|
||||
struct CExtractOptions: public CExtractOptionsBase
|
||||
{
|
||||
bool StdInMode;
|
||||
bool StdOutMode;
|
||||
bool YesToAll;
|
||||
bool TestMode;
|
||||
|
||||
// bool ShowDialog;
|
||||
// bool PasswordEnabled;
|
||||
// UString Password;
|
||||
#ifndef Z7_SFX
|
||||
CObjectVector<CProperty> Properties;
|
||||
#endif
|
||||
|
||||
/*
|
||||
#ifdef Z7_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(
|
||||
// DECL_EXTERNAL_CODECS_LOC_VARS
|
||||
CCodecs *codecs,
|
||||
const CObjectVector<COpenType> &types,
|
||||
const CIntVector &excludedFormats,
|
||||
UStringVector &archivePaths, UStringVector &archivePathsFull,
|
||||
const NWildcard::CCensorNode &wildcardCensor,
|
||||
const CExtractOptions &options,
|
||||
IOpenCallbackUI *openCallback,
|
||||
IExtractCallbackUI *extractCallback,
|
||||
IFolderArchiveExtractCallback *faeCallback,
|
||||
#ifndef Z7_SFX
|
||||
IHashCalc *hash,
|
||||
#endif
|
||||
UString &errorMessage,
|
||||
CDecompressStat &st);
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,44 @@
|
||||
// ExtractMode.h
|
||||
|
||||
#ifndef ZIP7_INC_EXTRACT_MODE_H
|
||||
#define ZIP7_INC_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
|
||||
};
|
||||
}
|
||||
|
||||
namespace NZoneIdMode
|
||||
{
|
||||
enum EEnum
|
||||
{
|
||||
kNone,
|
||||
kAll,
|
||||
kOffice
|
||||
};
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,296 @@
|
||||
// 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)
|
||||
{
|
||||
#if WCHAR_PATH_SEPARATOR != L'/'
|
||||
// 22.00 : WSL replacement for backslash
|
||||
if (c == WCHAR_PATH_SEPARATOR)
|
||||
c = WCHAR_IN_FILE_NAME_BACKSLASH_REPLACEMENT;
|
||||
else
|
||||
#endif
|
||||
c = '_';
|
||||
s.ReplaceOneCharAtPos(i,
|
||||
c
|
||||
// (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 < Z7_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].IsEqualTo("?"))
|
||||
{
|
||||
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;
|
||||
}
|
||||
@@ -0,0 +1,31 @@
|
||||
// ExtractingFilePath.h
|
||||
|
||||
#ifndef ZIP7_INC_EXTRACTING_FILE_PATH_H
|
||||
#define ZIP7_INC_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
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,322 @@
|
||||
// HashCalc.h
|
||||
|
||||
#ifndef ZIP7_INC_HASH_CALC_H
|
||||
#define ZIP7_INC_HASH_CALC_H
|
||||
|
||||
#include "../../../Common/UTFConvert.h"
|
||||
#include "../../../Common/Wildcard.h"
|
||||
|
||||
#include "../../Common/CreateCoder.h"
|
||||
#include "../../Common/MethodProps.h"
|
||||
|
||||
#include "DirItem.h"
|
||||
#include "IFileExtractCallback.h"
|
||||
|
||||
const unsigned k_HashCalc_DigestSize_Max = 64;
|
||||
const unsigned k_HashCalc_ExtraSize = 8;
|
||||
const unsigned k_HashCalc_NumGroups = 4;
|
||||
|
||||
/*
|
||||
if (size <= 8) : upper case : reversed byte order : it shows 32-bit/64-bit number, if data contains little-endian number
|
||||
if (size > 8) : lower case : original byte order (as big-endian byte sequence)
|
||||
*/
|
||||
void HashHexToString(char *dest, const Byte *data, size_t size);
|
||||
|
||||
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;
|
||||
UInt64 NumSums[k_HashCalc_NumGroups];
|
||||
Byte Digests[k_HashCalc_NumGroups][k_HashCalc_DigestSize_Max + k_HashCalc_ExtraSize];
|
||||
|
||||
void InitDigestGroup(unsigned groupIndex)
|
||||
{
|
||||
NumSums[groupIndex] = 0;
|
||||
memset(Digests[groupIndex], 0, sizeof(Digests[groupIndex]));
|
||||
}
|
||||
|
||||
const Byte *GetExtraData_for_Group(unsigned groupIndex) const
|
||||
{
|
||||
return Digests[groupIndex] + k_HashCalc_DigestSize_Max;
|
||||
}
|
||||
|
||||
unsigned GetNumExtraBytes_for_Group(unsigned groupIndex) const
|
||||
{
|
||||
const Byte *p = GetExtraData_for_Group(groupIndex);
|
||||
// we use little-endian to read extra bytes
|
||||
for (unsigned i = k_HashCalc_ExtraSize; i != 0; i--)
|
||||
if (p[i - 1] != 0)
|
||||
return i;
|
||||
return 0;
|
||||
}
|
||||
|
||||
void AddDigest(unsigned groupIndex, const Byte *data);
|
||||
|
||||
void WriteToString(unsigned digestIndex, char *s) const;
|
||||
};
|
||||
|
||||
|
||||
Z7_PURE_INTERFACES_BEGIN
|
||||
|
||||
|
||||
DECLARE_INTERFACE(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;
|
||||
};
|
||||
|
||||
Z7_PURE_INTERFACES_END
|
||||
|
||||
struct CHashBundle Z7_final: 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;
|
||||
}
|
||||
|
||||
void InitForNewFile() Z7_override;
|
||||
void Update(const void *data, UInt32 size) Z7_override;
|
||||
void SetSize(UInt64 size) Z7_override;
|
||||
void Final(bool isDir, bool isAltStream, const UString &path) Z7_override;
|
||||
};
|
||||
|
||||
Z7_PURE_INTERFACES_BEGIN
|
||||
|
||||
// INTERFACE_IDirItemsCallback(x)
|
||||
|
||||
#define Z7_IFACEN_IHashCallbackUI(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 \
|
||||
|
||||
Z7_IFACE_DECL_PURE_(IHashCallbackUI, IDirItemsCallback)
|
||||
|
||||
Z7_PURE_INTERFACES_END
|
||||
|
||||
|
||||
struct CHashOptionsLocal
|
||||
{
|
||||
CBoolPair HashMode_Zero;
|
||||
CBoolPair HashMode_Tag;
|
||||
CBoolPair HashMode_Dirs;
|
||||
CBoolPair HashMode_OnlyHash;
|
||||
|
||||
void Init_HashOptionsLocal()
|
||||
{
|
||||
HashMode_Zero.Init();
|
||||
HashMode_Tag.Init();
|
||||
HashMode_Dirs.Init();
|
||||
HashMode_OnlyHash.Init();
|
||||
// HashMode_Dirs = true; // for debug
|
||||
}
|
||||
|
||||
CHashOptionsLocal()
|
||||
{
|
||||
Init_HashOptionsLocal();
|
||||
}
|
||||
|
||||
bool ParseFlagCharOption(wchar_t c, bool val)
|
||||
{
|
||||
c = MyCharLower_Ascii(c);
|
||||
if (c == 'z') HashMode_Zero.SetVal_as_Defined(val);
|
||||
else if (c == 't') HashMode_Tag.SetVal_as_Defined(val);
|
||||
else if (c == 'd') HashMode_Dirs.SetVal_as_Defined(val);
|
||||
else if (c == 'h') HashMode_OnlyHash.SetVal_as_Defined(val);
|
||||
else return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool ParseString(const UString &s)
|
||||
{
|
||||
for (unsigned i = 0; i < s.Len();)
|
||||
{
|
||||
const wchar_t c = s[i++];
|
||||
bool val = true;
|
||||
if (i < s.Len())
|
||||
{
|
||||
const wchar_t next = s[i];
|
||||
if (next == '-')
|
||||
{
|
||||
val = false;
|
||||
i++;
|
||||
}
|
||||
}
|
||||
if (!ParseFlagCharOption(c, val))
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
struct CHashOptions
|
||||
// : public CHashOptionsLocal
|
||||
{
|
||||
UStringVector Methods;
|
||||
// UString HashFilePath;
|
||||
|
||||
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);
|
||||
|
||||
|
||||
|
||||
#ifndef Z7_SFX
|
||||
|
||||
namespace NHash {
|
||||
|
||||
struct CHashPair
|
||||
{
|
||||
CByteBuffer Hash;
|
||||
char Mode;
|
||||
bool IsBSD;
|
||||
bool Escape;
|
||||
bool Size_from_Arc_Defined;
|
||||
bool Size_from_Disk_Defined;
|
||||
AString Method;
|
||||
AString Name;
|
||||
|
||||
AString FullLine;
|
||||
AString HashString;
|
||||
// unsigned HashLengthInBits;
|
||||
|
||||
// AString MethodName;
|
||||
UInt64 Size_from_Arc;
|
||||
UInt64 Size_from_Disk;
|
||||
|
||||
bool IsDir() const;
|
||||
|
||||
void Get_UString_Path(UString &path) const
|
||||
{
|
||||
path.Empty();
|
||||
if (!ConvertUTF8ToUnicode(Name, path))
|
||||
return;
|
||||
}
|
||||
|
||||
bool ParseCksum(const char *s);
|
||||
bool Parse(const char *s);
|
||||
|
||||
bool IsSupportedMode() const
|
||||
{
|
||||
return Mode != 'U' && Mode != '^';
|
||||
}
|
||||
|
||||
CHashPair():
|
||||
Mode(0)
|
||||
, IsBSD(false)
|
||||
, Escape(false)
|
||||
, Size_from_Arc_Defined(false)
|
||||
, Size_from_Disk_Defined(false)
|
||||
// , HashLengthInBits(0)
|
||||
, Size_from_Arc(0)
|
||||
, Size_from_Disk(0)
|
||||
{}
|
||||
};
|
||||
|
||||
|
||||
Z7_CLASS_IMP_CHandler_IInArchive_3(
|
||||
IArchiveGetRawProps,
|
||||
/* public IGetArchiveHashHandler, */
|
||||
IOutArchive,
|
||||
ISetProperties
|
||||
)
|
||||
bool _isArc;
|
||||
bool _supportWindowsBackslash;
|
||||
bool _crcSize_WasSet;
|
||||
bool _is_CksumMode;
|
||||
bool _is_PgpMethod;
|
||||
bool _is_ZeroMode;
|
||||
bool _are_there_Tags;
|
||||
bool _are_there_Dirs;
|
||||
bool _is_KnownMethod_in_FileName;
|
||||
bool _hashSize_Defined;
|
||||
unsigned _hashSize;
|
||||
UInt32 _crcSize;
|
||||
UInt64 _phySize;
|
||||
CObjectVector<CHashPair> HashPairs;
|
||||
UStringVector _methods;
|
||||
AString _method_from_FileName;
|
||||
AString _pgpMethod;
|
||||
AString _method_for_Extraction;
|
||||
CHashOptionsLocal _options;
|
||||
|
||||
void ClearVars();
|
||||
void InitProps();
|
||||
|
||||
bool CanUpdate() const
|
||||
{
|
||||
if (!_isArc || _is_PgpMethod || _is_CksumMode)
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
HRESULT SetProperty(const wchar_t *nameSpec, const PROPVARIANT &value);
|
||||
|
||||
public:
|
||||
CHandler();
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
void Codecs_AddHashArcHandler(CCodecs *codecs);
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,112 @@
|
||||
// IFileExtractCallback.h
|
||||
|
||||
#ifndef ZIP7_INC_I_FILE_EXTRACT_CALLBACK_H
|
||||
#define ZIP7_INC_I_FILE_EXTRACT_CALLBACK_H
|
||||
|
||||
#include "../../../Common/MyString.h"
|
||||
|
||||
#include "../../IDecl.h"
|
||||
|
||||
#include "LoadCodecs.h"
|
||||
#include "OpenArchive.h"
|
||||
|
||||
Z7_PURE_INTERFACES_BEGIN
|
||||
|
||||
#define Z7_IFACE_CONSTR_FOLDERARC_SUB(i, base, n) \
|
||||
Z7_DECL_IFACE_7ZIP_SUB(i, base, 1, n) \
|
||||
{ Z7_IFACE_COM7_PURE(i) };
|
||||
|
||||
#define Z7_IFACE_CONSTR_FOLDERARC(i, n) \
|
||||
Z7_IFACE_CONSTR_FOLDERARC_SUB(i, IUnknown, n)
|
||||
|
||||
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 Z7_IFACEM_IFolderArchiveExtractCallback(x) \
|
||||
x(AskOverwrite( \
|
||||
const wchar_t *existName, const FILETIME *existTime, const UInt64 *existSize, \
|
||||
const wchar_t *newName, const FILETIME *newTime, const UInt64 *newSize, \
|
||||
Int32 *answer)) \
|
||||
x(PrepareOperation(const wchar_t *name, Int32 isFolder, Int32 askExtractMode, const UInt64 *position)) \
|
||||
x(MessageError(const wchar_t *message)) \
|
||||
x(SetOperationResult(Int32 opRes, Int32 encrypted)) \
|
||||
|
||||
Z7_IFACE_CONSTR_FOLDERARC_SUB(IFolderArchiveExtractCallback, IProgress, 0x07)
|
||||
|
||||
#define Z7_IFACEM_IFolderArchiveExtractCallback2(x) \
|
||||
x(ReportExtractResult(Int32 opRes, Int32 encrypted, const wchar_t *name)) \
|
||||
|
||||
Z7_IFACE_CONSTR_FOLDERARC(IFolderArchiveExtractCallback2, 0x08)
|
||||
|
||||
/* ---------- IExtractCallbackUI ----------
|
||||
is implemented by
|
||||
Console/ExtractCallbackConsole.h CExtractCallbackConsole
|
||||
FileManager/ExtractCallback.h CExtractCallbackImp
|
||||
*/
|
||||
|
||||
#ifdef Z7_NO_CRYPTO
|
||||
#define Z7_IFACEM_IExtractCallbackUI_Crypto(px)
|
||||
#else
|
||||
#define Z7_IFACEM_IExtractCallbackUI_Crypto(px) \
|
||||
virtual HRESULT SetPassword(const UString &password) px
|
||||
#endif
|
||||
|
||||
#define Z7_IFACEN_IExtractCallbackUI(px) \
|
||||
virtual HRESULT BeforeOpen(const wchar_t *name, bool testMode) px \
|
||||
virtual HRESULT OpenResult(const CCodecs *codecs, const CArchiveLink &arcLink, const wchar_t *name, HRESULT result) px \
|
||||
virtual HRESULT ThereAreNoFiles() px \
|
||||
virtual HRESULT ExtractResult(HRESULT result) px \
|
||||
Z7_IFACEM_IExtractCallbackUI_Crypto(px)
|
||||
|
||||
// IExtractCallbackUI - is non-COM interface
|
||||
// IFolderArchiveExtractCallback - is COM interface
|
||||
// Z7_IFACE_DECL_PURE_(IExtractCallbackUI, IFolderArchiveExtractCallback)
|
||||
Z7_IFACE_DECL_PURE(IExtractCallbackUI)
|
||||
|
||||
|
||||
|
||||
#define Z7_IFACEM_IGetProp(x) \
|
||||
x(GetProp(PROPID propID, PROPVARIANT *value)) \
|
||||
|
||||
Z7_IFACE_CONSTR_FOLDERARC(IGetProp, 0x20)
|
||||
|
||||
#define Z7_IFACEM_IFolderExtractToStreamCallback(x) \
|
||||
x(UseExtractToStream(Int32 *res)) \
|
||||
x(GetStream7(const wchar_t *name, Int32 isDir, ISequentialOutStream **outStream, Int32 askExtractMode, IGetProp *getProp)) \
|
||||
x(PrepareOperation7(Int32 askExtractMode)) \
|
||||
x(SetOperationResult8(Int32 resultEOperationResult, Int32 encrypted, UInt64 size)) \
|
||||
|
||||
Z7_IFACE_CONSTR_FOLDERARC(IFolderExtractToStreamCallback, 0x31)
|
||||
|
||||
Z7_PURE_INTERFACES_END
|
||||
|
||||
#endif
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,482 @@
|
||||
// LoadCodecs.h
|
||||
|
||||
#ifndef ZIP7_INC_LOAD_CODECS_H
|
||||
#define ZIP7_INC_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
|
||||
|
||||
Z7_EXTERNAL_CODECS
|
||||
---------------
|
||||
|
||||
if Z7_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 Z7_EXTERNAL_CODECS defined:
|
||||
- 7z.exe, 7zG.exe, 7zFM.exe
|
||||
|
||||
Note: Z7_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 Z7_EXTERNAL_CODECS:
|
||||
- SFX modules: 7z.sfx, 7zCon.sfx
|
||||
- standalone versions of console 7-Zip: 7za.exe, 7zr.exe
|
||||
|
||||
if Z7_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 Z7_EXTERNAL_CODECS
|
||||
#include "../../../Windows/DLL.h"
|
||||
#endif
|
||||
|
||||
#include "../../ICoder.h"
|
||||
|
||||
#include "../../Archive/IArchive.h"
|
||||
|
||||
|
||||
#ifdef Z7_EXTERNAL_CODECS
|
||||
|
||||
struct CDllCodecInfo
|
||||
{
|
||||
unsigned LibIndex;
|
||||
UInt32 CodecIndex;
|
||||
bool EncoderIsAssigned;
|
||||
bool DecoderIsAssigned;
|
||||
bool IsFilter;
|
||||
bool IsFilter_Assigned;
|
||||
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;
|
||||
UInt32 TimeFlags;
|
||||
|
||||
Func_CreateInArchive CreateInArchive;
|
||||
Func_IsArc IsArcFunc;
|
||||
|
||||
UString Name;
|
||||
CObjectVector<CArcExtInfo> Exts;
|
||||
|
||||
#ifndef Z7_SFX
|
||||
Func_CreateOutArchive CreateOutArchive;
|
||||
bool UpdateEnabled;
|
||||
bool NewInterface;
|
||||
// UInt32 Version;
|
||||
UInt32 SignatureOffset;
|
||||
CObjectVector<CByteBuffer> Signatures;
|
||||
/*
|
||||
#ifdef NEW_FOLDER_INTERFACE
|
||||
UStringVector AssociateExts;
|
||||
#endif
|
||||
*/
|
||||
#endif
|
||||
|
||||
#ifdef Z7_EXTERNAL_CODECS
|
||||
int LibIndex;
|
||||
UInt32 FormatIndex;
|
||||
CLSID ClassID;
|
||||
#endif
|
||||
|
||||
int Compare(const CArcInfoEx &a) const
|
||||
{
|
||||
const int res = Name.Compare(a.Name);
|
||||
if (res != 0)
|
||||
return res;
|
||||
#ifdef Z7_EXTERNAL_CODECS
|
||||
return MyCompare(LibIndex, a.LibIndex);
|
||||
#else
|
||||
return 0;
|
||||
#endif
|
||||
/*
|
||||
if (LibIndex < a.LibIndex) return -1;
|
||||
if (LibIndex > a.LibIndex) return 1;
|
||||
return 0;
|
||||
*/
|
||||
}
|
||||
|
||||
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_NtSecurity() 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; }
|
||||
bool Flags_HashHandler() const { return (Flags & NArcInfoFlags::kHashHandler) != 0; }
|
||||
|
||||
bool Flags_CTime() const { return (Flags & NArcInfoFlags::kCTime) != 0; }
|
||||
bool Flags_ATime() const { return (Flags & NArcInfoFlags::kATime) != 0; }
|
||||
bool Flags_MTime() const { return (Flags & NArcInfoFlags::kMTime) != 0; }
|
||||
|
||||
bool Flags_CTime_Default() const { return (Flags & NArcInfoFlags::kCTime_Default) != 0; }
|
||||
bool Flags_ATime_Default() const { return (Flags & NArcInfoFlags::kATime_Default) != 0; }
|
||||
bool Flags_MTime_Default() const { return (Flags & NArcInfoFlags::kMTime_Default) != 0; }
|
||||
|
||||
UInt32 Get_TimePrecFlags() const
|
||||
{
|
||||
return (TimeFlags >> NArcInfoTimeFlags::kTime_Prec_Mask_bit_index) &
|
||||
(((UInt32)1 << NArcInfoTimeFlags::kTime_Prec_Mask_num_bits) - 1);
|
||||
}
|
||||
|
||||
UInt32 Get_DefaultTimePrec() const
|
||||
{
|
||||
return (TimeFlags >> NArcInfoTimeFlags::kTime_Prec_Default_bit_index) &
|
||||
(((UInt32)1 << NArcInfoTimeFlags::kTime_Prec_Default_num_bits) - 1);
|
||||
}
|
||||
|
||||
|
||||
UString GetMainExt() const
|
||||
{
|
||||
if (Exts.IsEmpty())
|
||||
return UString();
|
||||
return Exts[0].Ext;
|
||||
}
|
||||
int FindExtension(const UString &ext) const;
|
||||
|
||||
bool Is_7z() const { return Name.IsEqualTo_Ascii_NoCase("7z"); }
|
||||
bool Is_Split() const { return Name.IsEqualTo_Ascii_NoCase("Split"); }
|
||||
bool Is_Xz() const { return Name.IsEqualTo_Ascii_NoCase("xz"); }
|
||||
bool Is_BZip2() const { return Name.IsEqualTo_Ascii_NoCase("bzip2"); }
|
||||
bool Is_GZip() const { return Name.IsEqualTo_Ascii_NoCase("gzip"); }
|
||||
bool Is_Tar() const { return Name.IsEqualTo_Ascii_NoCase("tar"); }
|
||||
bool Is_Zip() const { return Name.IsEqualTo_Ascii_NoCase("zip"); }
|
||||
bool Is_Rar() const { return Name.IsEqualTo_Ascii_NoCase("rar"); }
|
||||
bool Is_Zstd() const { return Name.IsEqualTo_Ascii_NoCase("zstd"); }
|
||||
|
||||
/*
|
||||
UString GetAllExtensions() const
|
||||
{
|
||||
UString s;
|
||||
for (int i = 0; i < Exts.Size(); i++)
|
||||
{
|
||||
if (i > 0)
|
||||
s.Add_Space();
|
||||
s += Exts[i].Ext;
|
||||
}
|
||||
return s;
|
||||
}
|
||||
*/
|
||||
|
||||
void AddExts(const UString &ext, const UString &addExt);
|
||||
|
||||
|
||||
CArcInfoEx():
|
||||
Flags(0),
|
||||
TimeFlags(0),
|
||||
CreateInArchive(NULL),
|
||||
IsArcFunc(NULL)
|
||||
#ifndef Z7_SFX
|
||||
, CreateOutArchive(NULL)
|
||||
, UpdateEnabled(false)
|
||||
, NewInterface(false)
|
||||
// , Version(0)
|
||||
, SignatureOffset(0)
|
||||
#endif
|
||||
#ifdef Z7_EXTERNAL_CODECS
|
||||
, LibIndex(-1)
|
||||
#endif
|
||||
{}
|
||||
};
|
||||
|
||||
|
||||
#ifdef Z7_EXTERNAL_CODECS
|
||||
|
||||
struct CCodecLib
|
||||
{
|
||||
NWindows::NDLL::CLibrary Lib;
|
||||
FString Path;
|
||||
|
||||
Func_CreateObject CreateObject;
|
||||
Func_GetMethodProperty GetMethodProperty;
|
||||
Func_CreateDecoder CreateDecoder;
|
||||
Func_CreateEncoder CreateEncoder;
|
||||
Func_SetCodecs SetCodecs;
|
||||
|
||||
CMyComPtr<IHashers> ComHashers;
|
||||
|
||||
UInt32 Version;
|
||||
|
||||
/*
|
||||
#ifdef NEW_FOLDER_INTERFACE
|
||||
CCodecIcons CodecIcons;
|
||||
void LoadIcons() { CodecIcons.LoadIcons((HMODULE)Lib); }
|
||||
#endif
|
||||
*/
|
||||
|
||||
CCodecLib():
|
||||
CreateObject(NULL),
|
||||
GetMethodProperty(NULL),
|
||||
CreateDecoder(NULL),
|
||||
CreateEncoder(NULL),
|
||||
SetCodecs(NULL),
|
||||
Version(0)
|
||||
{}
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
struct CCodecError
|
||||
{
|
||||
FString Path;
|
||||
HRESULT ErrorCode;
|
||||
AString Message;
|
||||
CCodecError(): ErrorCode(0) {}
|
||||
};
|
||||
|
||||
|
||||
struct CCodecInfoUser
|
||||
{
|
||||
// unsigned LibIndex;
|
||||
// UInt32 CodecIndex;
|
||||
// UInt64 id;
|
||||
bool EncoderIsAssigned;
|
||||
bool DecoderIsAssigned;
|
||||
bool IsFilter;
|
||||
bool IsFilter_Assigned;
|
||||
UInt32 NumStreams;
|
||||
AString Name;
|
||||
};
|
||||
|
||||
|
||||
class CCodecs Z7_final:
|
||||
#ifdef Z7_EXTERNAL_CODECS
|
||||
public ICompressCodecsInfo,
|
||||
public IHashers,
|
||||
#else
|
||||
public IUnknown,
|
||||
#endif
|
||||
public CMyUnknownImp
|
||||
{
|
||||
#ifdef Z7_EXTERNAL_CODECS
|
||||
Z7_IFACES_IMP_UNK_2(ICompressCodecsInfo, IHashers)
|
||||
#else
|
||||
Z7_COM_UNKNOWN_IMP_0
|
||||
#endif // Z7_EXTERNAL_CODECS
|
||||
|
||||
Z7_CLASS_NO_COPY(CCodecs)
|
||||
public:
|
||||
#ifdef Z7_EXTERNAL_CODECS
|
||||
|
||||
CObjectVector<CCodecLib> Libs;
|
||||
FString MainDll_ErrorPath;
|
||||
CObjectVector<CCodecError> Errors;
|
||||
|
||||
void AddLastError(const FString &path);
|
||||
void CloseLibs();
|
||||
|
||||
class CReleaser
|
||||
{
|
||||
Z7_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 Z7_EXTERNAL_CODECS
|
||||
CRecordVector<CDllCodecInfo> Codecs;
|
||||
CRecordVector<CDllHasherInfo> Hashers;
|
||||
#endif
|
||||
|
||||
bool CaseSensitive_Change;
|
||||
bool CaseSensitive;
|
||||
|
||||
CCodecs():
|
||||
#ifdef Z7_EXTERNAL_CODECS
|
||||
NeedSetLibCodecs(true),
|
||||
#endif
|
||||
CaseSensitive_Change(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 Z7_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 Z7_EXTERNAL_CODECS
|
||||
|
||||
int GetCodec_LibIndex(UInt32 index) const;
|
||||
bool GetCodec_DecoderIsAssigned(UInt32 index) const;
|
||||
bool GetCodec_EncoderIsAssigned(UInt32 index) const;
|
||||
bool GetCodec_IsFilter(UInt32 index, bool &isAssigned) 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 Z7_EXTERNAL_CODECS
|
||||
if (ai.LibIndex < 0)
|
||||
#endif
|
||||
{
|
||||
COM_TRY_BEGIN
|
||||
archive = ai.CreateInArchive();
|
||||
return S_OK;
|
||||
COM_TRY_END
|
||||
}
|
||||
#ifdef Z7_EXTERNAL_CODECS
|
||||
return CreateArchiveHandler(ai, false, (void **)&archive);
|
||||
#endif
|
||||
}
|
||||
|
||||
#ifndef Z7_SFX
|
||||
|
||||
HRESULT CreateOutArchive(unsigned formatIndex, CMyComPtr<IOutArchive> &archive) const
|
||||
{
|
||||
const CArcInfoEx &ai = Formats[formatIndex];
|
||||
#ifdef Z7_EXTERNAL_CODECS
|
||||
if (ai.LibIndex < 0)
|
||||
#endif
|
||||
{
|
||||
COM_TRY_BEGIN
|
||||
archive = ai.CreateOutArchive();
|
||||
return S_OK;
|
||||
COM_TRY_END
|
||||
}
|
||||
|
||||
#ifdef Z7_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;
|
||||
}
|
||||
|
||||
void Get_CodecsInfoUser_Vector(CObjectVector<CCodecInfoUser> &v);
|
||||
|
||||
#endif // Z7_SFX
|
||||
};
|
||||
|
||||
#ifdef Z7_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
@@ -0,0 +1,469 @@
|
||||
// OpenArchive.h
|
||||
|
||||
#ifndef ZIP7_INC_OPEN_ARCHIVE_H
|
||||
#define ZIP7_INC_OPEN_ARCHIVE_H
|
||||
|
||||
#include "../../../Windows/PropVariant.h"
|
||||
|
||||
#include "ArchiveOpenCallback.h"
|
||||
#include "LoadCodecs.h"
|
||||
#include "Property.h"
|
||||
#include "DirItem.h"
|
||||
|
||||
#ifndef Z7_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 Z7_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 IsHashType;
|
||||
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),
|
||||
IsHashType(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 Z7_SFX
|
||||
bool _use_baseParentFolder_mode;
|
||||
int _baseParentFolder;
|
||||
#endif
|
||||
|
||||
CReadArcItem()
|
||||
{
|
||||
#ifdef SUPPORT_ALT_STREAMS
|
||||
WriteToAltStreamIfColon = false;
|
||||
#endif
|
||||
|
||||
#ifndef Z7_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 Z7_SFX
|
||||
// parts.Back() can contain alt stream name "nams:AltName"
|
||||
HRESULT GetItem_PathToParent(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;
|
||||
|
||||
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
|
||||
|
||||
UString Path;
|
||||
UString filePath;
|
||||
UString DefaultName;
|
||||
int FormatIndex; // -1 means Parser
|
||||
UInt32 SubfileIndex; // (UInt32)(Int32)-1; means no subfile
|
||||
|
||||
// CFiTime MTime;
|
||||
// bool MTime_Defined;
|
||||
CArcTime MTime;
|
||||
|
||||
Int64 Offset; // it's offset of start of archive inside stream that is open by Archive Handler
|
||||
UInt64 PhySize;
|
||||
// UInt64 OkPhySize;
|
||||
bool PhySize_Defined;
|
||||
// bool OkPhySize_Defined;
|
||||
UInt64 FileSize;
|
||||
UInt64 AvailPhySize; // PhySize, but it's reduced if exceed end of file
|
||||
|
||||
CArcErrorInfo ErrorInfo; // for OK archives
|
||||
CArcErrorInfo NonOpen_ErrorInfo; // ErrorInfo for mainArchive (false OPEN)
|
||||
|
||||
UInt64 GetEstmatedPhySize() const { return PhySize_Defined ? 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;
|
||||
|
||||
// void Set_ErrorFlagsText();
|
||||
|
||||
CArc():
|
||||
// MTime_Defined(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);
|
||||
|
||||
HRESULT Close()
|
||||
{
|
||||
InStream.Release();
|
||||
return Archive->Close();
|
||||
}
|
||||
|
||||
HRESULT GetItem_Path(UInt32 index, UString &result) const;
|
||||
HRESULT GetItem_DefaultPath(UInt32 index, UString &result) const;
|
||||
|
||||
// GetItemPath2 adds [DELETED] dir prefix for deleted items.
|
||||
HRESULT GetItem_Path2(UInt32 index, UString &result) const;
|
||||
|
||||
HRESULT GetItem(UInt32 index, CReadArcItem &item) const;
|
||||
|
||||
HRESULT GetItem_Size(UInt32 index, UInt64 &size, bool &defined) const;
|
||||
|
||||
/* if (GetProperty() returns vt==VT_EMPTY), this function sets
|
||||
timestamp from archive file timestamp (MTime).
|
||||
So (at) will be set in most cases (at.Def == true)
|
||||
if (at.Prec == 0)
|
||||
{
|
||||
it means that (Prec == 0) was returned for (kpidMTime),
|
||||
and no value was returned for (kpidTimeType).
|
||||
it can mean Windows precision or unknown precision.
|
||||
}
|
||||
*/
|
||||
HRESULT GetItem_MTime(UInt32 index, CArcTime &at) const;
|
||||
|
||||
HRESULT IsItem_Anti(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, IArchiveOpenCallback *openCallback_Additional);
|
||||
|
||||
HRESULT CreateNewTailStream(CMyComPtr<IInStream> &stream);
|
||||
|
||||
bool IsHashHandler(const COpenOptions &options) const
|
||||
{
|
||||
if (FormatIndex < 0)
|
||||
return false;
|
||||
return options.codecs->Formats[(unsigned)FormatIndex].Flags_HashHandler();
|
||||
}
|
||||
};
|
||||
|
||||
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);
|
||||
|
||||
// bool IsHashType(const 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
|
||||
@@ -0,0 +1,745 @@
|
||||
// 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 Z7_SFX
|
||||
#define Get16(x) GetUi16(x)
|
||||
#define Get32(x) GetUi32(x)
|
||||
#endif
|
||||
|
||||
using namespace NWindows;
|
||||
|
||||
static const unsigned kNumWinAtrribFlags = 30;
|
||||
static const char g_WinAttribChars[kNumWinAtrribFlags + 1] = "RHS8DAdNTsLCOIEVvX.PU.M......B";
|
||||
|
||||
/*
|
||||
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 (10.0.16267)
|
||||
22 RECALL_ON_DATA_ACCESS
|
||||
29 STRICTLY_SEQUENTIAL (10.0.17134+) (SMR Blob)
|
||||
*/
|
||||
|
||||
|
||||
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.
|
||||
But this code works with Attrib from internal 7zip code.
|
||||
So we expect that 0x8000 marker is set, if there are posix attributes.
|
||||
(DT_UNKNOWN == 0) type in high bits is possible in some case for linux files.
|
||||
0x8000 flag is possible also in ReFS (Windows)?
|
||||
*/
|
||||
|
||||
const bool isPosix = (
|
||||
(wa & 0x8000) != 0 // FILE_ATTRIBUTE_UNIX_EXTENSION;
|
||||
// && (wa & 0xFFFF0000u) != 0
|
||||
);
|
||||
|
||||
UInt32 posix = 0;
|
||||
if (isPosix)
|
||||
{
|
||||
posix = wa >> 16;
|
||||
if ((wa & 0xF0000000u) != 0)
|
||||
wa &= (UInt32)0x3FFF;
|
||||
}
|
||||
|
||||
for (unsigned i = 0; i < kNumWinAtrribFlags; i++)
|
||||
{
|
||||
const UInt32 flag = (UInt32)1 << i;
|
||||
if (wa & flag)
|
||||
{
|
||||
const 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;
|
||||
unsigned ns100 = 0;
|
||||
int numDigits = kTimestampPrintLevel_NTFS;
|
||||
const unsigned prec = prop.wReserved1;
|
||||
const unsigned ns100_Temp = prop.wReserved2;
|
||||
if (prec != 0
|
||||
&& prec <= k_PropVar_TimePrec_1ns
|
||||
&& ns100_Temp < 100
|
||||
&& prop.wReserved3 == 0)
|
||||
{
|
||||
ns100 = ns100_Temp;
|
||||
if (prec == k_PropVar_TimePrec_Unix ||
|
||||
prec == k_PropVar_TimePrec_DOS)
|
||||
numDigits = 0;
|
||||
else if (prec == k_PropVar_TimePrec_HighPrec)
|
||||
numDigits = 9;
|
||||
else
|
||||
{
|
||||
numDigits = (int)prec - (int)k_PropVar_TimePrec_Base;
|
||||
if (
|
||||
// numDigits < kTimestampPrintLevel_DAY // for debuf
|
||||
numDigits < kTimestampPrintLevel_SEC
|
||||
)
|
||||
|
||||
numDigits = kTimestampPrintLevel_NTFS;
|
||||
}
|
||||
}
|
||||
if (ft.dwHighDateTime == 0 && ft.dwLowDateTime == 0 && ns100 == 0)
|
||||
return;
|
||||
if (level > numDigits)
|
||||
level = numDigits;
|
||||
ConvertUtcFileTimeToString2(ft, ns100, 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;
|
||||
const 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++ = '-';
|
||||
const 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;
|
||||
}
|
||||
|
||||
/*
|
||||
case kpidDevice:
|
||||
{
|
||||
UInt64 v = 0;
|
||||
if (prop.vt == VT_UI4)
|
||||
v = prop.ulVal;
|
||||
else if (prop.vt == VT_UI8)
|
||||
v = (UInt64)prop.uhVal.QuadPart;
|
||||
else
|
||||
break;
|
||||
ConvertUInt32ToString(MY_dev_major(v), dest);
|
||||
dest += strlen(dest);
|
||||
*dest++ = ',';
|
||||
ConvertUInt32ToString(MY_dev_minor(v), dest);
|
||||
return;
|
||||
}
|
||||
*/
|
||||
default: break;
|
||||
}
|
||||
|
||||
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 Z7_SFX
|
||||
|
||||
static inline void AddHexToString(AString &res, unsigned v)
|
||||
{
|
||||
res.Add_Char((char)GET_HEX_CHAR_UPPER(v >> 4));
|
||||
res.Add_Char((char)GET_HEX_CHAR_UPPER(v & 15));
|
||||
}
|
||||
|
||||
/*
|
||||
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, size_t lim /* , unsigned &sidSize */)
|
||||
{
|
||||
// sidSize = 0;
|
||||
if (lim < 8)
|
||||
{
|
||||
s += "ERROR";
|
||||
return;
|
||||
}
|
||||
if (p[0] != 1) // rev
|
||||
{
|
||||
s += "UNSUPPORTED";
|
||||
return;
|
||||
}
|
||||
const unsigned num = p[1];
|
||||
const unsigned sidSize_Loc = 8 + num * 4;
|
||||
if (sidSize_Loc > lim)
|
||||
{
|
||||
s += "ERROR";
|
||||
return;
|
||||
}
|
||||
// sidSize = sidSize_Loc;
|
||||
const UInt32 authority = GetBe32(p + 4);
|
||||
|
||||
if (p[2] == 0 && p[3] == 0 && authority == 5 && num >= 1)
|
||||
{
|
||||
const UInt32 v0 = Get32(p + 8);
|
||||
if (v0 < Z7_ARRAY_SIZE(sidNames))
|
||||
{
|
||||
s += sidNames[v0];
|
||||
return;
|
||||
}
|
||||
if (v0 == 32 && num == 2)
|
||||
{
|
||||
const UInt32 v1 = Get32(p + 12);
|
||||
const int index = FindPairIndex(sid_32_Names, Z7_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);
|
||||
const int index = FindPairIndex(sid_21_Names, Z7_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 < Z7_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.Add_Minus();
|
||||
s.Add_UInt32(Get32(p + 8 + i * 4));
|
||||
}
|
||||
}
|
||||
|
||||
static void ParseOwner(AString &s, const Byte *p, size_t size, UInt32 pos)
|
||||
{
|
||||
if (pos > size)
|
||||
{
|
||||
s += "ERROR";
|
||||
return;
|
||||
}
|
||||
// unsigned sidSize = 0;
|
||||
ParseSid(s, p + pos, size - pos /* , sidSize */);
|
||||
}
|
||||
|
||||
static void ParseAcl(AString &s, const Byte *p, size_t size, const char *strName, UInt32 flags, UInt32 offset)
|
||||
{
|
||||
const unsigned control = Get16(p + 2);
|
||||
if ((flags & control) == 0)
|
||||
return;
|
||||
const UInt32 pos = Get32(p + offset);
|
||||
s.Add_Space();
|
||||
s += strName;
|
||||
if (pos >= size)
|
||||
return;
|
||||
p += pos;
|
||||
size -= (size_t)pos;
|
||||
if (size < 8)
|
||||
return;
|
||||
if (Get16(p) != 2) // revision
|
||||
return;
|
||||
const 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, size_t 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((UInt32)size);
|
||||
// s.Add_LF();
|
||||
// s += Data_To_Hex(data, size);
|
||||
}
|
||||
|
||||
#ifdef _WIN32
|
||||
|
||||
static bool CheckSid(const Byte *data, size_t size, UInt32 pos) throw()
|
||||
{
|
||||
if (pos >= size)
|
||||
return false;
|
||||
size -= pos;
|
||||
if (size < 8)
|
||||
return false;
|
||||
if (data[pos] != 1) // rev
|
||||
return false;
|
||||
const unsigned num = data[pos + 1];
|
||||
return (8 + num * 4 <= size);
|
||||
}
|
||||
|
||||
static bool CheckAcl(const Byte *p, size_t size, UInt32 flags, size_t offset) throw()
|
||||
{
|
||||
const unsigned control = Get16(p + 2);
|
||||
if ((flags & control) == 0)
|
||||
return true;
|
||||
const UInt32 pos = Get32(p + offset);
|
||||
if (pos >= size)
|
||||
return false;
|
||||
p += pos;
|
||||
size -= pos;
|
||||
if (size < 8)
|
||||
return false;
|
||||
const unsigned aclSize = Get16(p + 2);
|
||||
return (aclSize <= size);
|
||||
}
|
||||
|
||||
bool CheckNtSecure(const Byte *data, size_t 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, size_t 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.Add_Space(); // for debug
|
||||
}
|
||||
|
||||
if (size < 8)
|
||||
return false;
|
||||
const UInt32 tag = Get32(data);
|
||||
const 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)
|
||||
{
|
||||
}
|
||||
*/
|
||||
|
||||
{
|
||||
const int index = FindPairIndex(k_ReparseTags, Z7_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.Add_Colon();
|
||||
s.Add_UInt32(len);
|
||||
|
||||
if (len != 0)
|
||||
{
|
||||
s.Add_Space();
|
||||
|
||||
data += 8;
|
||||
|
||||
for (UInt32 i = 0; i < len; i++)
|
||||
{
|
||||
if (i >= 16)
|
||||
{
|
||||
s += "...";
|
||||
break;
|
||||
}
|
||||
const unsigned b = data[i];
|
||||
s.Add_Char((char)GET_HEX_CHAR_UPPER(b >> 4));
|
||||
s.Add_Char((char)GET_HEX_CHAR_UPPER(b & 15));
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,18 @@
|
||||
// PropIDUtils.h
|
||||
|
||||
#ifndef ZIP7_INC_PROPID_UTILS_H
|
||||
#define ZIP7_INC_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, size_t size, UString &s);
|
||||
void ConvertNtSecureToString(const Byte *data, size_t size, AString &s);
|
||||
bool CheckNtSecure(const Byte *data, size_t size) throw();
|
||||
|
||||
void ConvertWinAttribToString(char *s, UInt32 wa) throw();
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,14 @@
|
||||
// Property.h
|
||||
|
||||
#ifndef ZIP7_INC_7Z_PROPERTY_H
|
||||
#define ZIP7_INC_7Z_PROPERTY_H
|
||||
|
||||
#include "../../../Common/MyString.h"
|
||||
|
||||
struct CProperty
|
||||
{
|
||||
UString Name;
|
||||
UString Value;
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,88 @@
|
||||
// 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;
|
||||
const 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;
|
||||
Z7_DECL_CMyComPtr_QI_FROM(
|
||||
ISetProperties,
|
||||
setProperties, unknown)
|
||||
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())
|
||||
{
|
||||
const 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.ConstData(), values.values, names.Size());
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
// SetProperties.h
|
||||
|
||||
#ifndef ZIP7_INC_SETPROPERTIES_H
|
||||
#define ZIP7_INC_SETPROPERTIES_H
|
||||
|
||||
#include "Property.h"
|
||||
|
||||
HRESULT SetProperties(IUnknown *unknown, const CObjectVector<CProperty> &properties);
|
||||
|
||||
#endif
|
||||
@@ -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);
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
// SortUtils.h
|
||||
|
||||
#ifndef ZIP7_INC_SORT_UTLS_H
|
||||
#define ZIP7_INC_SORT_UTLS_H
|
||||
|
||||
#include "../../../Common/MyString.h"
|
||||
|
||||
void SortFileNames(const UStringVector &strings, CUIntVector &indices);
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,11 @@
|
||||
// StdAfx.h
|
||||
|
||||
#ifndef ZIP7_INC_STDAFX_H
|
||||
#define ZIP7_INC_STDAFX_H
|
||||
|
||||
#if defined(_MSC_VER) && _MSC_VER >= 1800
|
||||
#pragma warning(disable : 4464) // relative include path contains '..'
|
||||
#endif
|
||||
#include "../../../Common/Common.h"
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,20 @@
|
||||
// TempFiles.cpp
|
||||
|
||||
#include "StdAfx.h"
|
||||
|
||||
#include "../../../Windows/FileDir.h"
|
||||
|
||||
#include "TempFiles.h"
|
||||
|
||||
using namespace NWindows;
|
||||
using namespace NFile;
|
||||
|
||||
void CTempFiles::Clear()
|
||||
{
|
||||
while (!Paths.IsEmpty())
|
||||
{
|
||||
if (NeedDeleteFiles)
|
||||
NDir::DeleteFileAlways(Paths.Back());
|
||||
Paths.DeleteBack();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
// TempFiles.h
|
||||
|
||||
#ifndef ZIP7_INC_TEMP_FILES_H
|
||||
#define ZIP7_INC_TEMP_FILES_H
|
||||
|
||||
#include "../../../Common/MyString.h"
|
||||
|
||||
class CTempFiles
|
||||
{
|
||||
void Clear();
|
||||
public:
|
||||
FStringVector Paths;
|
||||
bool NeedDeleteFiles;
|
||||
|
||||
CTempFiles(): NeedDeleteFiles(true) {}
|
||||
~CTempFiles() { Clear(); }
|
||||
};
|
||||
|
||||
#endif
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,221 @@
|
||||
// Update.h
|
||||
|
||||
#ifndef ZIP7_INC_COMMON_UPDATE_H
|
||||
#define ZIP7_INC_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"
|
||||
|
||||
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
|
||||
{
|
||||
bool UpdateArchiveItself;
|
||||
bool SfxMode;
|
||||
|
||||
bool PreserveATime;
|
||||
bool OpenShareForWrite;
|
||||
bool StopAfterOpenError;
|
||||
|
||||
bool StdInMode;
|
||||
bool StdOutMode;
|
||||
|
||||
bool EMailMode;
|
||||
bool EMailRemoveAfter;
|
||||
|
||||
bool DeleteAfterCompressing;
|
||||
bool SetArcMTime;
|
||||
bool RenameMode;
|
||||
|
||||
CBoolPair NtSecurity;
|
||||
CBoolPair AltStreams;
|
||||
CBoolPair HardLinks;
|
||||
CBoolPair SymLinks;
|
||||
|
||||
CBoolPair StoreOwnerId;
|
||||
CBoolPair StoreOwnerName;
|
||||
|
||||
EArcNameMode ArcNameMode;
|
||||
NWildcard::ECensorPathMode PathMode;
|
||||
|
||||
CCompressionMethodMode MethodMode;
|
||||
|
||||
CObjectVector<CUpdateArchiveCommand> Commands;
|
||||
CArchivePath ArchivePath;
|
||||
|
||||
FString SfxModule;
|
||||
UString StdInFileName;
|
||||
UString EMailAddress;
|
||||
FString WorkingDir;
|
||||
// UString AddPathPrefix;
|
||||
|
||||
CObjectVector<CRenamePair> RenamePairs;
|
||||
CRecordVector<UInt64> VolumesSizes;
|
||||
|
||||
bool InitFormatIndex(const CCodecs *codecs, const CObjectVector<COpenType> &types, const UString &arcPath);
|
||||
bool SetArcPath(const CCodecs *codecs, const UString &arcPath);
|
||||
|
||||
CUpdateOptions():
|
||||
UpdateArchiveItself(true),
|
||||
SfxMode(false),
|
||||
|
||||
PreserveATime(false),
|
||||
OpenShareForWrite(false),
|
||||
StopAfterOpenError(false),
|
||||
|
||||
StdInMode(false),
|
||||
StdOutMode(false),
|
||||
|
||||
EMailMode(false),
|
||||
EMailRemoveAfter(false),
|
||||
|
||||
DeleteAfterCompressing(false),
|
||||
SetArcMTime(false),
|
||||
RenameMode(false),
|
||||
|
||||
ArcNameMode(k_ArcNameMode_Smart),
|
||||
PathMode(NWildcard::k_RelatPath)
|
||||
|
||||
{}
|
||||
|
||||
void SetActionCommand_Add()
|
||||
{
|
||||
Commands.Clear();
|
||||
CUpdateArchiveCommand c;
|
||||
c.ActionSet = NUpdateArchive::k_ActionSet_Add;
|
||||
Commands.Add(c);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
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;
|
||||
unsigned NumVolumes;
|
||||
bool IsMultiVolMode;
|
||||
|
||||
CFinishArchiveStat(): OutArcFileSize(0), NumVolumes(0), IsMultiVolMode(false) {}
|
||||
};
|
||||
|
||||
Z7_PURE_INTERFACES_BEGIN
|
||||
|
||||
// INTERFACE_IUpdateCallbackUI(x)
|
||||
// INTERFACE_IDirItemsCallback(x)
|
||||
|
||||
#define Z7_IFACEN_IUpdateCallbackUI2(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 \
|
||||
virtual HRESULT MoveArc_Start(const wchar_t *srcTempPath, const wchar_t *destFinalPath, UInt64 size, Int32 updateMode) x \
|
||||
virtual HRESULT MoveArc_Progress(UInt64 total, UInt64 current) x \
|
||||
virtual HRESULT MoveArc_Finish() x \
|
||||
|
||||
DECLARE_INTERFACE(IUpdateCallbackUI2):
|
||||
public IUpdateCallbackUI,
|
||||
public IDirItemsCallback
|
||||
{
|
||||
Z7_IFACE_PURE(IUpdateCallbackUI2)
|
||||
};
|
||||
Z7_PURE_INTERFACES_END
|
||||
|
||||
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
|
||||
@@ -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
|
||||
}};
|
||||
|
||||
}
|
||||
@@ -0,0 +1,66 @@
|
||||
// UpdateAction.h
|
||||
|
||||
#ifndef ZIP7_INC_UPDATE_ACTION_H
|
||||
#define ZIP7_INC_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
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,197 @@
|
||||
// UpdateCallback.h
|
||||
|
||||
#ifndef ZIP7_INC_UPDATE_CALLBACK_H
|
||||
#define ZIP7_INC_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();
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
Z7_PURE_INTERFACES_BEGIN
|
||||
|
||||
#define Z7_IFACEN_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 ReportUpdateOperation(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 ReportProp(UInt32 indexType, UInt32 index, PROPID propID, const PROPVARIANT *value) x \
|
||||
virtual HRESULT ReportRawProp(UInt32 indexType, UInt32 index, PROPID propID, const void *data, UInt32 dataSize, UInt32 propType) x \
|
||||
virtual HRESULT ReportFinished(UInt32 indexType, UInt32 index, Int32 opRes) x \
|
||||
*/
|
||||
|
||||
/* virtual HRESULT CloseProgress() { return S_OK; } */
|
||||
|
||||
Z7_IFACE_DECL_PURE(IUpdateCallbackUI)
|
||||
Z7_PURE_INTERFACES_END
|
||||
|
||||
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 Z7_final:
|
||||
public IArchiveUpdateCallback2,
|
||||
public IArchiveUpdateCallbackFile,
|
||||
// public IArchiveUpdateCallbackArcProp,
|
||||
public IArchiveExtractCallbackMessage2,
|
||||
public IArchiveGetRawProps,
|
||||
public IArchiveGetRootProps,
|
||||
public ICryptoGetTextPassword2,
|
||||
public ICryptoGetTextPassword,
|
||||
public ICompressProgressInfo,
|
||||
public IInFileStream_Callback,
|
||||
public CMyUnknownImp
|
||||
{
|
||||
Z7_COM_QI_BEGIN2(IArchiveUpdateCallback2)
|
||||
Z7_COM_QI_ENTRY(IArchiveUpdateCallbackFile)
|
||||
// Z7_COM_QI_ENTRY(IArchiveUpdateCallbackArcProp)
|
||||
Z7_COM_QI_ENTRY(IArchiveExtractCallbackMessage2)
|
||||
Z7_COM_QI_ENTRY(IArchiveGetRawProps)
|
||||
Z7_COM_QI_ENTRY(IArchiveGetRootProps)
|
||||
Z7_COM_QI_ENTRY(ICryptoGetTextPassword2)
|
||||
Z7_COM_QI_ENTRY(ICryptoGetTextPassword)
|
||||
Z7_COM_QI_ENTRY(ICompressProgressInfo)
|
||||
Z7_COM_QI_END
|
||||
Z7_COM_ADDREF_RELEASE
|
||||
|
||||
Z7_IFACE_COM7_IMP(ICompressProgressInfo)
|
||||
|
||||
Z7_IFACE_COM7_IMP(IProgress)
|
||||
Z7_IFACE_COM7_IMP(IArchiveUpdateCallback)
|
||||
Z7_IFACE_COM7_IMP(IArchiveUpdateCallback2)
|
||||
Z7_IFACE_COM7_IMP(IArchiveUpdateCallbackFile)
|
||||
// Z7_IFACE_COM7_IMP(IArchiveUpdateCallbackArcProp)
|
||||
Z7_IFACE_COM7_IMP(IArchiveExtractCallbackMessage2)
|
||||
Z7_IFACE_COM7_IMP(IArchiveGetRawProps)
|
||||
Z7_IFACE_COM7_IMP(IArchiveGetRootProps)
|
||||
Z7_IFACE_COM7_IMP(ICryptoGetTextPassword2)
|
||||
Z7_IFACE_COM7_IMP(ICryptoGetTextPassword)
|
||||
|
||||
|
||||
void UpdateProcessedItemStatus(unsigned dirIndex);
|
||||
|
||||
public:
|
||||
bool PreserveATime;
|
||||
bool ShareForWrite;
|
||||
bool StopAfterOpenError;
|
||||
bool StdInMode;
|
||||
|
||||
bool KeepOriginalItemNames;
|
||||
bool StoreNtSecurity;
|
||||
bool StoreHardLinks;
|
||||
bool StoreSymLinks;
|
||||
|
||||
bool StoreOwnerId;
|
||||
bool StoreOwnerName;
|
||||
|
||||
bool Need_LatestMTime;
|
||||
bool LatestMTime_Defined;
|
||||
|
||||
/*
|
||||
bool Need_ArcMTime_Report;
|
||||
bool ArcMTime_WasReported;
|
||||
*/
|
||||
|
||||
CRecordVector<UInt32> _openFiles_Indexes;
|
||||
FStringVector _openFiles_Paths;
|
||||
// CRecordVector< CInFileStream* > _openFiles_Streams;
|
||||
|
||||
bool AreAllFilesClosed() const { return _openFiles_Indexes.IsEmpty(); }
|
||||
virtual HRESULT InFileStream_On_Error(UINT_PTR val, DWORD error) Z7_override;
|
||||
virtual void InFileStream_On_Destroy(CInFileStream *stream, UINT_PTR val) Z7_override;
|
||||
|
||||
IUpdateCallbackUI *Callback;
|
||||
|
||||
const CDirItems *DirItems;
|
||||
const CDirItem *ParentDirItem;
|
||||
|
||||
const CArc *Arc;
|
||||
CMyComPtr<IInArchive> Archive;
|
||||
const CObjectVector<CArcItem> *ArcItems;
|
||||
const CRecordVector<CUpdatePair2> *UpdatePairs;
|
||||
|
||||
CRecordVector<UInt64> VolumesSizes;
|
||||
FString VolName;
|
||||
FString VolExt;
|
||||
UString ArcFileName; // without path prefix
|
||||
|
||||
const UStringVector *NewNames;
|
||||
const UString *Comment;
|
||||
int CommentIndex;
|
||||
|
||||
/*
|
||||
CArcTime Reported_ArcMTime;
|
||||
*/
|
||||
CFiTime LatestMTime;
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
private:
|
||||
#if defined(_WIN32) && !defined(UNDER_CE)
|
||||
bool _saclEnabled;
|
||||
#endif
|
||||
CRecordVector<CKeyKeyValPair> _map;
|
||||
|
||||
UInt32 _hardIndex_From;
|
||||
UInt32 _hardIndex_To;
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,302 @@
|
||||
// UpdatePair.cpp
|
||||
|
||||
#include "StdAfx.h"
|
||||
|
||||
#include <time.h>
|
||||
// #include <stdio.h>
|
||||
|
||||
#include "../../../Common/Wildcard.h"
|
||||
|
||||
#include "../../../Windows/TimeUtils.h"
|
||||
|
||||
#include "SortUtils.h"
|
||||
#include "UpdatePair.h"
|
||||
|
||||
using namespace NWindows;
|
||||
using namespace NTime;
|
||||
|
||||
|
||||
/*
|
||||
a2.Prec =
|
||||
{
|
||||
0 (k_PropVar_TimePrec_0):
|
||||
if GetProperty(kpidMTime) returned 0 and
|
||||
GetProperty(kpidTimeType) did not returned VT_UI4.
|
||||
7z, wim, tar in 7-Zip before v21)
|
||||
in that case we use
|
||||
(prec) that is set by IOutArchive::GetFileTimeType()
|
||||
}
|
||||
*/
|
||||
|
||||
static int MyCompareTime(unsigned prec, const CFiTime &f1, const CArcTime &a2)
|
||||
{
|
||||
// except of precision, we also have limitation, when timestamp is out of range
|
||||
|
||||
/* if (Prec) in archive item is defined, then use global (prec) */
|
||||
if (a2.Prec != k_PropVar_TimePrec_0)
|
||||
prec = a2.Prec;
|
||||
|
||||
CArcTime a1;
|
||||
a1.Set_From_FiTime(f1);
|
||||
/* Set_From_FiTime() must set full form precision:
|
||||
k_PropVar_TimePrec_Base + numDigits
|
||||
windows: 7 digits, non-windows: 9 digits */
|
||||
|
||||
if (prec == k_PropVar_TimePrec_DOS)
|
||||
{
|
||||
const UInt32 dosTime1 = a1.Get_DosTime();
|
||||
const UInt32 dosTime2 = a2.Get_DosTime();
|
||||
return MyCompare(dosTime1, dosTime2);
|
||||
}
|
||||
|
||||
if (prec == k_PropVar_TimePrec_Unix)
|
||||
{
|
||||
const Int64 u2 = FileTime_To_UnixTime64(a2.FT);
|
||||
if (u2 == 0 || u2 == (UInt32)0xFFFFFFFF)
|
||||
{
|
||||
// timestamp probably was saturated in archive to 32-bit
|
||||
// so we use saturated 32-bit value for disk file too.
|
||||
UInt32 u1;
|
||||
FileTime_To_UnixTime(a1.FT, u1);
|
||||
const UInt32 u2_32 = (UInt32)u2;
|
||||
return MyCompare(u1, u2_32);
|
||||
}
|
||||
|
||||
const Int64 u1 = FileTime_To_UnixTime64(a1.FT);
|
||||
return MyCompare(u1, u2);
|
||||
// prec = k_PropVar_TimePrec_Base; // for debug
|
||||
}
|
||||
|
||||
if (prec == k_PropVar_TimePrec_0)
|
||||
prec = k_PropVar_TimePrec_Base + 7;
|
||||
else if (prec == k_PropVar_TimePrec_HighPrec)
|
||||
prec = k_PropVar_TimePrec_Base + 9;
|
||||
else if (prec < k_PropVar_TimePrec_Base)
|
||||
prec = k_PropVar_TimePrec_Base;
|
||||
else if (prec > k_PropVar_TimePrec_Base + 9)
|
||||
prec = k_PropVar_TimePrec_Base + 7;
|
||||
|
||||
// prec now is full form: k_PropVar_TimePrec_Base + numDigits;
|
||||
if (prec > a1.Prec && a1.Prec >= k_PropVar_TimePrec_Base)
|
||||
prec = a1.Prec;
|
||||
|
||||
const unsigned numDigits = prec - k_PropVar_TimePrec_Base;
|
||||
if (numDigits >= 7)
|
||||
{
|
||||
const int comp = CompareFileTime(&a1.FT, &a2.FT);
|
||||
if (comp != 0 || numDigits == 7)
|
||||
return comp;
|
||||
return MyCompare(a1.Ns100, a2.Ns100);
|
||||
}
|
||||
UInt32 d = 1;
|
||||
for (unsigned k = numDigits; k < 7; k++)
|
||||
d *= 10;
|
||||
const UInt64 v1 = a1.Get_FILETIME_as_UInt64() / d * d;
|
||||
const UInt64 v2 = a2.Get_FILETIME_as_UInt64() / d * d;
|
||||
// printf("\ndelta=%d numDigits=%d\n", (unsigned)(v1- v2), numDigits);
|
||||
return MyCompare(v1, v2);
|
||||
}
|
||||
|
||||
|
||||
|
||||
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):";
|
||||
|
||||
Z7_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)
|
||||
{
|
||||
const 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)
|
||||
{
|
||||
const unsigned i1 = *p1;
|
||||
const unsigned i2 = *p2;
|
||||
const CObjectVector<CArcItem> &arcItems = *(const CObjectVector<CArcItem> *)param;
|
||||
const 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;
|
||||
|
||||
const unsigned numDirItems = dirItems.Items.Size();
|
||||
const 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
|
||||
{
|
||||
const 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;
|
||||
|
||||
int compResult = 0;
|
||||
if (ai->MTime.Def)
|
||||
{
|
||||
compResult = MyCompareTime((unsigned)fileTimeType, di->MTime, ai->MTime);
|
||||
}
|
||||
switch (compResult)
|
||||
{
|
||||
case -1: pair.State = NUpdateArchive::NPairState::kNewInArchive; break;
|
||||
case 1: pair.State = NUpdateArchive::NPairState::kOldInArchive; break;
|
||||
default:
|
||||
pair.State = (ai->Size_Defined && di->Size == ai->Size) ?
|
||||
NUpdateArchive::NPairState::kSameFiles :
|
||||
NUpdateArchive::NPairState::kUnknowNewerFiles;
|
||||
}
|
||||
|
||||
dirIndex++;
|
||||
arcIndex++;
|
||||
}
|
||||
|
||||
if (
|
||||
#ifdef _WIN32
|
||||
(di && di->IsAltStream) ||
|
||||
#endif
|
||||
(ai && ai->IsAltStream))
|
||||
{
|
||||
if (prevHostName)
|
||||
{
|
||||
const 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();
|
||||
}
|
||||
@@ -0,0 +1,27 @@
|
||||
// UpdatePair.h
|
||||
|
||||
#ifndef ZIP7_INC_UPDATE_PAIR_H
|
||||
#define ZIP7_INC_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
|
||||
@@ -0,0 +1,74 @@
|
||||
// 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 ((int)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;
|
||||
|
||||
default: throw 123; // break; // is unexpected case
|
||||
}
|
||||
|
||||
up2.IsSameTime = ((unsigned)pair.State == NUpdateArchive::NPairState::kSameFiles);
|
||||
|
||||
operationChain.Add(up2);
|
||||
}
|
||||
|
||||
operationChain.ReserveDown();
|
||||
}
|
||||
@@ -0,0 +1,60 @@
|
||||
// UpdateProduce.h
|
||||
|
||||
#ifndef ZIP7_INC_UPDATE_PRODUCE_H
|
||||
#define ZIP7_INC_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;
|
||||
bool IsSameTime;
|
||||
|
||||
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),
|
||||
IsSameTime(false)
|
||||
{}
|
||||
};
|
||||
|
||||
Z7_PURE_INTERFACES_BEGIN
|
||||
|
||||
DECLARE_INTERFACE(IUpdateProduceCallback)
|
||||
{
|
||||
virtual HRESULT ShowDeleteFile(unsigned arcIndex) = 0;
|
||||
};
|
||||
Z7_PURE_INTERFACES_END
|
||||
|
||||
void UpdateProduce(
|
||||
const CRecordVector<CUpdatePair> &updatePairs,
|
||||
const NUpdateArchive::CActionSet &actionSet,
|
||||
CRecordVector<CUpdatePair2> &operationChain,
|
||||
IUpdateProduceCallback *callback);
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,84 @@
|
||||
// WorkDir.cpp
|
||||
|
||||
#include "StdAfx.h"
|
||||
|
||||
#include "../../../Windows/FileName.h"
|
||||
#include "../../../Windows/FileSystem.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;
|
||||
const FString prefix = path.Left(3);
|
||||
if (NName::IsDrivePath(prefix))
|
||||
{
|
||||
const UINT driveType = NSystem::MyGetDriveType(prefix);
|
||||
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
|
||||
|
||||
const int pos = path.ReverseFind_PathSepar() + 1;
|
||||
fileName = path.Ptr((unsigned)pos);
|
||||
|
||||
FString tempDir;
|
||||
switch ((int)mode)
|
||||
{
|
||||
case NWorkDir::NMode::kCurrent:
|
||||
tempDir = path.Left((unsigned)pos);
|
||||
break;
|
||||
case NWorkDir::NMode::kSpecified:
|
||||
tempDir = workDirInfo.Path;
|
||||
break;
|
||||
// case NWorkDir::NMode::kSystem:
|
||||
default:
|
||||
if (!MyGetTempPath(tempDir))
|
||||
throw 141717;
|
||||
break;
|
||||
}
|
||||
NName::NormalizeDirPathPrefix(tempDir);
|
||||
return tempDir;
|
||||
}
|
||||
|
||||
HRESULT CWorkDirTempFile::CreateTempFile(const FString &originalPath)
|
||||
{
|
||||
NWorkDir::CInfo workDirInfo;
|
||||
workDirInfo.Load();
|
||||
FString namePart;
|
||||
FString path = GetWorkDir(workDirInfo, originalPath, namePart);
|
||||
CreateComplexDir(path);
|
||||
path += namePart;
|
||||
_outStreamSpec = new COutFileStream;
|
||||
OutStream = _outStreamSpec;
|
||||
if (!_tempFile.Create(path, &_outStreamSpec->File))
|
||||
return GetLastError_noZero_HRESULT();
|
||||
_originalPath = originalPath;
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
HRESULT CWorkDirTempFile::MoveToOriginal(bool deleteOriginal,
|
||||
NWindows::NFile::NDir::ICopyFileProgress *progress)
|
||||
{
|
||||
OutStream.Release();
|
||||
if (!_tempFile.MoveTo(_originalPath, deleteOriginal, progress))
|
||||
return GetLastError_noZero_HRESULT();
|
||||
return S_OK;
|
||||
}
|
||||
@@ -0,0 +1,30 @@
|
||||
// WorkDir.h
|
||||
|
||||
#ifndef ZIP7_INC_WORK_DIR_H
|
||||
#define ZIP7_INC_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 MY_UNCOPYABLE
|
||||
{
|
||||
FString _originalPath;
|
||||
NWindows::NFile::NDir::CTempFile _tempFile;
|
||||
COutFileStream *_outStreamSpec;
|
||||
public:
|
||||
CMyComPtr<IOutStream> OutStream;
|
||||
|
||||
const FString &Get_OriginalFilePath() const { return _originalPath; }
|
||||
const FString &Get_TempFilePath() const { return _tempFile.GetPath(); }
|
||||
|
||||
HRESULT CreateTempFile(const FString &originalPath);
|
||||
HRESULT MoveToOriginal(bool deleteOriginal,
|
||||
NWindows::NFile::NDir::ICopyFileProgress *progress = NULL);
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,599 @@
|
||||
// ZipRegistry.cpp
|
||||
|
||||
#include "StdAfx.h"
|
||||
|
||||
#include "../../../../C/CpuArch.h"
|
||||
|
||||
#include "../../../Common/IntToString.h"
|
||||
#include "../../../Common/StringToInt.h"
|
||||
|
||||
#include "../../../Windows/FileDir.h"
|
||||
#include "../../../Windows/Registry.h"
|
||||
#include "../../../Windows/Synchronization.h"
|
||||
|
||||
// #include "../Explorer/ContextMenuFlags.h"
|
||||
#include "ZipRegistry.h"
|
||||
|
||||
using namespace NWindows;
|
||||
using namespace NRegistry;
|
||||
|
||||
static NSynchronization::CCriticalSection g_CS;
|
||||
#define CS_LOCK NSynchronization::CCriticalSectionLock lock(g_CS);
|
||||
|
||||
static LPCTSTR const kCuPrefix = TEXT("Software") TEXT(STRING_PATH_SEPARATOR) TEXT("7-Zip") TEXT(STRING_PATH_SEPARATOR);
|
||||
|
||||
static CSysString GetKeyPath(LPCTSTR path) { return kCuPrefix + (CSysString)path; }
|
||||
|
||||
static LONG OpenMainKey(CKey &key, LPCTSTR keyName)
|
||||
{
|
||||
return key.Open(HKEY_CURRENT_USER, GetKeyPath(keyName), KEY_READ);
|
||||
}
|
||||
|
||||
static LONG CreateMainKey(CKey &key, LPCTSTR keyName)
|
||||
{
|
||||
return key.Create(HKEY_CURRENT_USER, GetKeyPath(keyName));
|
||||
}
|
||||
|
||||
static void Key_Set_UInt32(CKey &key, LPCTSTR name, UInt32 value)
|
||||
{
|
||||
if (value == (UInt32)(Int32)-1)
|
||||
key.DeleteValue(name);
|
||||
else
|
||||
key.SetValue(name, value);
|
||||
}
|
||||
|
||||
|
||||
static void Key_Get_UInt32(CKey &key, LPCTSTR name, UInt32 &value)
|
||||
{
|
||||
value = (UInt32)(Int32)-1;
|
||||
key.GetValue_UInt32_IfOk(name, value);
|
||||
}
|
||||
|
||||
|
||||
static void Key_Set_BoolPair(CKey &key, LPCTSTR name, const CBoolPair &b)
|
||||
{
|
||||
if (b.Def)
|
||||
key.SetValue(name, b.Val);
|
||||
}
|
||||
|
||||
static void Key_Set_bool_if_Changed(CKey &key, LPCTSTR name, bool val)
|
||||
{
|
||||
bool oldVal = false;
|
||||
if (key.GetValue_bool_IfOk(name, oldVal) == ERROR_SUCCESS)
|
||||
if (val == oldVal)
|
||||
return;
|
||||
key.SetValue(name, val);
|
||||
}
|
||||
|
||||
static void Key_Set_BoolPair_Delete_IfNotDef(CKey &key, LPCTSTR name, const CBoolPair &b)
|
||||
{
|
||||
if (b.Def)
|
||||
Key_Set_bool_if_Changed(key, name, b.Val);
|
||||
else
|
||||
key.DeleteValue(name);
|
||||
}
|
||||
|
||||
static void Key_Get_BoolPair(CKey &key, LPCTSTR name, CBoolPair &b)
|
||||
{
|
||||
b.Val = false;
|
||||
b.Def = (key.GetValue_bool_IfOk(name, b.Val) == ERROR_SUCCESS);
|
||||
}
|
||||
|
||||
static void Key_Get_BoolPair_true(CKey &key, LPCTSTR name, CBoolPair &b)
|
||||
{
|
||||
b.Val = true;
|
||||
b.Def = (key.GetValue_bool_IfOk(name, b.Val) == ERROR_SUCCESS);
|
||||
}
|
||||
|
||||
namespace NExtract
|
||||
{
|
||||
|
||||
static LPCTSTR const kKeyName = TEXT("Extraction");
|
||||
|
||||
static LPCTSTR const kExtractMode = TEXT("ExtractMode");
|
||||
static LPCTSTR const kOverwriteMode = TEXT("OverwriteMode");
|
||||
static LPCTSTR const kShowPassword = TEXT("ShowPassword");
|
||||
static LPCTSTR const kPathHistory = TEXT("PathHistory");
|
||||
static LPCTSTR const kSplitDest = TEXT("SplitDest");
|
||||
static LPCTSTR const kElimDup = TEXT("ElimDup");
|
||||
// static LPCTSTR const kAltStreams = TEXT("AltStreams");
|
||||
static LPCTSTR const kNtSecur = TEXT("Security");
|
||||
static LPCTSTR const kMemLimit = TEXT("MemLimit");
|
||||
|
||||
void CInfo::Save() const
|
||||
{
|
||||
CS_LOCK
|
||||
CKey key;
|
||||
CreateMainKey(key, kKeyName);
|
||||
|
||||
if (PathMode_Force)
|
||||
key.SetValue(kExtractMode, (UInt32)PathMode);
|
||||
if (OverwriteMode_Force)
|
||||
key.SetValue(kOverwriteMode, (UInt32)OverwriteMode);
|
||||
|
||||
Key_Set_BoolPair(key, kSplitDest, SplitDest);
|
||||
Key_Set_BoolPair(key, kElimDup, ElimDup);
|
||||
// Key_Set_BoolPair(key, kAltStreams, AltStreams);
|
||||
Key_Set_BoolPair(key, kNtSecur, NtSecurity);
|
||||
Key_Set_BoolPair(key, kShowPassword, ShowPassword);
|
||||
|
||||
key.RecurseDeleteKey(kPathHistory);
|
||||
key.SetValue_Strings(kPathHistory, Paths);
|
||||
}
|
||||
|
||||
void Save_ShowPassword(bool showPassword)
|
||||
{
|
||||
CS_LOCK
|
||||
CKey key;
|
||||
CreateMainKey(key, kKeyName);
|
||||
key.SetValue(kShowPassword, showPassword);
|
||||
}
|
||||
|
||||
void Save_LimitGB(UInt32 limit_GB)
|
||||
{
|
||||
CS_LOCK
|
||||
CKey key;
|
||||
CreateMainKey(key, kKeyName);
|
||||
Key_Set_UInt32(key, kMemLimit, limit_GB);
|
||||
}
|
||||
|
||||
void CInfo::Load()
|
||||
{
|
||||
PathMode = NPathMode::kCurPaths;
|
||||
PathMode_Force = false;
|
||||
OverwriteMode = NOverwriteMode::kAsk;
|
||||
OverwriteMode_Force = false;
|
||||
|
||||
SplitDest.Val = true;
|
||||
|
||||
Paths.Clear();
|
||||
|
||||
CS_LOCK
|
||||
CKey key;
|
||||
if (OpenMainKey(key, kKeyName) != ERROR_SUCCESS)
|
||||
return;
|
||||
|
||||
key.GetValue_Strings(kPathHistory, Paths);
|
||||
UInt32 v;
|
||||
if (key.GetValue_UInt32_IfOk(kExtractMode, v) == ERROR_SUCCESS && v <= NPathMode::kAbsPaths)
|
||||
{
|
||||
PathMode = (NPathMode::EEnum)v;
|
||||
PathMode_Force = true;
|
||||
}
|
||||
if (key.GetValue_UInt32_IfOk(kOverwriteMode, v) == ERROR_SUCCESS && v <= NOverwriteMode::kRenameExisting)
|
||||
{
|
||||
OverwriteMode = (NOverwriteMode::EEnum)v;
|
||||
OverwriteMode_Force = true;
|
||||
}
|
||||
|
||||
Key_Get_BoolPair_true(key, kSplitDest, SplitDest);
|
||||
|
||||
Key_Get_BoolPair(key, kElimDup, ElimDup);
|
||||
// Key_Get_BoolPair(key, kAltStreams, AltStreams);
|
||||
Key_Get_BoolPair(key, kNtSecur, NtSecurity);
|
||||
Key_Get_BoolPair(key, kShowPassword, ShowPassword);
|
||||
}
|
||||
|
||||
bool Read_ShowPassword()
|
||||
{
|
||||
CS_LOCK
|
||||
CKey key;
|
||||
bool showPassword = false;
|
||||
if (OpenMainKey(key, kKeyName) != ERROR_SUCCESS)
|
||||
return showPassword;
|
||||
key.GetValue_bool_IfOk(kShowPassword, showPassword);
|
||||
return showPassword;
|
||||
}
|
||||
|
||||
UInt32 Read_LimitGB()
|
||||
{
|
||||
CS_LOCK
|
||||
CKey key;
|
||||
UInt32 v = (UInt32)(Int32)-1;
|
||||
if (OpenMainKey(key, kKeyName) == ERROR_SUCCESS)
|
||||
key.GetValue_UInt32_IfOk(kMemLimit, v);
|
||||
return v;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
namespace NCompression
|
||||
{
|
||||
|
||||
static LPCTSTR const kKeyName = TEXT("Compression");
|
||||
|
||||
static LPCTSTR const kArcHistory = TEXT("ArcHistory");
|
||||
static LPCWSTR const kArchiver = L"Archiver";
|
||||
static LPCTSTR const kShowPassword = TEXT("ShowPassword");
|
||||
static LPCTSTR const kEncryptHeaders = TEXT("EncryptHeaders");
|
||||
|
||||
static LPCTSTR const kOptionsKeyName = TEXT("Options");
|
||||
|
||||
static LPCTSTR const kLevel = TEXT("Level");
|
||||
static LPCTSTR const kDictionary = TEXT("Dictionary");
|
||||
// static LPCTSTR const kDictionaryChain = TEXT("DictionaryChain");
|
||||
static LPCTSTR const kOrder = TEXT("Order");
|
||||
static LPCTSTR const kBlockSize = TEXT("BlockSize");
|
||||
static LPCTSTR const kNumThreads = TEXT("NumThreads");
|
||||
static LPCWSTR const kMethod = L"Method";
|
||||
static LPCWSTR const kOptions = L"Options";
|
||||
static LPCWSTR const kEncryptionMethod = L"EncryptionMethod";
|
||||
|
||||
static LPCTSTR const kNtSecur = TEXT("Security");
|
||||
static LPCTSTR const kAltStreams = TEXT("AltStreams");
|
||||
static LPCTSTR const kHardLinks = TEXT("HardLinks");
|
||||
static LPCTSTR const kSymLinks = TEXT("SymLinks");
|
||||
static LPCTSTR const kPreserveATime = TEXT("PreserveATime");
|
||||
|
||||
static LPCTSTR const kTimePrec = TEXT("TimePrec");
|
||||
static LPCTSTR const kMTime = TEXT("MTime");
|
||||
static LPCTSTR const kATime = TEXT("ATime");
|
||||
static LPCTSTR const kCTime = TEXT("CTime");
|
||||
static LPCTSTR const kSetArcMTime = TEXT("SetArcMTime");
|
||||
|
||||
static void SetRegString(CKey &key, LPCWSTR name, const UString &value)
|
||||
{
|
||||
if (value.IsEmpty())
|
||||
key.DeleteValue(name);
|
||||
else
|
||||
key.SetValue(name, value);
|
||||
}
|
||||
|
||||
static void GetRegString(CKey &key, LPCWSTR name, UString &value)
|
||||
{
|
||||
if (key.QueryValue(name, value) != ERROR_SUCCESS)
|
||||
value.Empty();
|
||||
}
|
||||
|
||||
static LPCWSTR const kMemUse = L"MemUse"
|
||||
#if defined(MY_CPU_SIZEOF_POINTER) && (MY_CPU_SIZEOF_POINTER == 4)
|
||||
L"32";
|
||||
#else
|
||||
L"64";
|
||||
#endif
|
||||
|
||||
void CInfo::Save() const
|
||||
{
|
||||
CS_LOCK
|
||||
|
||||
CKey key;
|
||||
CreateMainKey(key, kKeyName);
|
||||
|
||||
Key_Set_BoolPair_Delete_IfNotDef (key, kNtSecur, NtSecurity);
|
||||
Key_Set_BoolPair_Delete_IfNotDef (key, kAltStreams, AltStreams);
|
||||
Key_Set_BoolPair_Delete_IfNotDef (key, kHardLinks, HardLinks);
|
||||
Key_Set_BoolPair_Delete_IfNotDef (key, kSymLinks, SymLinks);
|
||||
Key_Set_BoolPair_Delete_IfNotDef (key, kPreserveATime, PreserveATime);
|
||||
|
||||
key.SetValue(kShowPassword, ShowPassword);
|
||||
key.SetValue(kLevel, (UInt32)Level);
|
||||
key.SetValue(kArchiver, ArcType);
|
||||
key.SetValue(kShowPassword, ShowPassword);
|
||||
key.SetValue(kEncryptHeaders, EncryptHeaders);
|
||||
key.RecurseDeleteKey(kArcHistory);
|
||||
key.SetValue_Strings(kArcHistory, ArcPaths);
|
||||
|
||||
key.RecurseDeleteKey(kOptionsKeyName);
|
||||
{
|
||||
CKey optionsKey;
|
||||
optionsKey.Create(key, kOptionsKeyName);
|
||||
FOR_VECTOR (i, Formats)
|
||||
{
|
||||
const CFormatOptions &fo = Formats[i];
|
||||
CKey fk;
|
||||
fk.Create(optionsKey, fo.FormatID);
|
||||
|
||||
SetRegString(fk, kMethod, fo.Method);
|
||||
SetRegString(fk, kOptions, fo.Options);
|
||||
SetRegString(fk, kEncryptionMethod, fo.EncryptionMethod);
|
||||
SetRegString(fk, kMemUse, fo.MemUse);
|
||||
|
||||
Key_Set_UInt32(fk, kLevel, fo.Level);
|
||||
Key_Set_UInt32(fk, kDictionary, fo.Dictionary);
|
||||
// Key_Set_UInt32(fk, kDictionaryChain, fo.DictionaryChain);
|
||||
Key_Set_UInt32(fk, kOrder, fo.Order);
|
||||
Key_Set_UInt32(fk, kBlockSize, fo.BlockLogSize);
|
||||
Key_Set_UInt32(fk, kNumThreads, fo.NumThreads);
|
||||
|
||||
Key_Set_UInt32(fk, kTimePrec, fo.TimePrec);
|
||||
Key_Set_BoolPair_Delete_IfNotDef (fk, kMTime, fo.MTime);
|
||||
Key_Set_BoolPair_Delete_IfNotDef (fk, kATime, fo.ATime);
|
||||
Key_Set_BoolPair_Delete_IfNotDef (fk, kCTime, fo.CTime);
|
||||
Key_Set_BoolPair_Delete_IfNotDef (fk, kSetArcMTime, fo.SetArcMTime);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void CInfo::Load()
|
||||
{
|
||||
ArcPaths.Clear();
|
||||
Formats.Clear();
|
||||
|
||||
Level = 5;
|
||||
ArcType = L"7z";
|
||||
ShowPassword = false;
|
||||
EncryptHeaders = false;
|
||||
|
||||
CS_LOCK
|
||||
CKey key;
|
||||
|
||||
if (OpenMainKey(key, kKeyName) != ERROR_SUCCESS)
|
||||
return;
|
||||
|
||||
Key_Get_BoolPair(key, kNtSecur, NtSecurity);
|
||||
Key_Get_BoolPair(key, kAltStreams, AltStreams);
|
||||
Key_Get_BoolPair(key, kHardLinks, HardLinks);
|
||||
Key_Get_BoolPair(key, kSymLinks, SymLinks);
|
||||
Key_Get_BoolPair(key, kPreserveATime, PreserveATime);
|
||||
|
||||
key.GetValue_Strings(kArcHistory, ArcPaths);
|
||||
|
||||
{
|
||||
CKey optionsKey;
|
||||
if (optionsKey.Open(key, kOptionsKeyName, KEY_READ) == ERROR_SUCCESS)
|
||||
{
|
||||
CSysStringVector formatIDs;
|
||||
optionsKey.EnumKeys(formatIDs);
|
||||
FOR_VECTOR (i, formatIDs)
|
||||
{
|
||||
CKey fk;
|
||||
CFormatOptions fo;
|
||||
fo.FormatID = formatIDs[i];
|
||||
if (fk.Open(optionsKey, fo.FormatID, KEY_READ) == ERROR_SUCCESS)
|
||||
{
|
||||
GetRegString(fk, kMethod, fo.Method);
|
||||
GetRegString(fk, kOptions, fo.Options);
|
||||
GetRegString(fk, kEncryptionMethod, fo.EncryptionMethod);
|
||||
GetRegString(fk, kMemUse, fo.MemUse);
|
||||
|
||||
Key_Get_UInt32(fk, kLevel, fo.Level);
|
||||
Key_Get_UInt32(fk, kDictionary, fo.Dictionary);
|
||||
// Key_Get_UInt32(fk, kDictionaryChain, fo.DictionaryChain);
|
||||
Key_Get_UInt32(fk, kOrder, fo.Order);
|
||||
Key_Get_UInt32(fk, kBlockSize, fo.BlockLogSize);
|
||||
Key_Get_UInt32(fk, kNumThreads, fo.NumThreads);
|
||||
|
||||
Key_Get_UInt32(fk, kTimePrec, fo.TimePrec);
|
||||
Key_Get_BoolPair(fk, kMTime, fo.MTime);
|
||||
Key_Get_BoolPair(fk, kATime, fo.ATime);
|
||||
Key_Get_BoolPair(fk, kCTime, fo.CTime);
|
||||
Key_Get_BoolPair(fk, kSetArcMTime, fo.SetArcMTime);
|
||||
|
||||
Formats.Add(fo);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
UString a;
|
||||
if (key.QueryValue(kArchiver, a) == ERROR_SUCCESS)
|
||||
ArcType = a;
|
||||
key.GetValue_UInt32_IfOk(kLevel, Level);
|
||||
key.GetValue_bool_IfOk(kShowPassword, ShowPassword);
|
||||
key.GetValue_bool_IfOk(kEncryptHeaders, EncryptHeaders);
|
||||
}
|
||||
|
||||
|
||||
static bool ParseMemUse(const wchar_t *s, CMemUse &mu)
|
||||
{
|
||||
mu.Clear();
|
||||
|
||||
bool percentMode = false;
|
||||
{
|
||||
const wchar_t c = *s;
|
||||
if (MyCharLower_Ascii(c) == 'p')
|
||||
{
|
||||
percentMode = true;
|
||||
s++;
|
||||
}
|
||||
}
|
||||
const wchar_t *end;
|
||||
UInt64 number = ConvertStringToUInt64(s, &end);
|
||||
if (end == s)
|
||||
return false;
|
||||
|
||||
wchar_t c = *end;
|
||||
|
||||
if (percentMode)
|
||||
{
|
||||
if (c != 0)
|
||||
return false;
|
||||
mu.IsPercent = true;
|
||||
mu.Val = number;
|
||||
return true;
|
||||
}
|
||||
|
||||
if (c == 0)
|
||||
{
|
||||
mu.Val = number;
|
||||
return true;
|
||||
}
|
||||
|
||||
c = MyCharLower_Ascii(c);
|
||||
|
||||
const wchar_t c1 = end[1];
|
||||
|
||||
if (c == '%')
|
||||
{
|
||||
if (c1 != 0)
|
||||
return false;
|
||||
mu.IsPercent = true;
|
||||
mu.Val = number;
|
||||
return true;
|
||||
}
|
||||
|
||||
if (c == 'b')
|
||||
{
|
||||
if (c1 != 0)
|
||||
return false;
|
||||
mu.Val = number;
|
||||
return true;
|
||||
}
|
||||
|
||||
if (c1 != 0)
|
||||
if (MyCharLower_Ascii(c1) != 'b' || end[2] != 0)
|
||||
return false;
|
||||
|
||||
unsigned numBits;
|
||||
switch (c)
|
||||
{
|
||||
case 'k': numBits = 10; break;
|
||||
case 'm': numBits = 20; break;
|
||||
case 'g': numBits = 30; break;
|
||||
case 't': numBits = 40; break;
|
||||
default: return false;
|
||||
}
|
||||
if (number >= ((UInt64)1 << (64 - numBits)))
|
||||
return false;
|
||||
mu.Val = number << numBits;
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
void CMemUse::Parse(const UString &s)
|
||||
{
|
||||
IsDefined = ParseMemUse(s, *this);
|
||||
}
|
||||
|
||||
/*
|
||||
void MemLimit_Save(const UString &s)
|
||||
{
|
||||
CS_LOCK
|
||||
CKey key;
|
||||
CreateMainKey(key, kKeyName);
|
||||
SetRegString(key, kMemUse, s);
|
||||
}
|
||||
|
||||
bool MemLimit_Load(NCompression::CMemUse &mu)
|
||||
{
|
||||
mu.Clear();
|
||||
UString a;
|
||||
{
|
||||
CS_LOCK
|
||||
CKey key;
|
||||
if (OpenMainKey(key, kKeyName) != ERROR_SUCCESS)
|
||||
return false;
|
||||
if (key.QueryValue(kMemUse, a) != ERROR_SUCCESS)
|
||||
return false;
|
||||
}
|
||||
if (a.IsEmpty())
|
||||
return false;
|
||||
mu.Parse(a);
|
||||
return mu.IsDefined;
|
||||
}
|
||||
*/
|
||||
|
||||
}
|
||||
|
||||
static LPCTSTR const kOptionsInfoKeyName = TEXT("Options");
|
||||
|
||||
namespace NWorkDir
|
||||
{
|
||||
static LPCTSTR const kWorkDirType = TEXT("WorkDirType");
|
||||
static LPCWSTR const kWorkDirPath = L"WorkDirPath";
|
||||
static LPCTSTR const kTempRemovableOnly = TEXT("TempRemovableOnly");
|
||||
|
||||
|
||||
void CInfo::Save()const
|
||||
{
|
||||
CS_LOCK
|
||||
CKey key;
|
||||
CreateMainKey(key, kOptionsInfoKeyName);
|
||||
key.SetValue(kWorkDirType, (UInt32)Mode);
|
||||
key.SetValue(kWorkDirPath, fs2us(Path));
|
||||
key.SetValue(kTempRemovableOnly, ForRemovableOnly);
|
||||
}
|
||||
|
||||
void CInfo::Load()
|
||||
{
|
||||
SetDefault();
|
||||
|
||||
CS_LOCK
|
||||
CKey key;
|
||||
if (OpenMainKey(key, kOptionsInfoKeyName) != ERROR_SUCCESS)
|
||||
return;
|
||||
|
||||
UInt32 dirType;
|
||||
if (key.GetValue_UInt32_IfOk(kWorkDirType, dirType) != ERROR_SUCCESS)
|
||||
return;
|
||||
switch (dirType)
|
||||
{
|
||||
case NMode::kSystem:
|
||||
case NMode::kCurrent:
|
||||
case NMode::kSpecified:
|
||||
Mode = (NMode::EEnum)dirType;
|
||||
}
|
||||
UString pathU;
|
||||
if (key.QueryValue(kWorkDirPath, pathU) == ERROR_SUCCESS)
|
||||
Path = us2fs(pathU);
|
||||
else
|
||||
{
|
||||
Path.Empty();
|
||||
if (Mode == NMode::kSpecified)
|
||||
Mode = NMode::kSystem;
|
||||
}
|
||||
key.GetValue_bool_IfOk(kTempRemovableOnly, ForRemovableOnly);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
static LPCTSTR const kCascadedMenu = TEXT("CascadedMenu");
|
||||
static LPCTSTR const kContextMenu = TEXT("ContextMenu");
|
||||
static LPCTSTR const kMenuIcons = TEXT("MenuIcons");
|
||||
static LPCTSTR const kElimDup = TEXT("ElimDupExtract");
|
||||
static LPCTSTR const kWriteZoneId = TEXT("WriteZoneIdExtract");
|
||||
|
||||
void CContextMenuInfo::Save() const
|
||||
{
|
||||
CS_LOCK
|
||||
CKey key;
|
||||
CreateMainKey(key, kOptionsInfoKeyName);
|
||||
|
||||
Key_Set_BoolPair(key, kCascadedMenu, Cascaded);
|
||||
Key_Set_BoolPair(key, kMenuIcons, MenuIcons);
|
||||
Key_Set_BoolPair(key, kElimDup, ElimDup);
|
||||
|
||||
Key_Set_UInt32(key, kWriteZoneId, WriteZone);
|
||||
|
||||
if (Flags_Def)
|
||||
key.SetValue(kContextMenu, Flags);
|
||||
}
|
||||
|
||||
void CContextMenuInfo::Load()
|
||||
{
|
||||
Cascaded.Val = true;
|
||||
Cascaded.Def = false;
|
||||
|
||||
MenuIcons.Val = false;
|
||||
MenuIcons.Def = false;
|
||||
|
||||
ElimDup.Val = true;
|
||||
ElimDup.Def = false;
|
||||
|
||||
WriteZone = (UInt32)(Int32)-1;
|
||||
|
||||
/* we can disable email items by default,
|
||||
because email code doesn't work in some systems */
|
||||
Flags = (UInt32)(Int32)-1
|
||||
/*
|
||||
& ~NContextMenuFlags::kCompressEmail
|
||||
& ~NContextMenuFlags::kCompressTo7zEmail
|
||||
& ~NContextMenuFlags::kCompressToZipEmail
|
||||
*/
|
||||
;
|
||||
Flags_Def = false;
|
||||
|
||||
CS_LOCK
|
||||
|
||||
CKey key;
|
||||
if (OpenMainKey(key, kOptionsInfoKeyName) != ERROR_SUCCESS)
|
||||
return;
|
||||
|
||||
Key_Get_BoolPair_true(key, kCascadedMenu, Cascaded);
|
||||
Key_Get_BoolPair_true(key, kElimDup, ElimDup);
|
||||
Key_Get_BoolPair(key, kMenuIcons, MenuIcons);
|
||||
|
||||
Key_Get_UInt32(key, kWriteZoneId, WriteZone);
|
||||
|
||||
Flags_Def = (key.GetValue_UInt32_IfOk(kContextMenu, Flags) == ERROR_SUCCESS);
|
||||
}
|
||||
@@ -0,0 +1,212 @@
|
||||
// ZipRegistry.h
|
||||
|
||||
#ifndef ZIP7_INC_ZIP_REGISTRY_H
|
||||
#define ZIP7_INC_ZIP_REGISTRY_H
|
||||
|
||||
#include "../../../Common/MyTypes.h"
|
||||
#include "../../../Common/MyString.h"
|
||||
|
||||
#include "../../Common/MethodProps.h"
|
||||
|
||||
#include "ExtractMode.h"
|
||||
|
||||
/*
|
||||
CBoolPair::Def in writing functions means:
|
||||
if ( CBoolPair::Def ), we write CBoolPair::Val
|
||||
if ( !CBoolPair::Def )
|
||||
{
|
||||
in NCompression functions we delete registry value
|
||||
in another functions we do nothing
|
||||
}
|
||||
*/
|
||||
|
||||
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();
|
||||
|
||||
void Save_LimitGB(UInt32 limit_GB);
|
||||
UInt32 Read_LimitGB();
|
||||
}
|
||||
|
||||
namespace NCompression
|
||||
{
|
||||
struct CMemUse
|
||||
{
|
||||
// UString Str;
|
||||
bool IsDefined;
|
||||
bool IsPercent;
|
||||
UInt64 Val;
|
||||
|
||||
CMemUse():
|
||||
IsDefined(false),
|
||||
IsPercent(false),
|
||||
Val(0)
|
||||
{}
|
||||
|
||||
void Clear()
|
||||
{
|
||||
// Str.Empty();
|
||||
IsDefined = false;
|
||||
IsPercent = false;
|
||||
Val = 0;
|
||||
}
|
||||
|
||||
UInt64 GetBytes(UInt64 ramSize) const
|
||||
{
|
||||
if (!IsPercent)
|
||||
return Val;
|
||||
return Calc_From_Val_Percents(ramSize, Val);
|
||||
}
|
||||
void Parse(const UString &s);
|
||||
};
|
||||
|
||||
struct CFormatOptions
|
||||
{
|
||||
UInt32 Level;
|
||||
UInt32 Dictionary;
|
||||
// UInt32 DictionaryChain;
|
||||
UInt32 Order;
|
||||
UInt32 BlockLogSize;
|
||||
UInt32 NumThreads;
|
||||
|
||||
UInt32 TimePrec;
|
||||
CBoolPair MTime;
|
||||
CBoolPair ATime;
|
||||
CBoolPair CTime;
|
||||
CBoolPair SetArcMTime;
|
||||
|
||||
CSysString FormatID;
|
||||
UString Method;
|
||||
UString Options;
|
||||
UString EncryptionMethod;
|
||||
UString MemUse;
|
||||
|
||||
void Reset_TimePrec()
|
||||
{
|
||||
TimePrec = (UInt32)(Int32)-1;
|
||||
}
|
||||
|
||||
bool IsSet_TimePrec() const
|
||||
{
|
||||
return TimePrec != (UInt32)(Int32)-1;
|
||||
}
|
||||
|
||||
|
||||
void Reset_BlockLogSize()
|
||||
{
|
||||
BlockLogSize = (UInt32)(Int32)-1;
|
||||
}
|
||||
|
||||
void ResetForLevelChange()
|
||||
{
|
||||
BlockLogSize = NumThreads = Level = Dictionary = Order = (UInt32)(Int32)-1;
|
||||
// DictionaryChain = (UInt32)(Int32)-1;
|
||||
Method.Empty();
|
||||
// Options.Empty();
|
||||
// EncryptionMethod.Empty();
|
||||
}
|
||||
CFormatOptions()
|
||||
{
|
||||
// TimePrec = 0;
|
||||
Reset_TimePrec();
|
||||
ResetForLevelChange();
|
||||
}
|
||||
};
|
||||
|
||||
struct CInfo
|
||||
{
|
||||
UInt32 Level;
|
||||
bool ShowPassword;
|
||||
bool EncryptHeaders;
|
||||
|
||||
CBoolPair NtSecurity;
|
||||
CBoolPair AltStreams;
|
||||
CBoolPair HardLinks;
|
||||
CBoolPair SymLinks;
|
||||
|
||||
CBoolPair PreserveATime;
|
||||
|
||||
UString ArcType;
|
||||
UStringVector ArcPaths;
|
||||
|
||||
CObjectVector<CFormatOptions> Formats;
|
||||
|
||||
void Save() const;
|
||||
void Load();
|
||||
};
|
||||
}
|
||||
|
||||
namespace NWorkDir
|
||||
{
|
||||
namespace NMode
|
||||
{
|
||||
enum EEnum
|
||||
{
|
||||
kSystem,
|
||||
kCurrent,
|
||||
kSpecified
|
||||
};
|
||||
}
|
||||
struct CInfo
|
||||
{
|
||||
NMode::EEnum Mode;
|
||||
bool ForRemovableOnly;
|
||||
FString Path;
|
||||
|
||||
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;
|
||||
UInt32 WriteZone;
|
||||
|
||||
/*
|
||||
CContextMenuInfo():
|
||||
Flags_Def(0),
|
||||
WriteZone((UInt32)(Int32)-1),
|
||||
Flags((UInt32)(Int32)-1)
|
||||
{}
|
||||
*/
|
||||
|
||||
void Save() const;
|
||||
void Load();
|
||||
};
|
||||
|
||||
#endif
|
||||
Reference in New Issue
Block a user