mirror of
https://github.com/Xevion/easy7zip.git
synced 2025-12-10 12:07:08 -06:00
Update to 7-Zip Version 22.00
See: https://sourceforge.net/p/sevenzip/discussion/45797/thread/9c2d9061ce/
This commit is contained in:
@@ -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)
|
||||
|
||||
@@ -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),
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -334,7 +334,7 @@ static void ExtractGroupCommand(const UStringVector &arcPaths, UString ¶ms,
|
||||
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);
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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));
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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)
|
||||
{}
|
||||
};
|
||||
|
||||
|
||||
@@ -29,6 +29,16 @@ namespace NOverwriteMode
|
||||
};
|
||||
}
|
||||
|
||||
namespace NZoneIdMode
|
||||
{
|
||||
enum EEnum
|
||||
{
|
||||
kNone,
|
||||
kAll,
|
||||
kOffice
|
||||
};
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
@@ -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
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -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)
|
||||
{}
|
||||
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -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); }
|
||||
|
||||
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -112,6 +112,9 @@ struct CUpdateOptions
|
||||
CBoolPair HardLinks;
|
||||
CBoolPair SymLinks;
|
||||
|
||||
CBoolPair StoreOwnerId;
|
||||
CBoolPair StoreOwnerName;
|
||||
|
||||
bool DeleteAfterCompressing;
|
||||
|
||||
bool SetArcMTime;
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -63,6 +63,8 @@ void UpdateProduce(
|
||||
break;
|
||||
}
|
||||
|
||||
up2.IsSameTime = ((unsigned)pair.State == NUpdateArchive::NPairState::kSameFiles);
|
||||
|
||||
operationChain.Add(up2);
|
||||
}
|
||||
|
||||
|
||||
@@ -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)
|
||||
{}
|
||||
};
|
||||
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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();
|
||||
|
||||
Reference in New Issue
Block a user