mirror of
https://github.com/Xevion/easy7zip.git
synced 2025-12-06 19:14:56 -06:00
18.01
This commit is contained in:
@@ -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;
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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));
|
||||
|
||||
Reference in New Issue
Block a user