Update to 7-Zip Version 22.00

See: https://sourceforge.net/p/sevenzip/discussion/45797/thread/9c2d9061ce/
This commit is contained in:
Tino Reichardt
2022-08-07 09:59:33 +02:00
parent 6a4fe97fc3
commit 57558682a8
211 changed files with 15251 additions and 2482 deletions

View File

@@ -160,7 +160,11 @@ enum Enum
kSymLinks_AllowDangerous,
kSymLinks,
kNtSecurity,
kStoreOwnerId,
kStoreOwnerName,
kZoneFile,
kAltStreams,
kReplaceColonForAltStream,
kWriteToAltStreamIfColon,
@@ -304,7 +308,11 @@ static const CSwitchForm kSwitchForms[] =
{ "snld", SWFRM_MINUS },
{ "snl", SWFRM_MINUS },
{ "sni", SWFRM_SIMPLE },
{ "snoi", SWFRM_MINUS },
{ "snon", SWFRM_MINUS },
{ "snz", SWFRM_STRING_SINGL(0) },
{ "sns", SWFRM_MINUS },
{ "snr", SWFRM_SIMPLE },
{ "snc", SWFRM_SIMPLE },
@@ -1032,9 +1040,9 @@ void CArcCmdLineParser::Parse1(const UStringVector &commandStrings,
if (parser[NKey::kCaseSensitive].ThereIs)
{
options.CaseSensitive =
g_CaseSensitive = !parser[NKey::kCaseSensitive].WithMinus;
options.CaseSensitiveChange = true;
options.CaseSensitive = g_CaseSensitive;
options.CaseSensitive_Change = true;
}
@@ -1367,6 +1375,9 @@ void CArcCmdLineParser::Parse2(CArcCmdLineOptions &options)
SetBoolPair(parser, NKey::kAltStreams, options.AltStreams);
SetBoolPair(parser, NKey::kHardLinks, options.HardLinks);
SetBoolPair(parser, NKey::kSymLinks, options.SymLinks);
SetBoolPair(parser, NKey::kStoreOwnerId, options.StoreOwnerId);
SetBoolPair(parser, NKey::kStoreOwnerName, options.StoreOwnerName);
CBoolPair symLinks_AllowDangerous;
SetBoolPair(parser, NKey::kSymLinks_AllowDangerous, symLinks_AllowDangerous);
@@ -1420,12 +1431,28 @@ void CArcCmdLineParser::Parse2(CArcCmdLineOptions &options)
nt.ReplaceColonForAltStream = parser[NKey::kReplaceColonForAltStream].ThereIs;
nt.WriteToAltStreamIfColon = parser[NKey::kWriteToAltStreamIfColon].ThereIs;
nt.ExtractOwner = options.StoreOwnerId.Val; // StoreOwnerName
if (parser[NKey::kPreserveATime].ThereIs)
nt.PreserveATime = true;
if (parser[NKey::kShareForWrite].ThereIs)
nt.OpenShareForWrite = true;
}
if (parser[NKey::kZoneFile].ThereIs)
{
eo.ZoneMode = NExtract::NZoneIdMode::kAll;
const UString &s = parser[NKey::kZoneFile].PostStrings[0];
if (!s.IsEmpty())
{
if (s == L"0") eo.ZoneMode = NExtract::NZoneIdMode::kNone;
else if (s == L"1") eo.ZoneMode = NExtract::NZoneIdMode::kAll;
else if (s == L"2") eo.ZoneMode = NExtract::NZoneIdMode::kOffice;
else
throw CArcCmdLineException("Unsupported -snz:", s);
}
}
options.Censor.AddPathsToCensor(NWildcard::k_AbsPath);
options.Censor.ExtendExclude();
@@ -1549,6 +1576,9 @@ void CArcCmdLineParser::Parse2(CArcCmdLineOptions &options)
updateOptions.NtSecurity = options.NtSecurity;
updateOptions.HardLinks = options.HardLinks;
updateOptions.SymLinks = options.SymLinks;
updateOptions.StoreOwnerId = options.StoreOwnerId;
updateOptions.StoreOwnerName = options.StoreOwnerName;
updateOptions.EMailMode = parser[NKey::kEmail].ThereIs;
if (updateOptions.EMailMode)

View File

@@ -51,7 +51,7 @@ struct CArcCmdLineOptions
bool HelpMode;
// bool LargePages;
bool CaseSensitiveChange;
bool CaseSensitive_Change;
bool CaseSensitive;
bool IsInTerminal;
@@ -97,6 +97,9 @@ struct CArcCmdLineOptions
CBoolPair AltStreams;
CBoolPair HardLinks;
CBoolPair SymLinks;
CBoolPair StoreOwnerId;
CBoolPair StoreOwnerName;
CUpdateOptions UpdateOptions;
CHashOptions HashOptions;
@@ -117,7 +120,7 @@ struct CArcCmdLineOptions
CArcCmdLineOptions():
HelpMode(false),
// LargePages(false),
CaseSensitiveChange(false),
CaseSensitive_Change(false),
CaseSensitive(false),
IsInTerminal(false),

View File

@@ -95,6 +95,83 @@ bool InitLocalPrivileges()
#endif // _USE_SECURITY_CODE
#if defined(_WIN32) && !defined(UNDER_CE) && !defined(_SFX)
static const char * const kOfficeExtensions =
" doc dot wbk"
" docx docm dotx dotm docb wll wwl"
" xls xlt xlm"
" xlsx xlsm xltx xltm xlsb xla xlam"
" ppt pot pps ppa ppam"
" pptx pptm potx potm ppam ppsx ppsm sldx sldm"
" ";
static bool FindExt2(const char *p, const UString &name)
{
const int pathPos = name.ReverseFind_PathSepar();
const int dotPos = name.ReverseFind_Dot();
if (dotPos < 0
|| dotPos < pathPos
|| dotPos == (int)name.Len() - 1)
return false;
AString s;
for (unsigned pos = dotPos + 1;; pos++)
{
const wchar_t c = name[pos];
if (c <= 0)
break;
if (c >= 0x80)
return false;
s += (char)MyCharLower_Ascii((char)c);
}
for (unsigned i = 0; p[i] != 0;)
{
unsigned j;
for (j = i; p[j] != ' '; j++);
if (s.Len() == j - i && memcmp(p + i, (const char *)s, s.Len()) == 0)
return true;
i = j + 1;
}
return false;
}
static const FChar * const k_ZoneId_StreamName = FTEXT(":Zone.Identifier");
void ReadZoneFile_Of_BaseFile(CFSTR fileName2, CByteBuffer &buf)
{
FString fileName = fileName2;
fileName += k_ZoneId_StreamName;
buf.Free();
NIO::CInFile file;
if (!file.Open(fileName))
return;
UInt64 fileSize;
if (!file.GetLength(fileSize))
return;
if (fileSize == 0 || fileSize >= ((UInt32)1 << 16))
return;
buf.Alloc((size_t)fileSize);
size_t processed;
if (file.ReadFull(buf, (size_t)fileSize, processed) && processed == fileSize)
return;
buf.Free();
}
static bool WriteZoneFile(CFSTR fileName, const CByteBuffer &buf)
{
NIO::COutFile file;
if (!file.Create(fileName, true))
return false;
return file.WriteFull(buf, buf.Size());
}
#endif
#ifdef SUPPORT_LINKS
int CHardLinkNode::Compare(const CHardLinkNode &a) const
@@ -190,9 +267,9 @@ HRESULT CArchiveExtractCallback::PrepareHardLinks(const CRecordVector<UInt32> *r
CArchiveExtractCallback::CArchiveExtractCallback():
_arc(NULL),
WriteCTime(true),
WriteATime(true),
WriteMTime(true),
Write_CTime(true),
Write_ATime(true),
Write_MTime(true),
_multiArchives(false)
{
LocalProgressSpec = new CLocalProgress();
@@ -204,6 +281,13 @@ CArchiveExtractCallback::CArchiveExtractCallback():
}
void CArchiveExtractCallback::InitBeforeNewArchive()
{
#if defined(_WIN32) && !defined(UNDER_CE)
ZoneBuf.Free();
#endif
}
void CArchiveExtractCallback::Init(
const CExtractNtOptions &ntOptions,
const NWildcard::CCensorNode *wildcardCensor,
@@ -240,13 +324,19 @@ void CArchiveExtractCallback::Init(
_progressTotal_Defined = true;
_extractCallback2 = extractCallback2;
_compressProgress.Release();
_extractCallback2.QueryInterface(IID_ICompressProgressInfo, &_compressProgress);
_callbackMessage.Release();
_extractCallback2.QueryInterface(IID_IArchiveExtractCallbackMessage, &_callbackMessage);
_folderArchiveExtractCallback2.Release();
_extractCallback2.QueryInterface(IID_IFolderArchiveExtractCallback2, &_folderArchiveExtractCallback2);
#ifndef _SFX
ExtractToStreamCallback.Release();
_extractCallback2.QueryInterface(IID_IFolderExtractToStreamCallback, &ExtractToStreamCallback);
if (ExtractToStreamCallback)
{
@@ -416,26 +506,22 @@ void CArchiveExtractCallback::CreateComplexDirectory(const UStringVector &dirPat
}
HRESULT CArchiveExtractCallback::GetTime(UInt32 index, PROPID propID, FILETIME &filetime, bool &filetimeIsDefined)
HRESULT CArchiveExtractCallback::GetTime(UInt32 index, PROPID propID, CArcTime &ft)
{
filetimeIsDefined = false;
filetime.dwLowDateTime = 0;
filetime.dwHighDateTime = 0;
ft.Clear();
NCOM::CPropVariant prop;
RINOK(_arc->Archive->GetProperty(index, propID, &prop));
if (prop.vt == VT_FILETIME)
{
filetime = prop.filetime;
filetimeIsDefined = (filetime.dwHighDateTime != 0 || filetime.dwLowDateTime != 0);
}
ft.Set_From_Prop(prop);
else if (prop.vt != VT_EMPTY)
return E_FAIL;
return S_OK;
}
HRESULT CArchiveExtractCallback::GetUnpackSize()
{
return _arc->GetItemSize(_index, _curSize, _curSizeDefined);
return _arc->GetItem_Size(_index, _curSize, _curSizeDefined);
}
static void AddPathToMessage(UString &s, const FString &path)
@@ -454,8 +540,9 @@ HRESULT CArchiveExtractCallback::SendMessageError(const char *message, const FSt
HRESULT CArchiveExtractCallback::SendMessageError_with_LastError(const char *message, const FString &path)
{
DWORD errorCode = GetLastError();
if (errorCode == 0)
errorCode = (DWORD)E_FAIL;
UString s (message);
if (errorCode != 0)
{
s += " : ";
s += NError::MyFormatMessage(errorCode);
@@ -843,13 +930,58 @@ HRESULT CArchiveExtractCallback::ReadLink()
#endif // SUPPORT_LINKS
#ifndef _WIN32
static HRESULT GetOwner(IInArchive *archive,
UInt32 index, UInt32 pidName, UInt32 pidId, COwnerInfo &res)
{
{
NWindows::NCOM::CPropVariant prop;
RINOK(archive->GetProperty(index, pidId, &prop));
if (prop.vt == VT_UI4)
{
res.Id_Defined = true;
res.Id = prop.ulVal; // for debug
// res.Id++; // for debug
// if (pidId == kpidGroupId) res.Id += 7; // for debug
// res.Id = 0; // for debug
}
else if (prop.vt != VT_EMPTY)
return E_INVALIDARG;
}
{
NWindows::NCOM::CPropVariant prop;
RINOK(archive->GetProperty(index, pidName, &prop));
if (prop.vt == VT_BSTR)
{
const UString s = prop.bstrVal;
ConvertUnicodeToUTF8(s, res.Name);
}
else if (prop.vt == VT_UI4)
{
res.Id_Defined = true;
res.Id = prop.ulVal;
}
else if (prop.vt != VT_EMPTY)
return E_INVALIDARG;
}
return S_OK;
}
#endif
HRESULT CArchiveExtractCallback::Read_fi_Props()
{
IInArchive *archive = _arc->Archive;
const UInt32 index = _index;
_fi.AttribDefined = false;
_fi.Attrib_Defined = false;
#ifndef _WIN32
_fi.Owner.Clear();
_fi.Group.Clear();
#endif
{
NCOM::CPropVariant prop;
@@ -868,15 +1000,25 @@ HRESULT CArchiveExtractCallback::Read_fi_Props()
if (prop.vt == VT_UI4)
{
_fi.Attrib = prop.ulVal;
_fi.AttribDefined = true;
_fi.Attrib_Defined = true;
}
else if (prop.vt != VT_EMPTY)
return E_FAIL;
}
RINOK(GetTime(index, kpidCTime, _fi.CTime, _fi.CTimeDefined));
RINOK(GetTime(index, kpidATime, _fi.ATime, _fi.ATimeDefined));
RINOK(GetTime(index, kpidMTime, _fi.MTime, _fi.MTimeDefined));
RINOK(GetTime(index, kpidCTime, _fi.CTime));
RINOK(GetTime(index, kpidATime, _fi.ATime));
RINOK(GetTime(index, kpidMTime, _fi.MTime));
#ifndef _WIN32
if (_ntOptions.ExtractOwner)
{
// SendMessageError_with_LastError("_ntOptions.ExtractOwner", _diskFilePath);
GetOwner(archive, index, kpidUser, kpidUserId, _fi.Owner);
GetOwner(archive, index, kpidGroup, kpidGroupId, _fi.Group);
}
#endif
return S_OK;
}
@@ -923,6 +1065,39 @@ void CArchiveExtractCallback::CorrectPathParts()
}
void CArchiveExtractCallback::GetFiTimesCAM(CFiTimesCAM &pt)
{
pt.CTime_Defined = false;
pt.ATime_Defined = false;
pt.MTime_Defined = false;
if (Write_MTime)
{
if (_fi.MTime.Def)
{
_fi.MTime.Write_To_FiTime(pt.MTime);
pt.MTime_Defined = true;
}
else if (_arc->MTime.Def)
{
_arc->MTime.Write_To_FiTime(pt.MTime);
pt.MTime_Defined = true;
}
}
if (Write_CTime && _fi.CTime.Def)
{
_fi.CTime.Write_To_FiTime(pt.CTime);
pt.CTime_Defined = true;
}
if (Write_ATime && _fi.ATime.Def)
{
_fi.ATime.Write_To_FiTime(pt.ATime);
pt.ATime_Defined = true;
}
}
void CArchiveExtractCallback::CreateFolders()
{
@@ -948,30 +1123,9 @@ void CArchiveExtractCallback::CreateFolders()
return;
CDirPathTime pt;
pt.CTime = _fi.CTime;
pt.CTimeDefined = (WriteCTime && _fi.CTimeDefined);
pt.ATime = _fi.ATime;
pt.ATimeDefined = (WriteATime && _fi.ATimeDefined);
pt.MTimeDefined = false;
if (WriteMTime)
{
if (_fi.MTimeDefined)
{
pt.MTime = _fi.MTime;
pt.MTimeDefined = true;
}
else if (_arc->MTimeDefined)
{
pt.MTime = _arc->MTime;
pt.MTimeDefined = true;
}
}
if (pt.MTimeDefined || pt.ATimeDefined || pt.CTimeDefined)
GetFiTimesCAM(pt);
if (pt.IsSomeTimeDefined())
{
pt.Path = fullPathNew;
pt.SetDirTime();
@@ -1006,10 +1160,13 @@ HRESULT CArchiveExtractCallback::CheckExistFile(FString &fullProcessedPath, bool
/* (fileInfo) can be symbolic link.
we can show final file properties here. */
FILETIME ft1;
FiTime_To_FILETIME(fileInfo.MTime, ft1);
Int32 overwriteResult;
RINOK(_extractCallback2->AskOverwrite(
fs2us(realFullProcessedPath), &fileInfo.MTime, &fileInfo.Size, _item.Path,
_fi.MTimeDefined ? &_fi.MTime : NULL,
fs2us(realFullProcessedPath), &ft1, &fileInfo.Size, _item.Path,
_fi.MTime.Def ? &_fi.MTime.FT : NULL,
_curSizeDefined ? &_curSize : NULL,
&overwriteResult))
@@ -1126,7 +1283,7 @@ HRESULT CArchiveExtractCallback::GetExtractStream(CMyComPtr<ISequentialOutStream
const UInt32 index = _index;
bool isAnti = false;
RINOK(_arc->IsItemAnti(index, isAnti));
RINOK(_arc->IsItem_Anti(index, isAnti));
CorrectPathParts();
UString processedPath (MakePathFromParts(_item.PathParts));
@@ -1147,8 +1304,8 @@ HRESULT CArchiveExtractCallback::GetExtractStream(CMyComPtr<ISequentialOutStream
#ifdef SUPPORT_ALT_STREAMS
if (_item.IsAltStream && _item.ParentIndex != (UInt32)(Int32)-1)
{
int renIndex = _renamedFiles.FindInSorted(CIndexToPathPair(_item.ParentIndex));
if (renIndex >= 0)
const int renIndex = _renamedFiles.FindInSorted(CIndexToPathPair(_item.ParentIndex));
if (renIndex != -1)
{
const CIndexToPathPair &pair = _renamedFiles[(unsigned)renIndex];
fullProcessedPath = pair.Path;
@@ -1224,8 +1381,8 @@ HRESULT CArchiveExtractCallback::GetExtractStream(CMyComPtr<ISequentialOutStream
RINOK(Archive_Get_HardLinkNode(archive, index, h, defined));
if (defined)
{
int linkIndex = _hardLinks.IDs.FindInSorted2(h);
if (linkIndex >= 0)
const int linkIndex = _hardLinks.IDs.FindInSorted2(h);
if (linkIndex != -1)
{
FString &hl = _hardLinks.Links[(unsigned)linkIndex];
if (hl.IsEmpty())
@@ -1733,11 +1890,34 @@ HRESULT CArchiveExtractCallback::CloseFile()
_curSize = processedSize;
_curSizeDefined = true;
#if defined(_WIN32) && !defined(UNDER_CE) && !defined(_SFX)
if (ZoneBuf.Size() != 0
&& !_item.IsAltStream)
{
// if (NFind::DoesFileExist_Raw(tempFilePath))
if (ZoneMode != NExtract::NZoneIdMode::kOffice ||
FindExt2(kOfficeExtensions, _diskFilePath))
{
// we must write zone file before setting of timestamps
const FString path = _diskFilePath + k_ZoneId_StreamName;
if (!WriteZoneFile(path, ZoneBuf))
{
// we can't write it in FAT
// SendMessageError_with_LastError("Can't write Zone.Identifier stream", path);
}
}
}
#endif
CFiTimesCAM t;
GetFiTimesCAM(t);
// #ifdef _WIN32
_outFileStreamSpec->SetTime(
(WriteCTime && _fi.CTimeDefined) ? &_fi.CTime : NULL,
(WriteATime && _fi.ATimeDefined) ? &_fi.ATime : NULL,
(WriteMTime && _fi.MTimeDefined) ? &_fi.MTime : (_arc->MTimeDefined ? &_arc->MTime : NULL));
if (t.IsSomeTimeDefined())
_outFileStreamSpec->SetTime(
t.CTime_Defined ? &t.CTime : NULL,
t.ATime_Defined ? &t.ATime : NULL,
t.MTime_Defined ? &t.MTime : NULL);
// #endif
RINOK(_outFileStreamSpec->Close());
@@ -2065,19 +2245,30 @@ HRESULT CArchiveExtractCallback::CloseReparseAndFile()
void CArchiveExtractCallback::SetAttrib()
{
#ifndef _WIN32
#ifndef _WIN32
// Linux now doesn't support permissions for symlinks
if (_isSymLinkCreated)
return;
#endif
#endif
if (_itemFailure
|| _diskFilePath.IsEmpty()
|| _stdOutMode
|| !_extractMode
|| !_fi.AttribDefined)
|| !_extractMode)
return;
#ifndef _WIN32
if (_fi.Owner.Id_Defined &&
_fi.Group.Id_Defined)
{
if (my_chown(_diskFilePath, _fi.Owner.Id, _fi.Group.Id) != 0)
{
SendMessageError_with_LastError("Cannot set owner", _diskFilePath);
}
}
#endif
if (_fi.Attrib_Defined)
{
// const AString s = GetAnsiString(_diskFilePath);
// printf("\nSetFileAttrib_PosixHighDetect: %s: hex:%x\n", s.Ptr(), _fi.Attrib);
@@ -2276,7 +2467,7 @@ STDMETHODIMP CArchiveExtractCallback::GetStream2(UInt32 index, ISequentialInStre
CInFileStream *inStreamSpec = new CInFileStream;
CMyComPtr<ISequentialInStream> inStreamRef = inStreamSpec;
inStreamSpec->File.PreserveATime = _ntOptions.PreserveATime;
inStreamSpec->Set_PreserveATime(_ntOptions.PreserveATime);
if (!inStreamSpec->OpenShared(fullProcessedPath, _ntOptions.OpenShareForWrite))
{
RINOK(SendMessageError_with_LastError(kCantOpenInFile, fullProcessedPath));
@@ -2318,9 +2509,9 @@ void CDirPathSortPair::SetNumSlashes(const FChar *s)
bool CDirPathTime::SetDirTime() const
{
return NDir::SetDirTime(Path,
CTimeDefined ? &CTime : NULL,
ATimeDefined ? &ATime : NULL,
MTimeDefined ? &MTime : NULL);
CTime_Defined ? &CTime : NULL,
ATime_Defined ? &ATime : NULL,
MTime_Defined ? &MTime : NULL);
}

View File

@@ -60,6 +60,8 @@ struct CExtractNtOptions
bool ReplaceColonForAltStream;
bool WriteToAltStreamIfColon;
bool ExtractOwner;
bool PreAllocateOutFile;
// used for hash arcs only, when we open external files
@@ -69,6 +71,7 @@ struct CExtractNtOptions
CExtractNtOptions():
ReplaceColonForAltStream(false),
WriteToAltStreamIfColon(false),
ExtractOwner(false),
PreserveATime(false),
OpenShareForWrite(false)
{
@@ -163,16 +166,27 @@ struct CIndexToPathPair
struct CDirPathTime
struct CFiTimesCAM
{
FILETIME CTime;
FILETIME ATime;
FILETIME MTime;
CFiTime CTime;
CFiTime ATime;
CFiTime MTime;
bool CTimeDefined;
bool ATimeDefined;
bool MTimeDefined;
bool CTime_Defined;
bool ATime_Defined;
bool MTime_Defined;
bool IsSomeTimeDefined() const
{
return
CTime_Defined |
ATime_Defined |
MTime_Defined;
}
};
struct CDirPathTime: public CFiTimesCAM
{
FString Path;
bool SetDirTime() const;
@@ -216,6 +230,25 @@ struct CLinkInfo
#endif // SUPPORT_LINKS
#ifndef _WIN32
struct COwnerInfo
{
bool Id_Defined;
UInt32 Id;
AString Name;
void Clear()
{
Id_Defined = false;
Id = 0;
Name.Empty();
}
};
#endif
class CArchiveExtractCallback:
public IArchiveExtractCallback,
public IArchiveExtractCallbackMessage,
@@ -256,32 +289,33 @@ class CArchiveExtractCallback:
bool _extractMode;
bool WriteCTime;
bool WriteATime;
bool WriteMTime;
bool Write_CTime;
bool Write_ATime;
bool Write_MTime;
bool _encrypted;
struct CProcessedFileInfo
{
FILETIME CTime;
FILETIME ATime;
FILETIME MTime;
CArcTime CTime;
CArcTime ATime;
CArcTime MTime;
UInt32 Attrib;
bool CTimeDefined;
bool ATimeDefined;
bool MTimeDefined;
bool AttribDefined;
bool Attrib_Defined;
#ifndef _WIN32
COwnerInfo Owner;
COwnerInfo Group;
#endif
bool IsReparse() const
{
return (AttribDefined && (Attrib & FILE_ATTRIBUTE_REPARSE_POINT) != 0);
return (Attrib_Defined && (Attrib & FILE_ATTRIBUTE_REPARSE_POINT) != 0);
}
bool IsLinuxSymLink() const
{
return (AttribDefined && MY_LIN_S_ISLNK(Attrib >> 16));
return (Attrib_Defined && MY_LIN_S_ISLNK(Attrib >> 16));
}
void SetFromPosixAttrib(UInt32 a)
@@ -294,10 +328,14 @@ class CArchiveExtractCallback:
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
AttribDefined = true;
Attrib_Defined = true;
}
} _fi;
@@ -359,7 +397,7 @@ class CArchiveExtractCallback:
#endif
void CreateComplexDirectory(const UStringVector &dirPathParts, FString &fullPath);
HRESULT GetTime(UInt32 index, PROPID propID, FILETIME &filetime, bool &filetimeIsDefined);
HRESULT GetTime(UInt32 index, PROPID propID, CArcTime &ft);
HRESULT GetUnpackSize();
FString Hash_GetFullFilePath();
@@ -372,6 +410,10 @@ public:
HRESULT SendMessageError2(HRESULT errorCode, const char *message, const FString &path1, const FString &path2);
public:
#if defined(_WIN32) && !defined(UNDER_CE)
NExtract::NZoneIdMode::EEnum ZoneMode;
CByteBuffer ZoneBuf;
#endif
CLocalProgress *LocalProgressSpec;
@@ -405,11 +447,17 @@ public:
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)
ZoneMode = zoneMode;
#else
UNUSED_VAR(zoneMode)
#endif
_keepAndReplaceEmptyDirPrefixes = keepAndReplaceEmptyDirPrefixes;
NumFolders = NumFiles = NumAltStreams = UnpackSize = AltStreams_UnpackSize = 0;
}
@@ -427,6 +475,8 @@ public:
#endif
void InitBeforeNewArchive();
void Init(
const CExtractNtOptions &ntOptions,
const NWildcard::CCensorNode *wildcardCensor,
@@ -483,6 +533,7 @@ private:
HRESULT Read_fi_Props();
void CorrectPathParts();
void GetFiTimesCAM(CFiTimesCAM &pt);
void CreateFolders();
bool _isRenamed;
@@ -533,4 +584,6 @@ struct CArchiveExtractCallback_Closer
bool CensorNode_CheckPath(const NWildcard::CCensorNode &node, const CReadArcItem &item);
void ReadZoneFile_Of_BaseFile(CFSTR fileName2, CByteBuffer &buf);
#endif

View File

@@ -34,7 +34,8 @@ STDMETHODIMP COpenCallbackImp::SetCompleted(const UInt64 *files, const UInt64 *b
return Callback->Open_SetCompleted(files, bytes);
COM_TRY_END
}
STDMETHODIMP COpenCallbackImp::GetProperty(PROPID propID, PROPVARIANT *value)
{
COM_TRY_BEGIN
@@ -51,10 +52,11 @@ STDMETHODIMP COpenCallbackImp::GetProperty(PROPID propID, PROPVARIANT *value)
case kpidName: prop = fs2us(_fileInfo.Name); break;
case kpidIsDir: prop = _fileInfo.IsDir(); break;
case kpidSize: prop = _fileInfo.Size; break;
case kpidAttrib: prop = (UInt32)_fileInfo.Attrib; break;
case kpidCTime: prop = _fileInfo.CTime; break;
case kpidATime: prop = _fileInfo.ATime; break;
case kpidMTime: prop = _fileInfo.MTime; break;
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;
}
prop.Detach(value);
return S_OK;

View File

@@ -334,7 +334,7 @@ static void ExtractGroupCommand(const UStringVector &arcPaths, UString &params,
ErrorMessageHRESULT(result);
}
void ExtractArchives(const UStringVector &arcPaths, const UString &outFolder, bool showDialog, bool elimDup)
void ExtractArchives(const UStringVector &arcPaths, const UString &outFolder, bool showDialog, bool elimDup, UInt32 writeZone)
{
MY_TRY_BEGIN
UString params ('x');
@@ -345,6 +345,11 @@ void ExtractArchives(const UStringVector &arcPaths, const UString &outFolder, bo
}
if (elimDup)
params += " -spe";
if (writeZone != (UInt32)(Int32)-1)
{
params += " -snz";
params.Add_UInt32(writeZone);
}
if (showDialog)
params += kShowDialogSwitch;
ExtractGroupCommand(arcPaths, params, false);

View File

@@ -15,7 +15,7 @@ HRESULT CompressFiles(
const UStringVector &names,
bool email, bool showDialog, bool waitFinish);
void ExtractArchives(const UStringVector &arcPaths, const UString &outFolder, bool showDialog, bool elimDup);
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,

View File

@@ -152,19 +152,12 @@ HRESULT CompressFiles(
static HRESULT ExtractGroupCommand(const UStringVector &arcPaths,
bool showDialog, const UString &outFolder, bool testMode, bool elimDup = false,
const char *kType = NULL)
bool showDialog, CExtractOptions &eo, const char *kType = NULL)
{
MY_TRY_BEGIN
CREATE_CODECS
CExtractOptions eo;
eo.OutputDir = us2fs(outFolder);
eo.TestMode = testMode;
eo.ElimDup.Val = elimDup;
eo.ElimDup.Def = elimDup;
CExtractCallbackImp *ecs = new CExtractCallbackImp;
CMyComPtr<IFolderArchiveExtractCallback> extractCallback = ecs;
@@ -228,15 +221,26 @@ static HRESULT ExtractGroupCommand(const UStringVector &arcPaths,
return result;
}
void ExtractArchives(const UStringVector &arcPaths, const UString &outFolder, bool showDialog, bool elimDup)
void ExtractArchives(const UStringVector &arcPaths, const UString &outFolder,
bool showDialog, bool elimDup, UInt32 writeZone)
{
ExtractGroupCommand(arcPaths, showDialog, outFolder, false, elimDup);
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)
{
ExtractGroupCommand(arcPaths, true, UString(), true,
false, // elimDup
CExtractOptions eo;
eo.TestMode = true;
ExtractGroupCommand(arcPaths,
true, // showDialog
eo,
hashMode ? "hash" : NULL);
}

View File

@@ -10,6 +10,8 @@
#include "../../../Common/MyString.h"
#include "../../../Windows/FileFind.h"
#include "../../../Windows/PropVariant.h"
#include "../../../Windows/TimeUtils.h"
#include "../../Common/UniqBlocks.h"
@@ -80,50 +82,213 @@ struct IDirItemsCallback
INTERFACE_IDirItemsCallback(=0)
};
struct CDirItem
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
{
UInt64 Size;
FILETIME CTime;
FILETIME ATime;
FILETIME MTime;
UString Name;
#ifndef UNDER_CE
#ifndef UNDER_CE
CByteBuffer ReparseData;
#ifdef _WIN32
#ifdef _WIN32
// UString ShortName;
CByteBuffer ReparseData2; // fixed (reduced) absolute links for WIM format
bool AreReparseData() const { return ReparseData.Size() != 0 || ReparseData2.Size() != 0; }
#else
#else
bool AreReparseData() const { return ReparseData.Size() != 0; }
#endif // _WIN32
#endif // _WIN32
#endif // !UNDER_CE
#endif // !UNDER_CE
UInt32 Attrib;
void Copy_From_FileInfoBase(const NWindows::NFile::NFind::CFileInfoBase &fi)
{
(NWindows::NFile::NFind::CFileInfoBase &)*this = fi;
}
int PhyParent;
int LogParent;
int SecureIndex;
bool IsAltStream;
CDirItem(): PhyParent(-1), LogParent(-1), SecureIndex(-1), IsAltStream(false) {}
bool IsDir() const { return (Attrib & FILE_ATTRIBUTE_DIRECTORY) != 0; }
bool IsReadOnly() const { return (Attrib & FILE_ATTRIBUTE_READONLY) != 0; }
bool Has_Attrib_ReparsePoint() const { return (Attrib & FILE_ATTRIBUTE_REPARSE_POINT) != 0; }
#ifdef _WIN32
#else
int OwnerNameIndex;
int OwnerGroupIndex;
#endif
#ifdef _WIN32
UInt32 GetPosixAttrib() const
CDirItem():
PhyParent(-1)
, LogParent(-1)
, SecureIndex(-1)
#ifdef _WIN32
#else
, OwnerNameIndex(-1)
, OwnerGroupIndex(-1)
#endif
{
UInt32 v = IsDir() ? MY_LIN_S_IFDIR : MY_LIN_S_IFREG;
/* 21.06: as WSL we allow write permissions (0222) for directories even for (FILE_ATTRIBUTE_READONLY).
So extracting at Linux will be allowed to write files inside (0777) directories. */
v |= ((IsReadOnly() && !IsDir()) ? 0555 : 0777);
return v;
}
#endif
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
{}
};
@@ -145,6 +310,7 @@ public:
bool ScanAltStreams;
bool ExcludeDirItems;
bool ExcludeFileItems;
bool ShareForWrite;
/* it must be called after anotrher checks */
bool CanIncludeItem(bool isDir) const
@@ -160,7 +326,7 @@ public:
const FString &phyPrefix);
#endif
#if defined(_WIN32) && !defined(UNDER_CE)
#if defined(_WIN32) && !defined(UNDER_CE)
CUniqBlocks SecureBlocks;
CByteBuffer TempSecureBuf;
@@ -170,7 +336,17 @@ public:
HRESULT AddSecurityItem(const FString &path, int &secureIndex);
HRESULT FillFixedReparse();
#endif
#endif
#ifndef _WIN32
C_UInt32_UString_Map OwnerNameMap;
C_UInt32_UString_Map OwnerGroupMap;
bool StoreOwnerName;
HRESULT FillDeviceSizes();
#endif
IDirItemsCallback *Callback;
@@ -204,20 +380,25 @@ public:
};
struct CArcItem
{
UInt64 Size;
FILETIME MTime;
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 SizeDefined;
bool MTimeDefined;
bool Size_Defined;
bool Censored;
UInt32 IndexInServer;
int TimeType;
CArcItem(): IsDir(false), IsAltStream(false), SizeDefined(false), MTimeDefined(false), Censored(false), TimeType(-1) {}
CArcItem():
IsDir(false),
IsAltStream(false),
Size_Defined(false),
Censored(false)
{}
};
#endif

View File

@@ -5,6 +5,12 @@
#include <wchar.h>
// #include <stdio.h>
#ifndef _WIN32
#include <grp.h>
#include <pwd.h>
#include "../../../Common/UTFConvert.h"
#endif
#include "../../../Common/Wildcard.h"
#include "../../../Windows/FileDir.h"
@@ -23,32 +29,60 @@ using namespace NWindows;
using namespace NFile;
using namespace NName;
static bool FindFile_KeepDots(NFile::NFind::CFileInfo &fi, const FString &path, bool followLink)
{
const bool res = fi.Find(path, followLink);
if (!res)
return res;
if (path.IsEmpty())
return res;
// we keep name "." and "..", if it's without tail slash
const FChar *p = path.RightPtr(1);
if (*p != '.')
return res;
if (p != path.Ptr())
{
FChar c = p[-1];
if (!IS_PATH_SEPAR(c))
{
if (c != '.')
return res;
p--;
if (p != path.Ptr())
{
c = p[-1];
if (!IS_PATH_SEPAR(c))
return res;
}
}
}
fi.Name = p;
return res;
}
void CDirItems::AddDirFileInfo(int phyParent, int logParent, int secureIndex,
const NFind::CFileInfo &fi)
{
CDirItem di;
di.Size = fi.Size;
di.CTime = fi.CTime;
di.ATime = fi.ATime;
di.MTime = fi.MTime;
di.Attrib = fi.Attrib;
di.IsAltStream = fi.IsAltStream;
/*
CDirItem di(fi);
di.PhyParent = phyParent;
di.LogParent = logParent;
di.SecureIndex = secureIndex;
di.Name = fs2us(fi.Name);
#if defined(_WIN32) && !defined(UNDER_CE)
// di.ShortName = fs2us(fi.ShortName);
#endif
Items.Add(di);
*/
VECTOR_ADD_NEW_OBJECT (Items, CDirItem(fi, phyParent, logParent, secureIndex))
if (fi.IsDir())
Stat.NumDirs++;
#ifdef _WIN32
else if (fi.IsAltStream)
{
Stat.NumAltStreams++;
Stat.AltStreamsSize += fi.Size;
}
#endif
else
{
Stat.NumFiles++;
@@ -148,9 +182,13 @@ CDirItems::CDirItems():
ScanAltStreams(false)
, ExcludeDirItems(false)
, ExcludeFileItems(false)
#ifdef _USE_SECURITY_CODE
, ShareForWrite(false)
#ifdef _USE_SECURITY_CODE
, ReadSecure(false)
#endif
#endif
#ifndef _WIN32
, StoreOwnerName(true)
#endif
, Callback(NULL)
{
#ifdef _USE_SECURITY_CODE
@@ -379,7 +417,7 @@ HRESULT CDirItems::EnumerateItems2(
const FString &filePath = filePaths[i];
NFind::CFileInfo fi;
const FString phyPath = phyPrefix + filePath;
if (!fi.Find(phyPath FOLLOW_LINK_PARAM))
if (!FindFile_KeepDots(fi, phyPath FOLLOW_LINK_PARAM))
{
RINOK(AddError(phyPath));
continue;
@@ -658,15 +696,14 @@ static HRESULT EnumerateForItem(
if (!enterToSubFolders)
return S_OK;
#ifndef _WIN32
#ifndef _WIN32
if (fi.IsPosixLink())
{
// here we can try to resolve posix link
// if the link to dir, then can we follow it
return S_OK; // we don't follow posix link
}
#endif
#else
if (dirItems.SymLinks && fi.HasReparsePoint())
{
/* 20.03: in SymLinks mode: we don't enter to directory that
@@ -677,6 +714,7 @@ static HRESULT EnumerateForItem(
*/
return S_OK;
}
#endif
nextNode = &curNode;
}
@@ -826,7 +864,7 @@ static HRESULT EnumerateDirItems(
}
else
#endif
if (!fi.Find(fullPath FOLLOW_LINK_PARAM2))
if (!FindFile_KeepDots(fi, fullPath FOLLOW_LINK_PARAM2))
{
RINOK(dirItems.AddError(fullPath));
continue;
@@ -914,15 +952,14 @@ static HRESULT EnumerateDirItems(
}
else
{
#ifndef _WIN32
#ifndef _WIN32
if (fi.IsPosixLink())
{
// here we can try to resolve posix link
// if the link to dir, then can we follow it
continue; // we don't follow posix link
}
#endif
#else
if (dirItems.SymLinks)
{
if (fi.HasReparsePoint())
@@ -932,6 +969,7 @@ static HRESULT EnumerateDirItems(
continue;
}
}
#endif
nextNode = &curNode;
newParts.Add(name); // don't change it to fi.Name. It's for shortnames support
}
@@ -973,7 +1011,7 @@ static HRESULT EnumerateDirItems(
}
else
{
if (!fi.Find(fullPath FOLLOW_LINK_PARAM2))
if (!FindFile_KeepDots(fi, fullPath FOLLOW_LINK_PARAM2))
{
if (!nextNode.AreThereIncludeItems())
continue;
@@ -1136,15 +1174,18 @@ HRESULT EnumerateItems(
}
dirItems.ReserveDown();
#if defined(_WIN32) && !defined(UNDER_CE)
#if defined(_WIN32) && !defined(UNDER_CE)
RINOK(dirItems.FillFixedReparse());
#endif
#endif
#ifndef _WIN32
RINOK(dirItems.FillDeviceSizes());
#endif
return S_OK;
}
#if defined(_WIN32) && !defined(UNDER_CE)
HRESULT CDirItems::FillFixedReparse()
@@ -1281,6 +1322,148 @@ HRESULT CDirItems::FillFixedReparse()
#endif
#ifndef _WIN32
HRESULT CDirItems::FillDeviceSizes()
{
{
FOR_VECTOR (i, Items)
{
CDirItem &item = Items[i];
if (S_ISBLK(item.mode) && item.Size == 0)
{
const FString phyPath = GetPhyPath(i);
NIO::CInFile inFile;
inFile.PreserveATime = true;
if (inFile.OpenShared(phyPath, ShareForWrite)) // fixme: OpenShared ??
{
UInt64 size = 0;
if (inFile.GetLength(size))
item.Size = size;
}
}
if (StoreOwnerName)
{
OwnerNameMap.Add_UInt32(item.uid);
OwnerGroupMap.Add_UInt32(item.gid);
}
}
}
if (StoreOwnerName)
{
UString u;
AString a;
{
FOR_VECTOR (i, OwnerNameMap.Numbers)
{
// 200K/sec speed
u.Empty();
const passwd *pw = getpwuid(OwnerNameMap.Numbers[i]);
if (pw)
{
a = pw->pw_name;
ConvertUTF8ToUnicode(a, u);
}
OwnerNameMap.Strings.Add(u);
}
}
{
FOR_VECTOR (i, OwnerGroupMap.Numbers)
{
u.Empty();
const group *gr = getgrgid(OwnerGroupMap.Numbers[i]);
if (gr)
{
// printf("\ngetgrgid %d %s\n", OwnerGroupMap.Numbers[i], gr->gr_name);
a = gr->gr_name;
ConvertUTF8ToUnicode(a, u);
}
OwnerGroupMap.Strings.Add(u);
}
}
FOR_VECTOR (i, Items)
{
CDirItem &item = Items[i];
{
const int index = OwnerNameMap.Find(item.uid);
if (index < 0) throw 1;
item.OwnerNameIndex = index;
}
{
const int index = OwnerGroupMap.Find(item.gid);
if (index < 0) throw 1;
item.OwnerGroupIndex = index;
}
}
}
// if (NeedOwnerNames)
{
/*
{
for (unsigned i = 0 ; i < 10000; i++)
{
const passwd *pw = getpwuid(i);
if (pw)
{
UString u;
ConvertUTF8ToUnicode(AString(pw->pw_name), u);
OwnerNameMap.Add(i, u);
OwnerNameMap.Add(i, u);
OwnerNameMap.Add(i, u);
}
const group *gr = getgrgid(i);
if (gr)
{
// we can use utf-8 here.
UString u;
ConvertUTF8ToUnicode(AString(gr->gr_name), u);
OwnerGroupMap.Add(i, u);
}
}
}
*/
/*
{
FOR_VECTOR (i, OwnerNameMap.Strings)
{
AString s;
ConvertUnicodeToUTF8(OwnerNameMap.Strings[i], s);
printf("\n%5d %s", (unsigned)OwnerNameMap.Numbers[i], s.Ptr());
}
}
{
printf("\n\n=========Groups\n");
FOR_VECTOR (i, OwnerGroupMap.Strings)
{
AString s;
ConvertUnicodeToUTF8(OwnerGroupMap.Strings[i], s);
printf("\n%5d %s", (unsigned)OwnerGroupMap.Numbers[i], s.Ptr());
}
}
*/
}
/*
for (unsigned i = 0 ; i < 100000000; i++)
{
// const passwd *pw = getpwuid(1000);
// pw = pw;
int pos = OwnerNameMap.Find(1000);
if (pos < 0 - (int)i)
throw 1;
}
*/
return S_OK;
}
#endif
static const char * const kCannotFindArchive = "Cannot find archive";
@@ -1351,11 +1534,18 @@ HRESULT EnumerateDirItemsAndSort(
#ifdef _WIN32
static bool IsDotsName(const wchar_t *s)
{
return s[0] == '.' && (s[1] == 0 || (s[1] == '.' && s[2] == 0));
}
// This code converts all short file names to long file names.
static void ConvertToLongName(const UString &prefix, UString &name)
{
if (name.IsEmpty() || DoesNameContainWildcard(name))
if (name.IsEmpty()
|| DoesNameContainWildcard(name)
|| IsDotsName(name))
return;
NFind::CFileInfo fi;
const FString path (us2fs(prefix + name));

View File

@@ -239,18 +239,18 @@ static HRESULT DecompressArchive(
Sorted list for file paths was sorted with case insensitive compare function.
But FindInSorted function did binary search via case sensitive compare function */
int Find_FileName_InSortedVector(const UStringVector &fileName, const UString &name);
int Find_FileName_InSortedVector(const UStringVector &fileName, const UString &name)
int Find_FileName_InSortedVector(const UStringVector &fileNames, const UString &name);
int Find_FileName_InSortedVector(const UStringVector &fileNames, const UString &name)
{
unsigned left = 0, right = fileName.Size();
unsigned left = 0, right = fileNames.Size();
while (left != right)
{
unsigned mid = (left + right) / 2;
const UString &midValue = fileName[mid];
int compare = CompareFileNames(name, midValue);
if (compare == 0)
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 (compare < 0)
if (comp < 0)
right = mid;
else
left = mid + 1;
@@ -314,8 +314,13 @@ HRESULT Extract(
CArchiveExtractCallback *ecs = new CArchiveExtractCallback;
CMyComPtr<IArchiveExtractCallback> ec(ecs);
bool multi = (numArcs > 1);
ecs->InitForMulti(multi, options.PathMode, options.OverwriteMode,
const bool multi = (numArcs > 1);
ecs->InitForMulti(multi,
options.PathMode,
options.OverwriteMode,
options.ZoneMode,
false // keepEmptyDirParts
);
#ifndef _SFX
@@ -335,12 +340,18 @@ HRESULT Extract(
if (skipArcs[i])
continue;
ecs->InitBeforeNewArchive();
const UString &arcPath = arcPaths[i];
NFind::CFileInfo fi;
if (options.StdInMode)
{
fi.Size = 0;
fi.Attrib = 0;
// do we need ctime and mtime?
fi.ClearBase();
fi.Size = 0; // (UInt64)(Int64)-1;
fi.SetAsFile();
// NTime::GetCurUtc_FiTime(fi.MTime);
// fi.CTime = fi.ATime = fi.MTime;
}
else
{
@@ -417,6 +428,15 @@ HRESULT Extract(
continue;
}
#if defined(_WIN32) && !defined(UNDER_CE) && !defined(_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))
@@ -490,11 +510,16 @@ HRESULT Extract(
*/
CArc &arc = arcLink.Arcs.Back();
arc.MTimeDefined = (!options.StdInMode && !fi.IsDevice);
arc.MTime = fi.MTime;
arc.MTime.Def = !options.StdInMode
#ifdef _WIN32
&& !fi.IsDevice
#endif
;
if (arc.MTime.Def)
arc.MTime.Set_From_FiTime(fi.MTime);
UInt64 packProcessed;
bool calcCrc =
const bool calcCrc =
#ifndef _SFX
(hash != NULL);
#else

View File

@@ -25,6 +25,7 @@ struct CExtractOptionsBase
bool OverwriteMode_Force;
NExtract::NPathMode::EEnum PathMode;
NExtract::NOverwriteMode::EEnum OverwriteMode;
NExtract::NZoneIdMode::EEnum ZoneMode;
FString OutputDir;
CExtractNtOptions NtOptions;
@@ -36,7 +37,8 @@ struct CExtractOptionsBase
PathMode_Force(false),
OverwriteMode_Force(false),
PathMode(NExtract::NPathMode::kFullPaths),
OverwriteMode(NExtract::NOverwriteMode::kAsk)
OverwriteMode(NExtract::NOverwriteMode::kAsk),
ZoneMode(NExtract::NZoneIdMode::kNone)
{}
};

View File

@@ -29,6 +29,16 @@ namespace NOverwriteMode
};
}
namespace NZoneIdMode
{
enum EEnum
{
kNone,
kAll,
kOffice
};
}
}
#endif

View File

@@ -34,10 +34,19 @@ static void ReplaceIncorrectChars(UString &s)
||
#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,
'_' // default
c
// (wchar_t)(0xf000 + c) // 21.02 debug: WSL encoding for unsupported characters
);
}
}
}

View File

@@ -15,6 +15,7 @@
#include "../../Common/StreamUtils.h"
#include "../../Archive/Common/ItemNameUtils.h"
#include "../../Archive/IArchive.h"
#ifdef WANT_OPTIONAL_LOWERCASE
#include "../FileManager/RegistryUtils.h"
@@ -313,8 +314,6 @@ static unsigned GetColumnWidth(unsigned digestSize)
}
void HashHexToString(char *dest, const Byte *data, UInt32 size);
static void AddHashResultLine(
AString &_s,
// bool showHash,
@@ -467,10 +466,7 @@ HRESULT HashCalc(
{
CDirItem di;
di.Size = (UInt64)(Int64)-1;
di.Attrib = 0;
di.MTime.dwLowDateTime = 0;
di.MTime.dwHighDateTime = 0;
di.CTime = di.ATime = di.MTime;
di.SetAsFile();
dirItems.Items.Add(di);
}
else
@@ -482,6 +478,8 @@ HRESULT HashCalc(
dirItems.ExcludeDirItems = censor.ExcludeDirItems;
dirItems.ExcludeFileItems = censor.ExcludeFileItems;
dirItems.ShareForWrite = options.OpenShareForWrite;
HRESULT res = EnumerateItems(censor,
options.PathMode,
UString(),
@@ -502,14 +500,16 @@ HRESULT HashCalc(
// hb.Init();
hb.NumErrors = dirItems.Stat.NumErrors;
UInt64 totalSize = 0;
if (options.StdInMode)
{
RINOK(callback->SetNumFiles(1));
}
else
{
RINOK(callback->SetTotal(dirItems.Stat.GetTotalBytes()));
totalSize = dirItems.Stat.GetTotalBytes();
RINOK(callback->SetTotal(totalSize));
}
const UInt32 kBufSize = 1 << 15;
@@ -541,7 +541,9 @@ HRESULT HashCalc(
{
path = dirItems.GetLogPath(i);
const CDirItem &di = dirItems.Items[i];
#ifdef _WIN32
isAltStream = di.IsAltStream;
#endif
#ifndef UNDER_CE
// if (di.AreReparseData())
@@ -555,7 +557,7 @@ HRESULT HashCalc(
#endif
{
CInFileStream *inStreamSpec = new CInFileStream;
inStreamSpec->File.PreserveATime = options.PreserveATime;
inStreamSpec->Set_PreserveATime(options.PreserveATime);
inStream = inStreamSpec;
isDir = di.IsDir();
if (!isDir)
@@ -569,6 +571,20 @@ HRESULT HashCalc(
return res;
continue;
}
if (!options.StdInMode)
{
UInt64 curSize = 0;
if (inStreamSpec->GetSize(&curSize) == S_OK)
{
if (curSize > di.Size)
{
totalSize += curSize - di.Size;
RINOK(callback->SetTotal(totalSize));
// printf("\ntotal = %d MiB\n", (unsigned)(totalSize >> 20));
}
}
}
// inStreamSpec->ReloadProps();
}
}
}
@@ -584,6 +600,7 @@ HRESULT HashCalc(
{
if ((step & 0xFF) == 0)
{
// printf("\ncompl = %d\n", (unsigned)(completeValue >> 20));
RINOK(callback->SetCompleted(&completeValue));
}
UInt32 size;
@@ -1689,8 +1706,11 @@ STDMETHODIMP CHandler::UpdateItems(ISequentialOutStream *outStream, UInt32 numIt
if (_isArc && !CanUpdate())
return E_NOTIMPL;
// const UINT codePage = CP_UTF8; // // (_forceCodePage ? _specifiedCodePage : _openCodePage);
// const unsigned utfFlags = g_Unicode_To_UTF8_Flags;
/*
CMyComPtr<IArchiveUpdateCallbackArcProp> reportArcProp;
callback->QueryInterface(IID_IArchiveUpdateCallbackArcProp, (void **)&reportArcProp);
*/
CObjectVector<CUpdateItem> updateItems;
UInt64 complexity = 0;
@@ -1837,6 +1857,8 @@ STDMETHODIMP CHandler::UpdateItems(ISequentialOutStream *outStream, UInt32 numIt
if (ui.NewData)
{
UInt64 currentComplexity = ui.Size;
UInt64 fileSize = 0;
CMyComPtr<ISequentialInStream> fileInStream;
bool needWrite = true;
{
@@ -1850,6 +1872,15 @@ STDMETHODIMP CHandler::UpdateItems(ISequentialOutStream *outStream, UInt32 numIt
if (fileInStream)
{
CMyComPtr<IStreamGetSize> streamGetSize;
fileInStream->QueryInterface(IID_IStreamGetSize, (void **)&streamGetSize);
if (streamGetSize)
{
UInt64 size;
if (streamGetSize->GetSize(&size) == S_OK)
currentComplexity = size;
}
/*
CMyComPtr<IStreamGetProps> getProps;
fileInStream->QueryInterface(IID_IStreamGetProps, (void **)&getProps);
if (getProps)
@@ -1862,6 +1893,7 @@ STDMETHODIMP CHandler::UpdateItems(ISequentialOutStream *outStream, UInt32 numIt
// item.MTime = NWindows::NTime::FileTimeToUnixTime64(mTime);;
}
}
*/
}
else
{
@@ -1875,7 +1907,6 @@ STDMETHODIMP CHandler::UpdateItems(ISequentialOutStream *outStream, UInt32 numIt
if (needWrite && fileInStream && !isDir)
{
UInt64 fileSize = 0;
for (UInt32 step = 0;; step++)
{
if ((step & 0xFF) == 0)
@@ -1911,6 +1942,36 @@ STDMETHODIMP CHandler::UpdateItems(ISequentialOutStream *outStream, UInt32 numIt
}
complexity += currentComplexity;
/*
if (reportArcProp)
{
PROPVARIANT prop;
prop.vt = VT_EMPTY;
prop.wReserved1 = 0;
NCOM::PropVarEm_Set_UInt64(&prop, fileSize);
RINOK(reportArcProp->ReportProp(NArchive::NEventIndexType::kOutArcIndex, ui.IndexInClient, kpidSize, &prop));
for (unsigned k = 0; k < hb.Hashers.Size(); k++)
{
const CHasherState &hs = hb.Hashers[k];
if (hs.DigestSize == 4 && hs.Name.IsEqualTo_Ascii_NoCase("crc32"))
{
NCOM::PropVarEm_Set_UInt32(&prop, GetUi32(hs.Digests[k_HashCalc_Index_Current]));
RINOK(reportArcProp->ReportProp(NArchive::NEventIndexType::kOutArcIndex, ui.IndexInClient, kpidCRC, &prop));
}
else
{
RINOK(reportArcProp->ReportRawProp(NArchive::NEventIndexType::kOutArcIndex, ui.IndexInClient,
kpidChecksum, hs.Digests[k_HashCalc_Index_Current],
hs.DigestSize, NPropDataType::kRaw));
}
RINOK(reportArcProp->ReportFinished(NArchive::NEventIndexType::kOutArcIndex, ui.IndexInClient, NArchive::NUpdate::NOperationResult::kOK));
}
}
*/
RINOK(callback->SetOperationResult(NArchive::NUpdate::NOperationResult::kOK));
}
else

View File

@@ -16,6 +16,12 @@ 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, UInt32 size);
enum
{
k_HashCalc_Index_Current,

View File

@@ -33,8 +33,6 @@ EXPORT_CODECS
#include "StdAfx.h"
#include "../../../../C/7zVersion.h"
#include "../../../Common/MyCom.h"
#include "../../../Common/StringToInt.h"
#include "../../../Common/StringConvert.h"
@@ -275,6 +273,9 @@ static HRESULT GetMethodBoolProp(Func_GetMethodProperty getMethodProperty, UInt3
#define MY_GET_FUNC(dest, type, func) *(void **)(&dest) = (func);
// #define MY_GET_FUNC(dest, type, func) dest = (type)(func);
#define MY_GET_FUNC_LOC(dest, type, func) \
type dest; MY_GET_FUNC(dest, type, func)
HRESULT CCodecs::LoadCodecs()
{
CCodecLib &lib = Libs.Back();
@@ -286,8 +287,7 @@ HRESULT CCodecs::LoadCodecs()
if (lib.GetMethodProperty)
{
UInt32 numMethods = 1;
Func_GetNumberOfMethods getNumberOfMethods;
MY_GET_FUNC (getNumberOfMethods, Func_GetNumberOfMethods, lib.Lib.GetProc("GetNumberOfMethods"));
MY_GET_FUNC_LOC (getNumberOfMethods, Func_GetNumberOfMethods, lib.Lib.GetProc("GetNumberOfMethods"));
if (getNumberOfMethods)
{
RINOK(getNumberOfMethods(&numMethods));
@@ -304,8 +304,7 @@ HRESULT CCodecs::LoadCodecs()
}
}
Func_GetHashers getHashers;
MY_GET_FUNC (getHashers, Func_GetHashers, lib.Lib.GetProc("GetHashers"));
MY_GET_FUNC_LOC (getHashers, Func_GetHashers, lib.Lib.GetProc("GetHashers"));
if (getHashers)
{
RINOK(getHashers(&lib.ComHashers));
@@ -414,17 +413,14 @@ HRESULT CCodecs::LoadFormats()
const NDLL::CLibrary &lib = Libs.Back().Lib;
Func_GetHandlerProperty getProp = NULL;
Func_GetHandlerProperty2 getProp2;
MY_GET_FUNC (getProp2, Func_GetHandlerProperty2, lib.GetProc("GetHandlerProperty2"));
Func_GetIsArc getIsArc;
MY_GET_FUNC (getIsArc, Func_GetIsArc, lib.GetProc("GetIsArc"));
MY_GET_FUNC_LOC (getProp2, Func_GetHandlerProperty2, lib.GetProc("GetHandlerProperty2"));
MY_GET_FUNC_LOC (getIsArc, Func_GetIsArc, lib.GetProc("GetIsArc"));
UInt32 numFormats = 1;
if (getProp2)
{
Func_GetNumberOfFormats getNumberOfFormats;
MY_GET_FUNC (getNumberOfFormats, Func_GetNumberOfFormats, lib.GetProc("GetNumberOfFormats"));
MY_GET_FUNC_LOC (getNumberOfFormats, Func_GetNumberOfFormats, lib.GetProc("GetNumberOfFormats"));
if (getNumberOfFormats)
{
RINOK(getNumberOfFormats(&numFormats));
@@ -477,6 +473,11 @@ HRESULT CCodecs::LoadFormats()
item.Flags |= kArcFlagsPars[j + 1];
}
}
{
bool defined = false;
RINOK(GetProp_UInt32(getProp, getProp2, i, NArchive::NHandlerPropID::kTimeFlags, item.TimeFlags, defined));
}
CByteBuffer sig;
RINOK(GetProp_RawData(getProp, getProp2, i, NArchive::NHandlerPropID::kSignature, sig));
@@ -567,8 +568,7 @@ HRESULT CCodecs::LoadDll(const FString &dllPath, bool needCheckDll, bool *loaded
/*
{
Func_LibStartup _LibStartup;
MY_GET_FUNC (_LibStartup, Func_LibStartup, lib.Lib.GetProc("LibStartup"));
MY_GET_FUNC_LOC (_LibStartup, Func_LibStartup, lib.Lib.GetProc("LibStartup"));
if (_LibStartup)
{
HRESULT res = _LibStartup();
@@ -585,21 +585,31 @@ HRESULT CCodecs::LoadDll(const FString &dllPath, bool needCheckDll, bool *loaded
#ifdef _7ZIP_LARGE_PAGES
if (g_LargePageSize != 0)
{
Func_SetLargePageMode setLargePageMode;
MY_GET_FUNC (setLargePageMode, Func_SetLargePageMode, lib.Lib.GetProc("SetLargePageMode"));
MY_GET_FUNC_LOC (setLargePageMode, Func_SetLargePageMode, lib.Lib.GetProc("SetLargePageMode"));
if (setLargePageMode)
setLargePageMode();
}
#endif
if (CaseSensitiveChange)
if (CaseSensitive_Change)
{
Func_SetCaseSensitive setCaseSensitive;
MY_GET_FUNC (setCaseSensitive, Func_SetCaseSensitive, lib.Lib.GetProc("SetCaseSensitive"));
MY_GET_FUNC_LOC (setCaseSensitive, Func_SetCaseSensitive, lib.Lib.GetProc("SetCaseSensitive"));
if (setCaseSensitive)
setCaseSensitive(CaseSensitive ? 1 : 0);
}
/*
{
MY_GET_FUNC_LOC (setClientVersion, Func_SetClientVersion, lib.Lib.GetProc("SetClientVersion"));
if (setClientVersion)
{
// const UInt32 kVersion = (MY_VER_MAJOR << 16) | MY_VER_MINOR;
setClientVersion(g_ClientVersion);
}
}
*/
MY_GET_FUNC (lib.CreateObject, Func_CreateObject, lib.Lib.GetProc("CreateObject"));
{
unsigned startSize = Codecs.Size() + Hashers.Size();

View File

@@ -96,6 +96,7 @@ struct CArcExtInfo
struct CArcInfoEx
{
UInt32 Flags;
UInt32 TimeFlags;
Func_CreateInArchive CreateInArchive;
Func_IsArc IsArcFunc;
@@ -142,7 +143,7 @@ struct CArcInfoEx
bool Flags_FindSignature() const { return (Flags & NArcInfoFlags::kFindSignature) != 0; }
bool Flags_AltStreams() const { return (Flags & NArcInfoFlags::kAltStreams) != 0; }
bool Flags_NtSecure() const { return (Flags & NArcInfoFlags::kNtSecure) != 0; }
bool Flags_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; }
@@ -154,6 +155,27 @@ struct CArcInfoEx
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())
@@ -162,6 +184,15 @@ struct CArcInfoEx
}
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"); }
/*
UString GetAllExtensions() const
{
@@ -178,11 +209,10 @@ struct CArcInfoEx
void AddExts(const UString &ext, const UString &addExt);
bool IsSplit() const { return StringsAreEqualNoCase_Ascii(Name, "Split"); }
// bool IsRar() const { return StringsAreEqualNoCase_Ascii(Name, "Rar"); }
CArcInfoEx():
Flags(0),
TimeFlags(0),
CreateInArchive(NULL),
IsArcFunc(NULL)
#ifndef _SFX
@@ -333,14 +363,14 @@ public:
CRecordVector<CDllHasherInfo> Hashers;
#endif
bool CaseSensitiveChange;
bool CaseSensitive_Change;
bool CaseSensitive;
CCodecs():
#ifdef EXTERNAL_CODECS
NeedSetLibCodecs(true),
#endif
CaseSensitiveChange(false),
CaseSensitive_Change(false),
CaseSensitive(false)
{}

View File

@@ -209,8 +209,8 @@ int CHandler::FindInsertPos(const CParseItem &item) const
unsigned left = 0, right = _items.Size();
while (left != right)
{
unsigned mid = (left + right) / 2;
const CParseItem & midItem = _items[mid];
const unsigned mid = (unsigned)(((size_t)left + (size_t)right) / 2);
const CParseItem &midItem = _items[mid];
if (item.Offset < midItem.Offset)
right = mid;
else if (item.Offset > midItem.Offset)
@@ -262,8 +262,8 @@ void CHandler::AddUnknownItem(UInt64 next)
void CHandler::AddItem(const CParseItem &item)
{
AddUnknownItem(item.Offset);
int pos = FindInsertPos(item);
if (pos >= 0)
const int pos = FindInsertPos(item);
if (pos != -1)
{
_items.Insert((unsigned)pos, item);
UInt64 next = item.Offset + item.Size;
@@ -482,7 +482,7 @@ HRESULT Archive_IsItem_Deleted(IInArchive *arc, UInt32 index, bool &result) thro
return Archive_GetItemBoolProp(arc, index, kpidIsDeleted, result);
}
static HRESULT Archive_GetArcBoolProp(IInArchive *arc, PROPID propid, bool &result) throw()
static HRESULT Archive_GetArcProp_Bool(IInArchive *arc, PROPID propid, bool &result) throw()
{
NCOM::CPropVariant prop;
result = false;
@@ -532,7 +532,7 @@ static HRESULT Archive_GetArcProp_Int(IInArchive *arc, PROPID propid, Int64 &res
#ifndef _SFX
HRESULT CArc::GetItemPathToParent(UInt32 index, UInt32 parent, UStringVector &parts) const
HRESULT CArc::GetItem_PathToParent(UInt32 index, UInt32 parent, UStringVector &parts) const
{
if (!GetRawProps)
return E_FAIL;
@@ -616,7 +616,7 @@ HRESULT CArc::GetItemPathToParent(UInt32 index, UInt32 parent, UStringVector &pa
HRESULT CArc::GetItemPath(UInt32 index, UString &result) const
HRESULT CArc::GetItem_Path(UInt32 index, UString &result) const
{
#ifdef MY_CPU_LE
if (GetRawProps)
@@ -752,13 +752,13 @@ HRESULT CArc::GetItemPath(UInt32 index, UString &result) const
}
if (result.IsEmpty())
return GetDefaultItemPath(index, result);
return GetItem_DefaultPath(index, result);
Convert_UnicodeEsc16_To_UnicodeEscHigh(result);
return S_OK;
}
HRESULT CArc::GetDefaultItemPath(UInt32 index, UString &result) const
HRESULT CArc::GetItem_DefaultPath(UInt32 index, UString &result) const
{
result.Empty();
bool isDir;
@@ -779,9 +779,9 @@ HRESULT CArc::GetDefaultItemPath(UInt32 index, UString &result) const
return S_OK;
}
HRESULT CArc::GetItemPath2(UInt32 index, UString &result) const
HRESULT CArc::GetItem_Path2(UInt32 index, UString &result) const
{
RINOK(GetItemPath(index, result));
RINOK(GetItem_Path(index, result));
if (Ask_Deleted)
{
bool isDeleted = false;
@@ -833,7 +833,7 @@ HRESULT CArc::GetItem(UInt32 index, CReadArcItem &item) const
RINOK(Archive_IsItem_Dir(Archive, index, item.IsDir));
item.MainIsDir = item.IsDir;
RINOK(GetItemPath2(index, item.Path));
RINOK(GetItem_Path2(index, item.Path));
#ifndef _SFX
UInt32 mainIndex = index;
@@ -885,7 +885,7 @@ HRESULT CArc::GetItem(UInt32 index, CReadArcItem &item) const
}
else
{
RINOK(GetItemPath2(parentIndex, item.MainPath));
RINOK(GetItem_Path2(parentIndex, item.MainPath));
RINOK(Archive_IsItem_Dir(Archive, parentIndex, item.MainIsDir));
}
}
@@ -911,7 +911,7 @@ HRESULT CArc::GetItem(UInt32 index, CReadArcItem &item) const
#ifndef _SFX
if (item._use_baseParentFolder_mode)
{
RINOK(GetItemPathToParent(mainIndex, (unsigned)item._baseParentFolder, item.PathParts));
RINOK(GetItem_PathToParent(mainIndex, (unsigned)item._baseParentFolder, item.PathParts));
#ifdef SUPPORT_ALT_STREAMS
if ((item.WriteToAltStreamIfColon || needFindAltStream) && !item.PathParts.IsEmpty())
@@ -970,7 +970,7 @@ static HRESULT Archive_GetItem_Size(IInArchive *archive, UInt32 index, UInt64 &s
#endif
HRESULT CArc::GetItemSize(UInt32 index, UInt64 &size, bool &defined) const
HRESULT CArc::GetItem_Size(UInt32 index, UInt64 &size, bool &defined) const
{
NCOM::CPropVariant prop;
defined = false;
@@ -989,24 +989,52 @@ HRESULT CArc::GetItemSize(UInt32 index, UInt64 &size, bool &defined) const
return S_OK;
}
HRESULT CArc::GetItemMTime(UInt32 index, FILETIME &ft, bool &defined) const
HRESULT CArc::GetItem_MTime(UInt32 index, CArcTime &at) const
{
at.Clear();
NCOM::CPropVariant prop;
defined = false;
ft.dwHighDateTime = ft.dwLowDateTime = 0;
RINOK(Archive->GetProperty(index, kpidMTime, &prop));
if (prop.vt == VT_FILETIME)
{
ft = prop.filetime;
defined = true;
/*
// for debug
if (FILETIME_IsZero(prop.at) && MTime.Def)
{
at = MTime;
return S_OK;
}
*/
at.Set_From_Prop(prop);
if (at.Prec == 0)
{
// (at.Prec == 0) before version 22.
// so kpidTimeType is required for that code
prop.Clear();
RINOK(Archive->GetProperty(index, kpidTimeType, &prop));
if (prop.vt == VT_UI4)
{
UInt32 val = prop.ulVal;
if (val == NFileTimeType::kWindows)
val = k_PropVar_TimePrec_100ns;
/*
else if (val > k_PropVar_TimePrec_1ns)
{
val = k_PropVar_TimePrec_100ns;
// val = k_PropVar_TimePrec_1ns;
// return E_FAIL; // for debug
}
*/
at.Prec = (UInt16)val;
}
}
return S_OK;
}
else if (prop.vt != VT_EMPTY)
if (prop.vt != VT_EMPTY)
return E_FAIL;
else if (MTimeDefined)
{
ft = MTime;
defined = true;
}
if (MTime.Def)
at = MTime;
return S_OK;
}
@@ -1020,6 +1048,7 @@ static inline bool TestSignature(const Byte *p1, const Byte *p2, size_t size)
return true;
}
static void MakeCheckOrder(CCodecs *codecs,
CIntVector &orderIndices, unsigned numTypes, CIntVector &orderIndices2,
const Byte *data, size_t dataSize)
@@ -1034,7 +1063,7 @@ static void MakeCheckOrder(CCodecs *codecs,
{
if (ai.Signatures.IsEmpty())
{
if (dataSize != 0) // 21.04: no Sinature means Empty Signature
if (dataSize != 0) // 21.04: no Signature means Empty Signature
continue;
}
else
@@ -1230,7 +1259,7 @@ void CArcErrorInfo::ClearErrors()
HRESULT CArc::ReadBasicProps(IInArchive *archive, UInt64 startPos, HRESULT openRes)
{
// OkPhySize_Defined = false;
PhySizeDefined = false;
PhySize_Defined = false;
PhySize = 0;
Offset = 0;
AvailPhySize = FileSize - startPos;
@@ -1263,12 +1292,12 @@ HRESULT CArc::ReadBasicProps(IInArchive *archive, UInt64 startPos, HRESULT openR
if (openRes == S_OK || ErrorInfo.IsArc_After_NonOpen())
{
RINOK(Archive_GetArcProp_UInt(archive, kpidPhySize, PhySize, PhySizeDefined));
RINOK(Archive_GetArcProp_UInt(archive, kpidPhySize, PhySize, PhySize_Defined));
/*
RINOK(Archive_GetArcProp_UInt(archive, kpidOkPhySize, OkPhySize, OkPhySize_Defined));
if (!OkPhySize_Defined)
{
OkPhySize_Defined = PhySizeDefined;
OkPhySize_Defined = PhySize_Defined;
OkPhySize = PhySize;
}
*/
@@ -1278,7 +1307,7 @@ HRESULT CArc::ReadBasicProps(IInArchive *archive, UInt64 startPos, HRESULT openR
Int64 globalOffset = (Int64)startPos + Offset;
AvailPhySize = (UInt64)((Int64)FileSize - globalOffset);
if (PhySizeDefined)
if (PhySize_Defined)
{
UInt64 endPos = (UInt64)(globalOffset + (Int64)PhySize);
if (endPos < FileSize)
@@ -1379,9 +1408,9 @@ static HRESULT ReadParseItemProps(IInArchive *archive, const CArcInfoEx &ai, NAr
pi.FileTime_Defined = false;
pi.ArcType = ai.Name;
RINOK(Archive_GetArcBoolProp(archive, kpidIsNotArcType, pi.IsNotArcType));
RINOK(Archive_GetArcProp_Bool(archive, kpidIsNotArcType, pi.IsNotArcType));
// RINOK(Archive_GetArcBoolProp(archive, kpidIsSelfExe, pi.IsSelfExe));
// RINOK(Archive_GetArcProp_Bool(archive, kpidIsSelfExe, pi.IsSelfExe));
pi.IsSelfExe = ai.Flags_PreArc();
{
@@ -1585,7 +1614,7 @@ static HRESULT OpenArchiveSpec(IInArchive *archive, bool needPhySize,
return S_OK;
bool phySizeCantBeDetected = false;
RINOK(Archive_GetArcBoolProp(archive, kpidPhySizeCantBeDetected, phySizeCantBeDetected));
RINOK(Archive_GetArcProp_Bool(archive, kpidPhySizeCantBeDetected, phySizeCantBeDetected));
if (!phySizeCantBeDetected)
{
@@ -1725,7 +1754,7 @@ HRESULT CArc::OpenStream2(const COpenOptions &op)
const CArcInfoEx &ai = op.codecs->Formats[i];
if (IgnoreSplit || !op.openType.CanReturnArc)
if (ai.IsSplit())
if (ai.Is_Split())
continue;
if (op.excludedFormats->FindInSorted((int)i) >= 0)
continue;
@@ -1737,8 +1766,8 @@ HRESULT CArc::OpenStream2(const COpenOptions &op)
if (ai.FindExtension(extension) >= 0
#ifndef _SFX
|| (isZip && StringsAreEqualNoCase_Ascii(ai.Name, "zip"))
|| (isRar && StringsAreEqualNoCase_Ascii(ai.Name, "rar"))
|| (isZip && ai.Is_Zip())
|| (isRar && ai.Is_Rar())
#endif
)
{
@@ -1812,11 +1841,27 @@ HRESULT CArc::OpenStream2(const COpenOptions &op)
/*
check type order:
1) matched extension, no signuature
2) matched extension, matched signuature
0) matched_extension && Backward
1) matched_extension && (no_signuature || SignatureOffset != 0)
2) matched_extension && (matched_signature)
// 3) no signuature
// 4) matched signuature
*/
// we move index from orderIndices to orderIndices2 for priority handlers.
for (unsigned i = 0; i < numFinded; i++)
{
const int index = orderIndices[i];
if (index < 0)
continue;
const CArcInfoEx &ai = op.codecs->Formats[(unsigned)index];
if (ai.Flags_BackwardOpen())
{
// backward doesn't need start signatures
orderIndices2.Add(index);
orderIndices[i] = -1;
}
}
MakeCheckOrder(op.codecs, orderIndices, numFinded, orderIndices2, NULL, 0);
MakeCheckOrder(op.codecs, orderIndices, numFinded, orderIndices2, byteBuffer, processedSize);
@@ -1907,6 +1952,7 @@ HRESULT CArc::OpenStream2(const COpenOptions &op)
// OutputDebugStringW(ai.Name);
if (i >= numMainTypes)
{
// here we allow mismatched extension only for backward handlers
if (!ai.Flags_BackwardOpen()
// && !ai.Flags_PureStartOpen()
)
@@ -2126,7 +2172,7 @@ HRESULT CArc::OpenStream2(const COpenOptions &op)
const CArcInfoEx &ai = op.codecs->Formats[form];
if (ai.IsSplit())
if (ai.Is_Split())
{
splitIndex = (int)form;
continue;
@@ -2235,7 +2281,7 @@ HRESULT CArc::OpenStream2(const COpenOptions &op)
// bool needScan = false;
if (!PhySizeDefined)
if (!PhySize_Defined)
{
// it's for Z format
pi.LenIsUnknown = true;
@@ -2727,14 +2773,14 @@ HRESULT CArc::OpenStream2(const COpenOptions &op)
}
continue;
}
if (!ErrorInfo.IsArc_After_NonOpen() || !PhySizeDefined || PhySize == 0)
if (!ErrorInfo.IsArc_After_NonOpen() || !PhySize_Defined || PhySize == 0)
continue;
}
else
{
if (PhySizeDefined && PhySize == 0)
if (PhySize_Defined && PhySize == 0)
{
PRF(printf(" phySizeDefined && PhySize == 0 "));
PRF(printf(" phySize_Defined && PhySize == 0 "));
// we skip that epmty archive case with unusual unexpected (PhySize == 0) from Code function.
continue;
}
@@ -2755,10 +2801,10 @@ HRESULT CArc::OpenStream2(const COpenOptions &op)
else if (Offset != 0)
return E_FAIL;
UInt64 arcRem = FileSize - pi.Offset;
const UInt64 arcRem = FileSize - pi.Offset;
UInt64 phySize = arcRem;
bool phySizeDefined = PhySizeDefined;
if (phySizeDefined)
const bool phySize_Defined = PhySize_Defined;
if (phySize_Defined)
{
if (pi.Offset + PhySize > FileSize)
{
@@ -2784,7 +2830,7 @@ HRESULT CArc::OpenStream2(const COpenOptions &op)
bool needScan = false;
if (isOpen && !phySizeDefined)
if (isOpen && !phySize_Defined)
{
// it's for Z format, or bzip2,gz,xz with phySize that was not detected
pi.LenIsUnknown = true;
@@ -2803,7 +2849,7 @@ HRESULT CArc::OpenStream2(const COpenOptions &op)
/*
if (needSkipFullArc)
if (pi.Offset == 0 && phySizeDefined && pi.Size >= fileSize)
if (pi.Offset == 0 && phySize_Defined && pi.Size >= fileSize)
continue;
*/
if (pi.Offset == 0 && !pi.LenIsUnknown && pi.Size >= FileSize)
@@ -2831,7 +2877,7 @@ HRESULT CArc::OpenStream2(const COpenOptions &op)
RINOK(ReadParseItemProps(archive, ai, pi));
if (pi.Offset < startArcPos && !mode.EachPos /* && phySizeDefined */)
if (pi.Offset < startArcPos && !mode.EachPos /* && phySize_Defined */)
{
/* It's for DMG format.
This code deletes all previous items that are included to current item */
@@ -2850,7 +2896,7 @@ HRESULT CArc::OpenStream2(const COpenOptions &op)
}
if (isOpen && mode.CanReturnArc && phySizeDefined)
if (isOpen && mode.CanReturnArc && phySize_Defined)
{
// if (pi.Offset + pi.Size >= fileSize)
bool openCur = false;
@@ -2994,12 +3040,12 @@ HRESULT CArc::OpenStream(const COpenOptions &op)
Archive->QueryInterface(IID_IArchiveGetRawProps, (void **)&GetRawProps);
Archive->QueryInterface(IID_IArchiveGetRootProps, (void **)&GetRootProps);
RINOK(Archive_GetArcBoolProp(Archive, kpidIsTree, IsTree));
RINOK(Archive_GetArcBoolProp(Archive, kpidIsDeleted, Ask_Deleted));
RINOK(Archive_GetArcBoolProp(Archive, kpidIsAltStream, Ask_AltStream));
RINOK(Archive_GetArcBoolProp(Archive, kpidIsAux, Ask_Aux));
RINOK(Archive_GetArcBoolProp(Archive, kpidINode, Ask_INode));
RINOK(Archive_GetArcBoolProp(Archive, kpidReadOnly, IsReadOnly));
RINOK(Archive_GetArcProp_Bool(Archive, kpidIsTree, IsTree));
RINOK(Archive_GetArcProp_Bool(Archive, kpidIsDeleted, Ask_Deleted));
RINOK(Archive_GetArcProp_Bool(Archive, kpidIsAltStream, Ask_AltStream));
RINOK(Archive_GetArcProp_Bool(Archive, kpidIsAux, Ask_Aux));
RINOK(Archive_GetArcProp_Bool(Archive, kpidINode, Ask_INode));
RINOK(Archive_GetArcProp_Bool(Archive, kpidReadOnly, IsReadOnly));
const UString fileName = ExtractFileNameFromPath(Path);
UString extension;
@@ -3093,7 +3139,7 @@ HRESULT CArc::OpenStreamOrFile(COpenOptions &op)
FOR_VECTOR (i, op.codecs->Formats)
{
const CArcInfoEx &ai = op.codecs->Formats[i];
if (ai.IsSplit())
if (ai.Is_Split())
continue;
UString path3 = path2;
path3 += '.';
@@ -3300,7 +3346,7 @@ HRESULT CArchiveLink::Open(COpenOptions &op)
break;
CArc arc2;
RINOK(arc.GetItemPath(mainSubfile, arc2.Path));
RINOK(arc.GetItem_Path(mainSubfile, arc2.Path));
bool zerosTailIsAllowed;
RINOK(Archive_GetItemBoolProp(arc.Archive, mainSubfile, kpidZerosTailIsAllowed, zerosTailIsAllowed));
@@ -3344,7 +3390,7 @@ HRESULT CArchiveLink::Open(COpenOptions &op)
break;
}
RINOK(result);
RINOK(arc.GetItemMTime(mainSubfile, arc2.MTime, arc2.MTimeDefined));
RINOK(arc.GetItem_MTime(mainSubfile, arc2.MTime));
Arcs.Add(arc2);
}
IsOpen = !Arcs.IsEmpty();

View File

@@ -8,6 +8,7 @@
#include "ArchiveOpenCallback.h"
#include "LoadCodecs.h"
#include "Property.h"
#include "DirItem.h"
#ifndef _SFX
@@ -260,6 +261,9 @@ struct CReadArcItem
}
};
class CArc
{
HRESULT PrepareToOpen(const COpenOptions &op, unsigned formatIndex, CMyComPtr<IInArchive> &archive);
@@ -268,7 +272,7 @@ class CArc
#ifndef _SFX
// parts.Back() can contain alt stream name "nams:AltName"
HRESULT GetItemPathToParent(UInt32 index, UInt32 parent, UStringVector &parts) const;
HRESULT GetItem_PathToParent(UInt32 index, UInt32 parent, UStringVector &parts) const;
#endif
public:
@@ -289,19 +293,21 @@ public:
UString DefaultName;
int FormatIndex; // -1 means Parser
UInt32 SubfileIndex; // (UInt32)(Int32)-1; means no subfile
FILETIME MTime;
bool MTimeDefined;
// 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 PhySizeDefined;
bool PhySize_Defined;
// bool OkPhySize_Defined;
UInt64 FileSize;
UInt64 AvailPhySize; // PhySize, but it's reduced if exceed end of file
// bool offsetDefined;
UInt64 GetEstmatedPhySize() const { return PhySizeDefined ? PhySize : FileSize; }
UInt64 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
@@ -323,7 +329,7 @@ public:
// void Set_ErrorFlagsText();
CArc():
MTimeDefined(false),
// MTime_Defined(false),
IsTree(false),
IsReadOnly(false),
Ask_Deleted(false),
@@ -343,17 +349,29 @@ public:
return Archive->Close();
}
HRESULT GetItemPath(UInt32 index, UString &result) const;
HRESULT GetDefaultItemPath(UInt32 index, UString &result) const;
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 GetItemPath2(UInt32 index, UString &result) const;
HRESULT GetItem_Path2(UInt32 index, UString &result) const;
HRESULT GetItem(UInt32 index, CReadArcItem &item) const;
HRESULT GetItemSize(UInt32 index, UInt64 &size, bool &defined) const;
HRESULT GetItemMTime(UInt32 index, FILETIME &ft, bool &defined) const;
HRESULT IsItemAnti(UInt32 index, bool &result) const
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); }

View File

@@ -136,10 +136,37 @@ void ConvertPropertyToShortString2(char *dest, const PROPVARIANT &prop, PROPID p
if (prop.vt == VT_FILETIME)
{
const FILETIME &ft = prop.filetime;
if ((ft.dwHighDateTime == 0 &&
ft.dwLowDateTime == 0))
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;
ConvertUtcFileTimeToString(prop.filetime, dest, level);
if (level > numDigits)
level = numDigits;
ConvertUtcFileTimeToString2(ft, ns100, dest, level);
return;
}
@@ -198,6 +225,24 @@ void ConvertPropertyToShortString2(char *dest, const PROPVARIANT &prop, PROPID p
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;
}
*/
}
ConvertPropVariantToShortString(prop, dest);

View File

@@ -2,6 +2,8 @@
#include "StdAfx.h"
// #include <stdio.h>
#include "Update.h"
#include "../../../Common/StringConvert.h"
@@ -101,7 +103,7 @@ public:
_length = 0;
}
bool SetMTime(const FILETIME *mTime);
bool SetMTime(const CFiTime *mTime);
HRESULT Close();
UInt64 GetSize() const { return _length; }
@@ -131,7 +133,7 @@ HRESULT COutMultiVolStream::Close()
return res;
}
bool COutMultiVolStream::SetMTime(const FILETIME *mTime)
bool COutMultiVolStream::SetMTime(const CFiTime *mTime)
{
bool res = true;
FOR_VECTOR (i, Streams)
@@ -545,11 +547,46 @@ static HRESULT Compress(
if (!outArchive)
throw kUpdateIsNotSupoorted;
// we need to set properties to get fileTimeType.
RINOK(SetProperties(outArchive, options.MethodMode.Properties));
NFileTimeType::EEnum fileTimeType;
{
/*
how we compare file_in_archive::MTime with dirItem.MTime
for GetUpdatePairInfoList():
if (kpidMTime is not defined), external MTime of archive is used.
before 22.00:
if (kpidTimeType is defined)
{
kpidTimeType is used as precision.
(kpidTimeType > kDOS) is not allowed.
}
else GetFileTimeType() value is used as precision.
22.00:
if (kpidMTime is defined)
{
if (kpidMTime::precision != 0), then kpidMTime::precision is used as precision.
else
{
if (kpidTimeType is defined), kpidTimeType is used as precision.
else GetFileTimeType() value is used as precision.
}
}
else external MTime of archive is used as precision.
*/
UInt32 value;
RINOK(outArchive->GetFileTimeType(&value));
// we support any future fileType here.
fileTimeType = (NFileTimeType::EEnum)value;
/*
old 21.07 code:
switch (value)
{
case NFileTimeType::kWindows:
@@ -560,13 +597,26 @@ static HRESULT Compress(
default:
return E_FAIL;
}
*/
}
// bool noTimestampExpected = false;
{
const CArcInfoEx &arcInfo = codecs->Formats[(unsigned)formatIndex];
// if (arcInfo.Flags_KeepName()) noTimestampExpected = true;
if (arcInfo.Is_Xz() ||
arcInfo.Is_BZip2())
{
/* 7-zip before 22.00 returns NFileTimeType::kUnix for xz and bzip2,
but we want to set timestamp without reduction to unix. */
// noTimestampExpected = true;
fileTimeType = NFileTimeType::kNotDefined; // it means not defined
}
if (options.AltStreams.Val && !arcInfo.Flags_AltStreams())
return E_NOTIMPL;
if (options.NtSecurity.Val && !arcInfo.Flags_NtSecure())
if (options.NtSecurity.Val && !arcInfo.Flags_NtSecurity())
return E_NOTIMPL;
if (options.DeleteAfterCompressing && arcInfo.Flags_HashHandler())
return E_NOTIMPL;
@@ -626,7 +676,7 @@ static HRESULT Compress(
if (needRename)
{
up2.NewProps = true;
RINOK(arc->IsItemAnti(i, up2.IsAnti));
RINOK(arc->IsItem_Anti(i, up2.IsAnti));
up2.NewNameIndex = (int)newNames.Add(dest);
}
updatePairs2.Add(up2);
@@ -661,6 +711,7 @@ static HRESULT Compress(
else
stat.NumDirs++;
}
#ifdef _WIN32
else if (di.IsAltStream)
{
if (up.IsAnti)
@@ -671,6 +722,7 @@ static HRESULT Compress(
stat.AltStreamsSize += di.Size;
}
}
#endif
else
{
if (up.IsAnti)
@@ -740,6 +792,8 @@ static HRESULT Compress(
updateCallbackSpec->StoreNtSecurity = options.NtSecurity.Val;
updateCallbackSpec->StoreHardLinks = options.HardLinks.Val;
updateCallbackSpec->StoreSymLinks = options.SymLinks.Val;
updateCallbackSpec->StoreOwnerName = options.StoreOwnerName.Val;
updateCallbackSpec->StoreOwnerId = options.StoreOwnerId.Val;
updateCallbackSpec->Arc = arc;
updateCallbackSpec->ArcItems = &arcItems;
@@ -755,6 +809,12 @@ static HRESULT Compress(
if (options.RenamePairs.Size() != 0)
updateCallbackSpec->NewNames = &newNames;
if (options.SetArcMTime)
{
// updateCallbackSpec->Need_ArcMTime_Report = true;
updateCallbackSpec->Need_LatestMTime = true;
}
CMyComPtr<IOutStream> outSeekStream;
CMyComPtr<ISequentialOutStream> outStream;
@@ -838,8 +898,6 @@ static HRESULT Compress(
*/
}
RINOK(SetProperties(outArchive, options.MethodMode.Properties));
if (options.SfxMode)
{
CInFileStream *sfxStreamSpec = new CInFileStream;
@@ -909,24 +967,71 @@ static HRESULT Compress(
if (options.SetArcMTime)
{
FILETIME ft;
ft.dwLowDateTime = 0;
ft.dwHighDateTime = 0;
FOR_VECTOR (i, updatePairs2)
CFiTime ft;
FiTime_Clear(ft);
bool isDefined = false;
// bool needNormalizeAfterStream;
// needParse;
/*
if (updateCallbackSpec->ArcMTime_WasReported)
{
const CUpdatePair2 &pair2 = updatePairs2[i];
const FILETIME *ft2 = NULL;
if (pair2.NewProps && pair2.DirIndex >= 0)
ft2 = &dirItems.Items[(unsigned)pair2.DirIndex].MTime;
else if (pair2.UseArcProps && pair2.ArcIndex >= 0)
ft2 = &arcItems[(unsigned)pair2.ArcIndex].MTime;
if (ft2)
{
if (::CompareFileTime(&ft, ft2) < 0)
ft = *ft2;
}
isDefined = updateCallbackSpec->Reported_ArcMTime.Def;
if (isDefined)
updateCallbackSpec->Reported_ArcMTime.Write_To_FiTime(ft);
else
fileTimeType = NFileTimeType::kNotDefined;
}
if (ft.dwLowDateTime != 0 || ft.dwHighDateTime != 0)
if (!isDefined)
*/
{
if (updateCallbackSpec->LatestMTime_Defined)
{
// CArcTime at = StreamCallback_ArcMTime;
// updateCallbackSpec->StreamCallback_ArcMTime.Write_To_FiTime(ft);
// we must normalize with precision from archive;
ft = updateCallbackSpec->LatestMTime;
isDefined = true;
}
FOR_VECTOR (i, updatePairs2)
{
const CUpdatePair2 &pair2 = updatePairs2[i];
CFiTime ft2;
bool ft2_Defined = false;
/* we use full precision of dirItem, if dirItem is defined
and (dirItem will be used or dirItem is sameTime in dir and arc */
if (pair2.DirIndex >= 0 &&
(pair2.NewProps || pair2.IsSameTime))
{
ft2 = dirItems.Items[(unsigned)pair2.DirIndex].MTime;
ft2_Defined = true;
}
else if (pair2.UseArcProps && pair2.ArcIndex >= 0)
{
const CArcItem &arcItem = arcItems[(unsigned)pair2.ArcIndex];
if (arcItem.MTime.Def)
{
arcItem.MTime.Write_To_FiTime(ft2);
ft2_Defined = true;
}
}
if (ft2_Defined)
{
if (Compare_FiTime(&ft, &ft2) < 0)
{
ft = ft2;
isDefined = true;
}
}
}
/*
if (fileTimeType != NFileTimeType::kNotDefined)
FiTime_Normalize_With_Prec(ft, fileTimeType);
*/
}
// if (ft.dwLowDateTime != 0 || ft.dwHighDateTime != 0)
if (isDefined)
{
if (outStreamSpec)
outStreamSpec->SetMTime(&ft);
@@ -1046,26 +1151,9 @@ static HRESULT EnumerateInArchiveItems(
else
ai.Censored = Censor_CheckPath(censor, item);
RINOK(arc.GetItemMTime(i, ai.MTime, ai.MTimeDefined));
RINOK(arc.GetItemSize(i, ai.Size, ai.SizeDefined));
{
CPropVariant prop;
RINOK(archive->GetProperty(i, kpidTimeType, &prop));
if (prop.vt == VT_UI4)
{
ai.TimeType = (int)(NFileTimeType::EEnum)prop.ulVal;
switch (ai.TimeType)
{
case NFileTimeType::kWindows:
case NFileTimeType::kUnix:
case NFileTimeType::kDOS:
break;
default:
return E_FAIL;
}
}
}
// ai.MTime will be set to archive MTime, if not present in archive item
RINOK(arc.GetItem_MTime(i, ai.MTime));
RINOK(arc.GetItem_Size(i, ai.Size, ai.Size_Defined));
ai.IndexInServer = i;
arcItems.AddInReserved(ai);
@@ -1198,8 +1286,10 @@ HRESULT UpdateArchive(
EISDIR
#endif
);
#ifdef _WIN32
if (fi.IsDevice)
return E_NOTIMPL;
#endif
if (!options.StdOutMode && options.UpdateArchiveItself)
if (fi.IsReadOnly())
@@ -1262,8 +1352,14 @@ HRESULT UpdateArchive(
}
CArc &arc = arcLink.Arcs.Back();
arc.MTimeDefined = !fi.IsDevice;
arc.MTime = fi.MTime;
arc.MTime.Def =
#ifdef _WIN32
!fi.IsDevice;
#else
true;
#endif
if (arc.MTime.Def)
arc.MTime.Set_From_FiTime(fi.MTime);
if (arc.ErrorInfo.ThereIsTail)
{
@@ -1307,10 +1403,11 @@ HRESULT UpdateArchive(
if (options.StdInMode)
{
CDirItem di;
di.ClearBase();
di.Name = options.StdInFileName;
di.Size = (UInt64)(Int64)-1;
di.Attrib = 0;
NTime::GetCurUtcFileTime(di.MTime);
di.SetAsFile();
NTime::GetCurUtc_FiTime(di.MTime);
di.CTime = di.ATime = di.MTime;
dirItems.Items.Add(di);
}
@@ -1336,8 +1433,14 @@ HRESULT UpdateArchive(
dirItems.ScanAltStreams = options.AltStreams.Val;
dirItems.ExcludeDirItems = censor.ExcludeDirItems;
dirItems.ExcludeFileItems = censor.ExcludeFileItems;
dirItems.ShareForWrite = options.OpenShareForWrite;
HRESULT res = EnumerateItems(censor,
#ifndef _WIN32
dirItems.StoreOwnerName = options.StoreOwnerName.Val;
#endif
const HRESULT res = EnumerateItems(censor,
options.PathMode,
UString(), // options.AddPathPrefix,
dirItems);
@@ -1351,6 +1454,8 @@ HRESULT UpdateArchive(
RINOK(callback->FinishScanning(dirItems.Stat));
// 22.00: we don't need parent folder, if absolute path mode
if (options.PathMode != NWildcard::k_AbsPath)
if (censor.Pairs.Size() == 1)
{
NFind::CFileInfo fi;
@@ -1366,11 +1471,7 @@ HRESULT UpdateArchive(
if (fi.Find(prefix))
if (fi.IsDir())
{
parentDirItem.Size = fi.Size;
parentDirItem.CTime = fi.CTime;
parentDirItem.ATime = fi.ATime;
parentDirItem.MTime = fi.MTime;
parentDirItem.Attrib = fi.Attrib;
parentDirItem.Copy_From_FileInfoBase(fi);
parentDirItem_Ptr = &parentDirItem;
int secureIndex = -1;
@@ -1723,8 +1824,8 @@ HRESULT UpdateArchive(
is_SameSize = (fileInfo.Size == dirItem.Size);
if (is_SameSize
&& CompareFileTime(&fileInfo.MTime, &dirItem.MTime) == 0
&& CompareFileTime(&fileInfo.CTime, &dirItem.CTime) == 0)
&& Compare_FiTime(&fileInfo.MTime, &dirItem.MTime) == 0
&& Compare_FiTime(&fileInfo.CTime, &dirItem.CTime) == 0)
{
RINOK(callback->DeletingAfterArchiving(phyPath, false));
DeleteFileAlways(phyPath);

View File

@@ -112,6 +112,9 @@ struct CUpdateOptions
CBoolPair HardLinks;
CBoolPair SymLinks;
CBoolPair StoreOwnerId;
CBoolPair StoreOwnerName;
bool DeleteAfterCompressing;
bool SetArcMTime;

View File

@@ -4,6 +4,15 @@
// #include <stdio.h>
#ifndef _WIN32
// #include <grp.h>
// #include <pwd.h>
// for major minor:
// BSD: <sys/types.h>
#include <sys/sysmacros.h>
#endif
#ifndef _7ZIP_ST
#include "../../../Windows/Synchronization.h"
#endif
@@ -66,6 +75,18 @@ CArchiveUpdateCallback::CArchiveUpdateCallback():
StoreNtSecurity(false),
StoreHardLinks(false),
StoreSymLinks(false),
#ifndef _WIN32
StoreOwnerId(false),
StoreOwnerName(false),
#endif
/*
, Need_ArcMTime_Report(false),
, ArcMTime_WasReported(false),
*/
Need_LatestMTime(false),
LatestMTime_Defined(false),
ProcessedItemsStatuses(NULL)
{
@@ -134,16 +155,17 @@ STDMETHODIMP CArchiveUpdateCallback::GetUpdateItemInfo(UInt32 index,
COM_TRY_END
}
STDMETHODIMP CArchiveUpdateCallback::GetRootProp(PROPID propID, PROPVARIANT *value)
{
NCOM::CPropVariant prop;
switch (propID)
{
case kpidIsDir: prop = true; break;
case kpidAttrib: if (ParentDirItem) prop = ParentDirItem->Attrib; break;
case kpidCTime: if (ParentDirItem) prop = ParentDirItem->CTime; break;
case kpidATime: if (ParentDirItem) prop = ParentDirItem->ATime; break;
case kpidMTime: if (ParentDirItem) prop = ParentDirItem->MTime; break;
case kpidAttrib: if (ParentDirItem) prop = ParentDirItem->GetWinAttrib(); break;
case kpidCTime: if (ParentDirItem) PropVariant_SetFrom_FiTime(prop, ParentDirItem->CTime); break;
case kpidATime: if (ParentDirItem) PropVariant_SetFrom_FiTime(prop, ParentDirItem->ATime); break;
case kpidMTime: if (ParentDirItem) PropVariant_SetFrom_FiTime(prop, ParentDirItem->MTime); break;
case kpidArcFileName: if (!ArcFileName.IsEmpty()) prop = ArcFileName; break;
}
prop.Detach(value);
@@ -446,25 +468,46 @@ STDMETHODIMP CArchiveUpdateCallback::GetProperty(UInt32 index, PROPID propID, PR
{
case kpidPath: prop = DirItems->GetLogPath((unsigned)up.DirIndex); break;
case kpidIsDir: prop = di.IsDir(); break;
case kpidSize: prop = di.IsDir() ? (UInt64)0 : di.Size; break;
case kpidAttrib: prop = di.Attrib; break;
case kpidCTime: prop = di.CTime; break;
case kpidATime: prop = di.ATime; break;
case kpidMTime: prop = di.MTime; break;
case kpidSize: prop = (UInt64)(di.IsDir() ? (UInt64)0 : di.Size); break;
case kpidCTime: PropVariant_SetFrom_FiTime(prop, di.CTime); break;
case kpidATime: PropVariant_SetFrom_FiTime(prop, di.ATime); break;
case kpidMTime: PropVariant_SetFrom_FiTime(prop, di.MTime); break;
case kpidAttrib: prop = (UInt32)di.GetWinAttrib(); break;
case kpidPosixAttrib: prop = (UInt32)di.GetPosixAttrib(); break;
#if defined(_WIN32)
case kpidIsAltStream: prop = di.IsAltStream; break;
#if defined(_WIN32) && !defined(UNDER_CE)
// case kpidShortName: prop = di.ShortName; break;
#endif
case kpidPosixAttrib:
{
#ifdef _WIN32
prop = di.GetPosixAttrib();
#else
if (di.Attrib & FILE_ATTRIBUTE_UNIX_EXTENSION)
prop = (UInt32)(di.Attrib >> 16);
#endif
#else
case kpidDeviceMajor:
/*
printf("\ndi.mode = %o\n", di.mode);
printf("\nst.st_rdev major = %d\n", (unsigned)major(di.rdev));
printf("\nst.st_rdev minor = %d\n", (unsigned)minor(di.rdev));
*/
if (S_ISCHR(di.mode) || S_ISBLK(di.mode))
prop = (UInt32)major(di.rdev);
break;
}
case kpidDeviceMinor:
if (S_ISCHR(di.mode) || S_ISBLK(di.mode))
prop = (UInt32)minor(di.rdev);
break;
// case kpidDevice: if (S_ISCHR(di.mode) || S_ISBLK(di.mode)) prop = (UInt64)(di.rdev); break;
case kpidUserId: if (StoreOwnerId) prop = (UInt32)di.uid; break;
case kpidGroupId: if (StoreOwnerId) prop = (UInt32)di.gid; break;
case kpidUser:
if (di.OwnerNameIndex >= 0)
prop = DirItems->OwnerNameMap.Strings[(unsigned)di.OwnerNameIndex];
break;
case kpidGroup:
if (di.OwnerGroupIndex >= 0)
prop = DirItems->OwnerGroupMap.Strings[(unsigned)di.OwnerGroupIndex];
break;
#endif
}
}
prop.Detach(value);
@@ -565,12 +608,41 @@ STDMETHODIMP CArchiveUpdateCallback::GetStream2(UInt32 index, ISequentialInStrea
CInFileStream *inStreamSpec = new CInFileStream;
CMyComPtr<ISequentialInStream> inStreamLoc(inStreamSpec);
/*
// for debug:
#ifdef _WIN32
inStreamSpec->StoreOwnerName = true;
inStreamSpec->OwnerName = "user_name";
inStreamSpec->OwnerName += di.Name;
inStreamSpec->OwnerName += "11111111112222222222222333333333333";
inStreamSpec->OwnerGroup = "gname_";
inStreamSpec->OwnerGroup += inStreamSpec->OwnerName;
#endif
*/
#ifndef _WIN32
inStreamSpec->StoreOwnerId = StoreOwnerId;
inStreamSpec->StoreOwnerName = StoreOwnerName;
// if (StoreOwner)
{
inStreamSpec->_uid = di.uid;
inStreamSpec->_gid = di.gid;
if (di.OwnerNameIndex >= 0)
inStreamSpec->OwnerName = DirItems->OwnerNameMap.Strings[(unsigned)di.OwnerNameIndex];
if (di.OwnerGroupIndex >= 0)
inStreamSpec->OwnerGroup = DirItems->OwnerGroupMap.Strings[(unsigned)di.OwnerGroupIndex];
}
#endif
inStreamSpec->SupportHardLinks = StoreHardLinks;
inStreamSpec->File.PreserveATime = PreserveATime;
inStreamSpec->Set_PreserveATime(PreserveATime
|| mode == NUpdateNotifyOp::kAnalyze); // 22.00 : we don't change access time in Analyze pass.
const FString path = DirItems->GetPhyPath((unsigned)up.DirIndex);
_openFiles_Indexes.Add(index);
_openFiles_Paths.Add(path);
// _openFiles_Streams.Add(inStreamSpec);
/* 21.02 : we set Callback/CallbackRef after _openFiles_Indexes adding
for correct working if exception was raised in GetPhyPath */
@@ -579,14 +651,30 @@ STDMETHODIMP CArchiveUpdateCallback::GetStream2(UInt32 index, ISequentialInStrea
if (!inStreamSpec->OpenShared(path, ShareForWrite))
{
DWORD error = ::GetLastError();
HRESULT hres = Callback->OpenFileError(path, error);
const DWORD error = ::GetLastError();
const HRESULT hres = Callback->OpenFileError(path, error);
if (StopAfterOpenError)
if (hres == S_OK || hres == S_FALSE)
return HRESULT_FROM_WIN32(error);
return hres;
}
/*
{
// for debug:
Byte b = 0;
UInt32 processedSize = 0;
if (inStreamSpec->Read(&b, 1, &processedSize) != S_OK ||
processedSize != 1)
return E_FAIL;
}
*/
if (Need_LatestMTime)
{
inStreamSpec->ReloadProps();
}
// #if defined(USE_WIN_FILE) || !defined(_WIN32)
if (StoreHardLinks)
{
@@ -643,6 +731,8 @@ STDMETHODIMP CArchiveUpdateCallback::ReportOperation(UInt32 indexType, UInt32 in
{
COM_TRY_BEGIN
// if (op == NUpdateNotifyOp::kOpFinished) return Callback->ReportFinished(indexType, index);
bool isDir = false;
if (indexType == NArchive::NEventIndexType::kOutArcIndex)
@@ -676,7 +766,7 @@ STDMETHODIMP CArchiveUpdateCallback::ReportOperation(UInt32 indexType, UInt32 in
}
else if (Arc)
{
RINOK(Arc->GetItemPath(index, s2));
RINOK(Arc->GetItem_Path(index, s2));
s = s2;
RINOK(Archive_IsItem_Dir(Arc->Archive, index, isDir));
}
@@ -731,7 +821,7 @@ STDMETHODIMP CArchiveUpdateCallback::ReportExtractResult(UInt32 indexType, UInt3
s = (*ArcItems)[index].Name;
else if (Arc)
{
RINOK(Arc->GetItemPath(index, s2));
RINOK(Arc->GetItem_Path(index, s2));
s = s2;
}
if (Archive)
@@ -752,6 +842,51 @@ STDMETHODIMP CArchiveUpdateCallback::ReportExtractResult(UInt32 indexType, UInt3
COM_TRY_END
}
/*
STDMETHODIMP CArchiveUpdateCallback::DoNeedArcProp(PROPID propID, Int32 *answer)
{
*answer = 0;
if (Need_ArcMTime_Report && propID == kpidComboMTime)
*answer = 1;
return S_OK;
}
STDMETHODIMP CArchiveUpdateCallback::ReportProp(UInt32 indexType, UInt32 index, PROPID propID, const PROPVARIANT *value)
{
if (indexType == NArchive::NEventIndexType::kArcProp)
{
if (propID == kpidComboMTime)
{
ArcMTime_WasReported = true;
if (value->vt == VT_FILETIME)
{
Reported_ArcMTime.Set_From_Prop(*value);
Reported_ArcMTime.Def = true;
}
else
{
Reported_ArcMTime.Clear();
if (value->vt != VT_EMPTY)
return E_FAIL; // for debug
}
}
}
return Callback->ReportProp(indexType, index, propID, value);
}
STDMETHODIMP CArchiveUpdateCallback::ReportRawProp(UInt32 indexType, UInt32 index,
PROPID propID, const void *data, UInt32 dataSize, UInt32 propType)
{
return Callback->ReportRawProp(indexType, index, propID, data, dataSize, propType);
}
STDMETHODIMP CArchiveUpdateCallback::ReportFinished(UInt32 indexType, UInt32 index, Int32 opRes)
{
return Callback->ReportFinished(indexType, index, opRes);
}
*/
STDMETHODIMP CArchiveUpdateCallback::GetVolumeSize(UInt32 index, UInt64 *size)
{
if (VolumesSizes.Size() == 0)
@@ -805,7 +940,7 @@ HRESULT CArchiveUpdateCallback::InFileStream_On_Error(UINT_PTR val, DWORD error)
#endif
{
MT_LOCK
UInt32 index = (UInt32)val;
const UInt32 index = (UInt32)val;
FOR_VECTOR(i, _openFiles_Indexes)
{
if (_openFiles_Indexes[i] == index)
@@ -818,21 +953,31 @@ HRESULT CArchiveUpdateCallback::InFileStream_On_Error(UINT_PTR val, DWORD error)
return HRESULT_FROM_WIN32(error);
}
void CArchiveUpdateCallback::InFileStream_On_Destroy(UINT_PTR val)
void CArchiveUpdateCallback::InFileStream_On_Destroy(CInFileStream *stream, UINT_PTR val)
{
{
MT_LOCK
UInt32 index = (UInt32)val;
if (Need_LatestMTime)
{
if (stream->_info_WasLoaded)
{
const CFiTime &ft = ST_MTIME(stream->_info);
if (!LatestMTime_Defined
|| Compare_FiTime(&LatestMTime, &ft) < 0)
LatestMTime = ft;
LatestMTime_Defined = true;
}
}
const UInt32 index = (UInt32)val;
FOR_VECTOR(i, _openFiles_Indexes)
{
if (_openFiles_Indexes[i] == index)
{
_openFiles_Indexes.Delete(i);
_openFiles_Paths.Delete(i);
// _openFiles_Streams.Delete(i);
return;
}
}
}
/* 21.02 : this function can be called in destructor.
And destructor can be called after some exception.
If we don't want to throw exception in desctructors or after another exceptions,

View File

@@ -45,6 +45,13 @@ struct CArcToDoStat
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; } */
struct IUpdateCallbackUI
@@ -70,6 +77,7 @@ struct CKeyKeyValPair
class CArchiveUpdateCallback:
public IArchiveUpdateCallback2,
public IArchiveUpdateCallbackFile,
// public IArchiveUpdateCallbackArcProp,
public IArchiveExtractCallbackMessage,
public IArchiveGetRawProps,
public IArchiveGetRootProps,
@@ -92,6 +100,7 @@ class CArchiveUpdateCallback:
public:
MY_QUERYINTERFACE_BEGIN2(IArchiveUpdateCallback2)
MY_QUERYINTERFACE_ENTRY(IArchiveUpdateCallbackFile)
// MY_QUERYINTERFACE_ENTRY(IArchiveUpdateCallbackArcProp)
MY_QUERYINTERFACE_ENTRY(IArchiveExtractCallbackMessage)
MY_QUERYINTERFACE_ENTRY(IArchiveGetRawProps)
MY_QUERYINTERFACE_ENTRY(IArchiveGetRootProps)
@@ -106,6 +115,7 @@ public:
INTERFACE_IArchiveUpdateCallback2(;)
INTERFACE_IArchiveUpdateCallbackFile(;)
// INTERFACE_IArchiveUpdateCallbackArcProp(;)
INTERFACE_IArchiveExtractCallbackMessage(;)
INTERFACE_IArchiveGetRawProps(;)
INTERFACE_IArchiveGetRootProps(;)
@@ -115,10 +125,11 @@ public:
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);
virtual void InFileStream_On_Destroy(UINT_PTR val);
virtual void InFileStream_On_Destroy(CInFileStream *stream, UINT_PTR val);
CRecordVector<UInt64> VolumesSizes;
FString VolName;
@@ -148,8 +159,22 @@ public:
bool StoreHardLinks;
bool StoreSymLinks;
bool StoreOwnerId;
bool StoreOwnerName;
/*
bool Need_ArcMTime_Report;
bool ArcMTime_WasReported;
CArcTime Reported_ArcMTime;
*/
bool Need_LatestMTime;
bool LatestMTime_Defined;
CFiTime LatestMTime;
Byte *ProcessedItemsStatuses;
CArchiveUpdateCallback();
bool IsDir(const CUpdatePair2 &up) const

View File

@@ -3,6 +3,7 @@
#include "StdAfx.h"
#include <time.h>
// #include <stdio.h>
#include "../../../Common/Wildcard.h"
@@ -14,30 +15,90 @@
using namespace NWindows;
using namespace NTime;
static int MyCompareTime(NFileTimeType::EEnum fileTimeType, const FILETIME &time1, const FILETIME &time2)
{
switch (fileTimeType)
/*
a2.Prec =
{
case NFileTimeType::kWindows:
return ::CompareFileTime(&time1, &time2);
case NFileTimeType::kUnix:
{
UInt32 unixTime1, unixTime2;
FileTimeToUnixTime(time1, unixTime1);
FileTimeToUnixTime(time2, unixTime2);
return MyCompare(unixTime1, unixTime2);
}
case NFileTimeType::kDOS:
{
UInt32 dosTime1, dosTime2;
FileTimeToDosTime(time1, dosTime1);
FileTimeToDosTime(time2, dosTime2);
return MyCompare(dosTime1, dosTime2);
}
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()
}
throw 4191618;
*/
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):";
@@ -64,8 +125,8 @@ static int CompareArcItemsBase(const CArcItem &ai1, const CArcItem &ai2)
static int CompareArcItems(const unsigned *p1, const unsigned *p2, void *param)
{
unsigned i1 = *p1;
unsigned i2 = *p2;
const unsigned i1 = *p1;
const unsigned i2 = *p2;
const CObjectVector<CArcItem> &arcItems = *(const CObjectVector<CArcItem> *)param;
int res = CompareArcItemsBase(arcItems[i1], arcItems[i2]);
if (res != 0)
@@ -81,8 +142,8 @@ void GetUpdatePairInfoList(
{
CUIntVector dirIndices, arcIndices;
unsigned numDirItems = dirItems.Items.Size();
unsigned numArcItems = arcItems.Size();
const unsigned numDirItems = dirItems.Items.Size();
const unsigned numArcItems = arcItems.Size();
CIntArr duplicatedArcItem(numArcItems);
{
@@ -184,7 +245,7 @@ void GetUpdatePairInfoList(
}
else
{
int dupl = duplicatedArcItem[arcIndex];
const int dupl = duplicatedArcItem[arcIndex];
if (dupl != 0)
ThrowError(k_Duplicate_inArc_Message, ai->Name, arcItems[arcIndices[(unsigned)((int)arcIndex + dupl)]].Name);
@@ -195,14 +256,17 @@ void GetUpdatePairInfoList(
pair.DirIndex = dirIndex2;
pair.ArcIndex = arcIndex2;
switch (ai->MTimeDefined ? MyCompareTime(
ai->TimeType != - 1 ? (NFileTimeType::EEnum)ai->TimeType : fileTimeType,
di->MTime, ai->MTime): 0)
int compResult = 0;
if (ai->MTime.Def)
{
compResult = MyCompareTime(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->SizeDefined && di->Size == ai->Size) ?
pair.State = (ai->Size_Defined && di->Size == ai->Size) ?
NUpdateArchive::NPairState::kSameFiles :
NUpdateArchive::NPairState::kUnknowNewerFiles;
}
@@ -211,7 +275,10 @@ void GetUpdatePairInfoList(
arcIndex++;
}
if ((di && di->IsAltStream) ||
if (
#ifdef _WIN32
(di && di->IsAltStream) ||
#endif
(ai && ai->IsAltStream))
{
if (prevHostName)

View File

@@ -63,6 +63,8 @@ void UpdateProduce(
break;
}
up2.IsSameTime = ((unsigned)pair.State == NUpdateArchive::NPairState::kSameFiles);
operationChain.Add(up2);
}

View File

@@ -17,6 +17,7 @@ struct CUpdatePair2
int NewNameIndex;
bool IsMainRenameItem;
bool IsSameTime;
void SetAs_NoChangeArcItem(unsigned arcIndex) // int
{
@@ -37,7 +38,8 @@ struct CUpdatePair2
DirIndex(-1),
ArcIndex(-1),
NewNameIndex(-1),
IsMainRenameItem(false)
IsMainRenameItem(false),
IsSameTime(false)
{}
};

View File

@@ -33,12 +33,45 @@ 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)
{
if (key.QueryValue(name, value) != ERROR_SUCCESS)
value = (UInt32)(Int32)-1;
}
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_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;
@@ -169,6 +202,13 @@ 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)
{
@@ -178,26 +218,12 @@ static void SetRegString(CKey &key, LPCWSTR name, const UString &value)
key.SetValue(name, value);
}
static void SetRegUInt32(CKey &key, LPCTSTR name, UInt32 value)
{
if (value == (UInt32)(Int32)-1)
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 void GetRegUInt32(CKey &key, LPCTSTR name, UInt32 &value)
{
if (key.QueryValue(name, value) != ERROR_SUCCESS)
value = (UInt32)(Int32)-1;
}
static LPCWSTR const kMemUse = L"MemUse"
#if defined(MY_CPU_SIZEOF_POINTER) && (MY_CPU_SIZEOF_POINTER == 4)
L"32";
@@ -212,10 +238,11 @@ void CInfo::Save() const
CKey key;
CreateMainKey(key, kKeyName);
Key_Set_BoolPair(key, kNtSecur, NtSecurity);
Key_Set_BoolPair(key, kAltStreams, AltStreams);
Key_Set_BoolPair(key, kHardLinks, HardLinks);
Key_Set_BoolPair(key, kSymLinks, SymLinks);
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);
@@ -235,16 +262,22 @@ void CInfo::Save() const
CKey fk;
fk.Create(optionsKey, fo.FormatID);
SetRegUInt32(fk, kLevel, fo.Level);
SetRegUInt32(fk, kDictionary, fo.Dictionary);
SetRegUInt32(fk, kOrder, fo.Order);
SetRegUInt32(fk, kBlockSize, fo.BlockLogSize);
SetRegUInt32(fk, kNumThreads, fo.NumThreads);
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, 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);
}
}
}
@@ -269,6 +302,7 @@ void CInfo::Load()
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);
@@ -290,11 +324,17 @@ void CInfo::Load()
GetRegString(fk, kEncryptionMethod, fo.EncryptionMethod);
GetRegString(fk, kMemUse, fo.MemUse);
GetRegUInt32(fk, kLevel, fo.Level);
GetRegUInt32(fk, kDictionary, fo.Dictionary);
GetRegUInt32(fk, kOrder, fo.Order);
GetRegUInt32(fk, kBlockSize, fo.BlockLogSize);
GetRegUInt32(fk, kNumThreads, fo.NumThreads);
Key_Get_UInt32(fk, kLevel, fo.Level);
Key_Get_UInt32(fk, kDictionary, fo.Dictionary);
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);
}
@@ -478,6 +518,7 @@ 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
{
@@ -488,6 +529,8 @@ void CContextMenuInfo::Save() const
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);
@@ -504,6 +547,8 @@ void CContextMenuInfo::Load()
ElimDup.Val = true;
ElimDup.Def = false;
WriteZone = (UInt32)(Int32)-1;
Flags = (UInt32)(Int32)-1;
Flags_Def = false;
@@ -517,5 +562,7 @@ void CContextMenuInfo::Load()
Key_Get_BoolPair_true(key, kElimDup, ElimDup);
Key_Get_BoolPair(key, kMenuIcons, MenuIcons);
Key_Get_UInt32(key, kWriteZoneId, WriteZone);
Flags_Def = (key.GetValue_IfOk(kContextMenu, Flags) == ERROR_SUCCESS);
}

View File

@@ -10,6 +10,16 @@
#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
@@ -75,12 +85,29 @@ namespace NCompression
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;
@@ -93,7 +120,12 @@ namespace NCompression
// Options.Empty();
// EncryptionMethod.Empty();
}
CFormatOptions() { ResetForLevelChange(); }
CFormatOptions()
{
// TimePrec = 0;
Reset_TimePrec();
ResetForLevelChange();
}
};
struct CInfo
@@ -111,6 +143,8 @@ namespace NCompression
CBoolPair HardLinks;
CBoolPair SymLinks;
CBoolPair PreserveATime;
void Save() const;
void Load();
};
@@ -152,9 +186,18 @@ 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();