This commit is contained in:
Igor Pavlov
2018-01-30 00:15:34 +00:00
committed by Kornel
parent da28077952
commit 866a06f5a0
30 changed files with 1413 additions and 119 deletions

View File

@@ -1217,7 +1217,12 @@ STDMETHODIMP CAgentFolder::GetFolderProperty(PROPID propID, PROPVARIANT *value)
NWindows::NCOM::CPropVariant prop;
if (propID == kpidReadOnly)
prop = _agentSpec->IsThereReadOnlyArc();
{
if (_agentSpec->Is_Attrib_ReadOnly())
prop = true;
else
prop = _agentSpec->IsThereReadOnlyArc();
}
else if (_proxy2)
{
const CProxyDir2 &dir = _proxy2->Dirs[_proxyDirIndex];
@@ -1564,6 +1569,7 @@ STDMETHODIMP CAgent::Open(
{
COM_TRY_BEGIN
_archiveFilePath = filePath;
_attrib = 0;
NFile::NFind::CFileInfo fi;
_isDeviceFile = false;
if (!inStream)
@@ -1572,6 +1578,7 @@ STDMETHODIMP CAgent::Open(
return ::GetLastError();
if (fi.IsDir())
return E_FAIL;
_attrib = fi.Attrib;
_isDeviceFile = fi.IsDevice;
}
CArcInfoEx archiverInfo0, archiverInfo1;

View File

@@ -241,6 +241,7 @@ public:
CAgentFolder *_agentFolder;
UString _archiveFilePath;
DWORD _attrib;
bool _isDeviceFile;
#ifndef EXTRACT_ONLY
@@ -252,6 +253,11 @@ public:
IInArchive *GetArchive() const { if ( _archiveLink.Arcs.IsEmpty()) return 0; return GetArc().Archive; }
bool CanUpdate() const;
bool Is_Attrib_ReadOnly() const
{
return _attrib != INVALID_FILE_ATTRIBUTES && (_attrib & FILE_ATTRIBUTE_READONLY);
}
bool IsThereReadOnlyArc() const
{
FOR_VECTOR (i, _archiveLink.Arcs)

View File

@@ -372,6 +372,8 @@ void CArchiveExtractCallback::CreateComplexDirectory(const UStringVector &dirPat
HRESULT CArchiveExtractCallback::GetTime(UInt32 index, PROPID propID, FILETIME &filetime, bool &filetimeIsDefined)
{
filetimeIsDefined = false;
filetime.dwLowDateTime = 0;
filetime.dwHighDateTime = 0;
NCOM::CPropVariant prop;
RINOK(_arc->Archive->GetProperty(index, propID, &prop));
if (prop.vt == VT_FILETIME)
@@ -1032,14 +1034,36 @@ if (askExtractMode == NArchive::NExtract::NAskMode::kExtract && !_testMode)
{
FString fullPathNew;
CreateComplexDirectory(pathParts, fullPathNew);
if (_item.IsDir)
{
_extractedFolderPaths.Add(fullPathNew);
_extractedFolderIndices.Add(index);
SetDirTime(fullPathNew,
(WriteCTime && _fi.CTimeDefined) ? &_fi.CTime : NULL,
(WriteATime && _fi.ATimeDefined) ? &_fi.ATime : NULL,
(WriteMTime && _fi.MTimeDefined) ? &_fi.MTime : (_arc->MTimeDefined ? &_arc->MTime : NULL));
CDirPathTime &pt = _extractedFolders.AddNew();
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;
}
}
pt.Path = fullPathNew;
pt.SetDirTime();
}
}
}
@@ -1602,75 +1626,53 @@ STDMETHODIMP CArchiveExtractCallback::CryptoGetTextPassword(BSTR *password)
}
struct CExtrRefSortPair
{
unsigned Len;
unsigned Index;
int Compare(const CExtrRefSortPair &a) const;
};
#define RINOZ(x) { int __tt = (x); if (__tt != 0) return __tt; }
int CExtrRefSortPair::Compare(const CExtrRefSortPair &a) const
{
RINOZ(-MyCompare(Len, a.Len));
return MyCompare(Index, a.Index);
}
static unsigned GetNumSlashes(const FChar *s)
void CDirPathSortPair::SetNumSlashes(const FChar *s)
{
for (unsigned numSlashes = 0;;)
{
FChar c = *s++;
if (c == 0)
return numSlashes;
{
Len = numSlashes;
return;
}
if (IS_PATH_SEPAR(c))
numSlashes++;
}
}
bool CDirPathTime::SetDirTime()
{
return NDir::SetDirTime(Path,
CTimeDefined ? &CTime : NULL,
ATimeDefined ? &ATime : NULL,
MTimeDefined ? &MTime : NULL);
}
HRESULT CArchiveExtractCallback::SetDirsTimes()
{
if (!_arc)
return S_OK;
CRecordVector<CExtrRefSortPair> pairs;
pairs.ClearAndSetSize(_extractedFolderPaths.Size());
CRecordVector<CDirPathSortPair> pairs;
pairs.ClearAndSetSize(_extractedFolders.Size());
unsigned i;
for (i = 0; i < _extractedFolderPaths.Size(); i++)
for (i = 0; i < _extractedFolders.Size(); i++)
{
CExtrRefSortPair &pair = pairs[i];
CDirPathSortPair &pair = pairs[i];
pair.Index = i;
pair.Len = GetNumSlashes(_extractedFolderPaths[i]);
pair.SetNumSlashes(_extractedFolders[i].Path);
}
pairs.Sort2();
for (i = 0; i < pairs.Size(); i++)
{
unsigned pairIndex = pairs[i].Index;
UInt32 index = _extractedFolderIndices[pairIndex];
FILETIME CTime;
FILETIME ATime;
FILETIME MTime;
bool CTimeDefined;
bool ATimeDefined;
bool MTimeDefined;
RINOK(GetTime(index, kpidCTime, CTime, CTimeDefined));
RINOK(GetTime(index, kpidATime, ATime, ATimeDefined));
RINOK(GetTime(index, kpidMTime, MTime, MTimeDefined));
// printf("\n%S", _extractedFolderPaths[pairIndex]);
SetDirTime(_extractedFolderPaths[pairIndex],
(WriteCTime && CTimeDefined) ? &CTime : NULL,
(WriteATime && ATimeDefined) ? &ATime : NULL,
(WriteMTime && MTimeDefined) ? &MTime : (_arc->MTimeDefined ? &_arc->MTime : NULL));
_extractedFolders[pairs[i].Index].SetDirTime();
// if (!) return GetLastError();
}
ClearExtractedDirsInfo();

View File

@@ -151,6 +151,25 @@ struct CIndexToPathPair
#endif
struct CDirPathTime
{
FILETIME CTime;
FILETIME ATime;
FILETIME MTime;
bool CTimeDefined;
bool ATimeDefined;
bool MTimeDefined;
FString Path;
bool SetDirTime();
};
class CArchiveExtractCallback:
public IArchiveExtractCallback,
public IArchiveExtractCallbackMessage,
@@ -241,8 +260,7 @@ class CArchiveExtractCallback:
UInt64 _progressTotal;
bool _progressTotal_Defined;
FStringVector _extractedFolderPaths;
CRecordVector<UInt32> _extractedFolderIndices;
CObjectVector<CDirPathTime> _extractedFolders;
#if defined(_WIN32) && !defined(UNDER_CE) && !defined(_SFX)
bool _saclEnabled;
@@ -348,8 +366,7 @@ public:
private:
void ClearExtractedDirsInfo()
{
_extractedFolderPaths.Clear();
_extractedFolderIndices.Clear();
_extractedFolders.Clear();
}
HRESULT CloseFile();

View File

@@ -857,7 +857,7 @@ HRESULT CArc::GetItem(UInt32 index, CReadArcItem &item) const
if (item.WriteToAltStreamIfColon || needFindAltStream)
{
/* Good handler must support GetRawProps::GetParent for alt streams./
/* Good handler must support GetRawProps::GetParent for alt streams.
So the following code currently is not used */
int colon = FindAltStreamColon_in_Path(item.Path);
if (colon >= 0)

View File

@@ -414,4 +414,23 @@ struct CArchiveLink
bool ParseOpenTypes(CCodecs &codecs, const UString &s, CObjectVector<COpenType> &types);
struct CDirPathSortPair
{
unsigned Len;
unsigned Index;
void SetNumSlashes(const FChar *s);
int Compare(const CDirPathSortPair &a) const
{
// We need sorting order where parent items will be after child items
if (Len < a.Len) return 1;
if (Len > a.Len) return -1;
if (Index < a.Index) return -1;
if (Index > a.Index) return 1;
return 0;
}
};
#endif

View File

@@ -1046,32 +1046,6 @@ static HRESULT EnumerateInArchiveItems(
#endif
struct CRefSortPair
{
unsigned Len;
unsigned Index;
};
#define RINOZ(x) { int __tt = (x); if (__tt != 0) return __tt; }
static int CompareRefSortPair(const CRefSortPair *a1, const CRefSortPair *a2, void *)
{
RINOZ(-MyCompare(a1->Len, a2->Len));
return MyCompare(a1->Index, a2->Index);
}
static unsigned GetNumSlashes(const FChar *s)
{
for (unsigned numSlashes = 0;;)
{
FChar c = *s++;
if (c == 0)
return numSlashes;
if (IS_PATH_SEPAR(c))
numSlashes++;
}
}
#ifdef _WIN32
void ConvertToLongNames(NWildcard::CCensor &censor);
#endif
@@ -1190,6 +1164,16 @@ HRESULT UpdateArchive(
throw "there is no such archive";
if (fi.IsDevice)
return E_NOTIMPL;
if (!options.StdOutMode && options.UpdateArchiveItself)
if (fi.IsReadOnly())
{
errorInfo.SystemError = ERROR_ACCESS_DENIED;
errorInfo.Message = "The file is read-only";
errorInfo.FileNames.Add(arcPath);
return errorInfo.Get_HRESULT_Error();
}
if (options.VolumesSizes.Size() > 0)
{
errorInfo.FileNames.Add(us2fs(arcPath));
@@ -1510,9 +1494,13 @@ HRESULT UpdateArchive(
CArchivePath &ap = options.Commands[0].ArchivePath;
const FString &tempPath = ap.GetTempPath();
// DWORD attrib = 0;
if (thereIsInArchive)
{
// attrib = NFind::GetFileAttrib(us2fs(arcPath));
if (!DeleteFileAlways(us2fs(arcPath)))
return errorInfo.SetFromLastError("cannot delete the file", us2fs(arcPath));
}
if (!MyMoveFile(tempPath, us2fs(arcPath)))
{
@@ -1520,6 +1508,15 @@ HRESULT UpdateArchive(
errorInfo.FileNames.Add(us2fs(arcPath));
return errorInfo.Get_HRESULT_Error();
}
/*
if (attrib != INVALID_FILE_ATTRIBUTES && (attrib & FILE_ATTRIBUTE_READONLY))
{
DWORD attrib2 = NFind::GetFileAttrib(us2fs(arcPath));
if (attrib2 != INVALID_FILE_ATTRIBUTES)
NDir::SetFileAttrib(us2fs(arcPath), attrib2 | FILE_ATTRIBUTE_READONLY);
}
*/
}
catch(...)
{
@@ -1609,7 +1606,7 @@ HRESULT UpdateArchive(
if (options.DeleteAfterCompressing)
{
CRecordVector<CRefSortPair> pairs;
CRecordVector<CDirPathSortPair> pairs;
FStringVector foldersNames;
unsigned i;
@@ -1617,12 +1614,12 @@ HRESULT UpdateArchive(
for (i = 0; i < dirItems.Items.Size(); i++)
{
const CDirItem &dirItem = dirItems.Items[i];
FString phyPath = dirItems.GetPhyPath(i);
const FString phyPath = dirItems.GetPhyPath(i);
if (dirItem.IsDir())
{
CRefSortPair pair;
CDirPathSortPair pair;
pair.Index = i;
pair.Len = GetNumSlashes(phyPath);
pair.SetNumSlashes(phyPath);
pairs.Add(pair);
}
else
@@ -1655,11 +1652,11 @@ HRESULT UpdateArchive(
}
}
pairs.Sort(CompareRefSortPair, NULL);
pairs.Sort2();
for (i = 0; i < pairs.Size(); i++)
{
FString phyPath = dirItems.GetPhyPath(pairs[i].Index);
const FString phyPath = dirItems.GetPhyPath(pairs[i].Index);
if (NFind::DoesDirExist(phyPath))
{
RINOK(callback->DeletingAfterArchiving(phyPath, true));