forked from gentoo/gentoo
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Gentoo-Bug: https://bugs.gentoo.org/show_bug.cgi?id=564266 Package-Manager: portage-2.2.23 Signed-off-by: Justin Lecher <[email protected]>
- Loading branch information
Showing
3 changed files
with
443 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,2 +1,3 @@ | ||
DIST p7zip_15.09_src_all.tar.bz2 4048481 SHA256 8783acf747e210e00150f7311cc06c4cd8ecf7b0c27b4adf2194284cc49b4d6f SHA512 4f020b13632ef7a85aa8a98586b59bef2dde3c1cbebdbd17e01f1d09b2e13a56ecfe82546d7efc677c45df67456a71cfdb67826b53ebea4c0fb4878f20c2f6dd WHIRLPOOL 71d1cdb9b3b1208197b2c056670d057b00e9a5f80cf08b5914b5d25f2f6756d4cb53e5a000ec76b7b879f82302fca6d012a2cd397e8aa95ae4fc21fd620eb1ab | ||
DIST p7zip_9.20.1_src_all.tar.bz2 3835235 SHA256 49557e7ffca08100f9fc687f4dfc5aea703ca207640c76d9dee7b66f03cb4782 SHA512 7bb8a276aaefc4a83364e45633c48527de44c6b1205344f3356db570582f30f81d82a94938c99a7ad193587b584cc1c03219c28249de40018bdaee6c3b2a022a WHIRLPOOL cb20f37d3f796931a9b330728aa7148afe98bbf8a49bb91bfd80e4667c16416206b23bf34298e9ec37825e8b43f92a5710f0cea1f974296d5c17aa2c7b0931f3 | ||
DIST p7zip_9.38.1_src_all.tar.bz2 3917925 SHA256 fd5019109c9a1bf34ad3257d37a6853eae8151ff50345f0a3ffba7d8c5fdb995 SHA512 f524ffae54e0d9563a509cc4b243e830d882a925e682eb2e15e2d19cb72c947fddecd72c8507d6c1538b997b240b0827046fc2fb4f5e3f7d49840257c92b9c04 WHIRLPOOL 6bad1cde056ab1e8db4079c0e649665fbc7e6b9a565261188bd0acaec6c583d8bd9425cb26d39315408d0180ba0be0069a77b704633cf05ec855220cb31f1c24 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,284 @@ | ||
CPP/7zip/UI/Agent/Agent.cpp | 2 +- | ||
CPP/7zip/UI/Client7z/Client7z.cpp | 19 ++++++++++- | ||
CPP/7zip/UI/Common/ArchiveExtractCallback.cpp | 14 +++++++-- | ||
CPP/7zip/UI/Common/ArchiveExtractCallback.h | 6 +++- | ||
CPP/7zip/UI/Common/Extract.cpp | 2 +- | ||
CPP/Windows/FileDir.cpp | 45 +++++++++++++++++++++++++-- | ||
CPP/Windows/FileDir.h | 31 +++++++++++++++++- | ||
7 files changed, 109 insertions(+), 10 deletions(-) | ||
|
||
diff --git a/CPP/7zip/UI/Agent/Agent.cpp b/CPP/7zip/UI/Agent/Agent.cpp | ||
index 201e82c..b0b8316 100644 | ||
--- a/CPP/7zip/UI/Agent/Agent.cpp | ||
+++ b/CPP/7zip/UI/Agent/Agent.cpp | ||
@@ -1515,7 +1515,7 @@ STDMETHODIMP CAgentFolder::Extract(const UInt32 *indices, | ||
HRESULT result = _agentSpec->GetArchive()->Extract(&realIndices.Front(), | ||
realIndices.Size(), testMode, extractCallback); | ||
if (result == S_OK) | ||
- result = extractCallbackSpec->SetDirsTimes(); | ||
+ result = extractCallbackSpec->SetFinalAttribs(); | ||
return result; | ||
COM_TRY_END | ||
} | ||
diff --git a/CPP/7zip/UI/Client7z/Client7z.cpp b/CPP/7zip/UI/Client7z/Client7z.cpp | ||
index c6522fe..1919389 100644 | ||
--- a/CPP/7zip/UI/Client7z/Client7z.cpp | ||
+++ b/CPP/7zip/UI/Client7z/Client7z.cpp | ||
@@ -230,8 +230,11 @@ private: | ||
COutFileStream *_outFileStreamSpec; | ||
CMyComPtr<ISequentialOutStream> _outFileStream; | ||
|
||
+ CObjectVector<NWindows::NFile::NDir::CDelayedSymLink> _delayedSymLinks; | ||
+ | ||
public: | ||
void Init(IInArchive *archiveHandler, const FString &directoryPath); | ||
+ HRESULT SetFinalAttribs(); | ||
|
||
UInt64 NumErrors; | ||
bool PasswordIsDefined; | ||
@@ -449,11 +452,23 @@ STDMETHODIMP CArchiveExtractCallback::SetOperationResult(Int32 operationResult) | ||
} | ||
_outFileStream.Release(); | ||
if (_extractMode && _processedFileInfo.AttribDefined) | ||
- SetFileAttrib(_diskFilePath, _processedFileInfo.Attrib); | ||
+ SetFileAttrib(_diskFilePath, _processedFileInfo.Attrib, &_delayedSymLinks); | ||
PrintNewLine(); | ||
return S_OK; | ||
} | ||
|
||
+HRESULT CArchiveExtractCallback::SetFinalAttribs() | ||
+{ | ||
+ HRESULT result = S_OK; | ||
+ | ||
+ for (int i = 0; i != _delayedSymLinks.Size(); ++i) | ||
+ if (!_delayedSymLinks[i].Create()) | ||
+ result = E_FAIL; | ||
+ | ||
+ _delayedSymLinks.Clear(); | ||
+ | ||
+ return result; | ||
+} | ||
|
||
STDMETHODIMP CArchiveExtractCallback::CryptoGetTextPassword(BSTR *password) | ||
{ | ||
@@ -914,6 +929,8 @@ int MY_CDECL main(int numArgs, const char *args[]) | ||
// extractCallbackSpec->PasswordIsDefined = true; | ||
// extractCallbackSpec->Password = L"1"; | ||
HRESULT result = archive->Extract(NULL, (UInt32)(Int32)(-1), false, extractCallback); | ||
+ if (result == S_OK) | ||
+ result = extractCallbackSpec->SetFinalAttribs(); | ||
if (result != S_OK) | ||
{ | ||
PrintError("Extract Error"); | ||
diff --git a/CPP/7zip/UI/Common/ArchiveExtractCallback.cpp b/CPP/7zip/UI/Common/ArchiveExtractCallback.cpp | ||
index 877326b..05b13f3 100644 | ||
--- a/CPP/7zip/UI/Common/ArchiveExtractCallback.cpp | ||
+++ b/CPP/7zip/UI/Common/ArchiveExtractCallback.cpp | ||
@@ -1502,7 +1502,7 @@ STDMETHODIMP CArchiveExtractCallback::SetOperationResult(Int32 opRes) | ||
NumFiles++; | ||
|
||
if (!_stdOutMode && _extractMode && _fi.AttribDefined) | ||
- SetFileAttrib(_diskFilePath, _fi.Attrib); | ||
+ SetFileAttrib(_diskFilePath, _fi.Attrib, &_delayedSymLinks); | ||
|
||
RINOK(_extractCallback2->SetOperationResult(opRes, BoolToInt(_encrypted))); | ||
|
||
@@ -1584,8 +1584,9 @@ static unsigned GetNumSlashes(const FChar *s) | ||
} | ||
} | ||
|
||
-HRESULT CArchiveExtractCallback::SetDirsTimes() | ||
+HRESULT CArchiveExtractCallback::SetFinalAttribs() | ||
{ | ||
+ HRESULT result = S_OK; | ||
CRecordVector<CExtrRefSortPair> pairs; | ||
pairs.ClearAndSetSize(_extractedFolderPaths.Size()); | ||
unsigned i; | ||
@@ -1622,5 +1623,12 @@ HRESULT CArchiveExtractCallback::SetDirsTimes() | ||
(WriteATime && ATimeDefined) ? &ATime : NULL, | ||
(WriteMTime && MTimeDefined) ? &MTime : (_arc->MTimeDefined ? &_arc->MTime : NULL)); | ||
} | ||
- return S_OK; | ||
+ | ||
+ for (int i = 0; i != _delayedSymLinks.Size(); ++i) | ||
+ if (!_delayedSymLinks[i].Create()) | ||
+ result = E_FAIL; | ||
+ | ||
+ _delayedSymLinks.Clear(); | ||
+ | ||
+ return result; | ||
} | ||
diff --git a/CPP/7zip/UI/Common/ArchiveExtractCallback.h b/CPP/7zip/UI/Common/ArchiveExtractCallback.h | ||
index 1e9f0b6..b51d78f 100644 | ||
--- a/CPP/7zip/UI/Common/ArchiveExtractCallback.h | ||
+++ b/CPP/7zip/UI/Common/ArchiveExtractCallback.h | ||
@@ -6,6 +6,8 @@ | ||
#include "../../../Common/MyCom.h" | ||
#include "../../../Common/Wildcard.h" | ||
|
||
+#include "../../../Windows/FileDir.h" | ||
+ | ||
#include "../../IPassword.h" | ||
|
||
#include "../../Common/FileStreams.h" | ||
@@ -237,6 +239,8 @@ class CArchiveExtractCallback: | ||
bool _saclEnabled; | ||
#endif | ||
|
||
+ CObjectVector<NWindows::NFile::NDir::CDelayedSymLink> _delayedSymLinks; | ||
+ | ||
void CreateComplexDirectory(const UStringVector &dirPathParts, FString &fullPath); | ||
HRESULT GetTime(int index, PROPID propID, FILETIME &filetime, bool &filetimeIsDefined); | ||
HRESULT GetUnpackSize(); | ||
@@ -330,7 +334,7 @@ public: | ||
} | ||
#endif | ||
|
||
- HRESULT SetDirsTimes(); | ||
+ HRESULT SetFinalAttribs(); | ||
}; | ||
|
||
bool CensorNode_CheckPath(const NWildcard::CCensorNode &node, const CReadArcItem &item); | ||
diff --git a/CPP/7zip/UI/Common/Extract.cpp b/CPP/7zip/UI/Common/Extract.cpp | ||
index 5b96071..98192fa 100644 | ||
--- a/CPP/7zip/UI/Common/Extract.cpp | ||
+++ b/CPP/7zip/UI/Common/Extract.cpp | ||
@@ -207,7 +207,7 @@ static HRESULT DecompressArchive( | ||
else | ||
result = archive->Extract(&realIndices.Front(), realIndices.Size(), testMode, ecs); | ||
if (result == S_OK && !options.StdInMode) | ||
- result = ecs->SetDirsTimes(); | ||
+ result = ecs->SetFinalAttribs(); | ||
return callback->ExtractResult(result); | ||
} | ||
|
||
diff --git a/CPP/Windows/FileDir.cpp b/CPP/Windows/FileDir.cpp | ||
index 422edfc..baa6255 100644 | ||
--- a/CPP/Windows/FileDir.cpp | ||
+++ b/CPP/Windows/FileDir.cpp | ||
@@ -347,7 +347,8 @@ static int convert_to_symlink(const char * name) { | ||
return -1; | ||
} | ||
|
||
-bool SetFileAttrib(CFSTR fileName, DWORD fileAttributes) | ||
+bool SetFileAttrib(CFSTR fileName, DWORD fileAttributes, | ||
+ CObjectVector<CDelayedSymLink> *delayedSymLinks) | ||
{ | ||
if (!fileName) { | ||
SetLastError(ERROR_PATH_NOT_FOUND); | ||
@@ -379,7 +380,9 @@ bool SetFileAttrib(CFSTR fileName, DWORD fileAttributes) | ||
stat_info.st_mode = fileAttributes >> 16; | ||
#ifdef ENV_HAVE_LSTAT | ||
if (S_ISLNK(stat_info.st_mode)) { | ||
- if ( convert_to_symlink(name) != 0) { | ||
+ if (delayedSymLinks) | ||
+ delayedSymLinks->Add(CDelayedSymLink(name)); | ||
+ else if ( convert_to_symlink(name) != 0) { | ||
TRACEN((printf("SetFileAttrib(%s,%d) : false-3\n",(const char *)name,fileAttributes))) | ||
return false; | ||
} | ||
@@ -814,6 +817,44 @@ bool CTempDir::Remove() | ||
return !_mustBeDeleted; | ||
} | ||
|
||
+#ifdef ENV_UNIX | ||
+ | ||
+CDelayedSymLink::CDelayedSymLink(const char * source) | ||
+ : _source(source) | ||
+{ | ||
+ struct stat st; | ||
+ | ||
+ if (lstat(_source, &st) == 0) { | ||
+ _dev = st.st_dev; | ||
+ _ino = st.st_ino; | ||
+ } else { | ||
+ _dev = 0; | ||
+ } | ||
+} | ||
+ | ||
+bool CDelayedSymLink::Create() | ||
+{ | ||
+ struct stat st; | ||
+ | ||
+ if (_dev == 0) { | ||
+ errno = EPERM; | ||
+ return false; | ||
+ } | ||
+ if (lstat(_source, &st) != 0) | ||
+ return false; | ||
+ if (_dev != st.st_dev || _ino != st.st_ino) { | ||
+ // Placeholder file has been overwritten or moved by another | ||
+ // symbolic link creation | ||
+ errno = EPERM; | ||
+ return false; | ||
+ } | ||
+ | ||
+ return convert_to_symlink(_source) == 0; | ||
+} | ||
+ | ||
+#endif // ENV_UNIX | ||
+ | ||
+ | ||
}}} | ||
|
||
#ifndef _SFX | ||
diff --git a/CPP/Windows/FileDir.h b/CPP/Windows/FileDir.h | ||
index b13d1cc..7429a81 100644 | ||
--- a/CPP/Windows/FileDir.h | ||
+++ b/CPP/Windows/FileDir.h | ||
@@ -4,6 +4,7 @@ | ||
#define __WINDOWS_FILE_DIR_H | ||
|
||
#include "../Common/MyString.h" | ||
+#include "../Common/MyVector.h" | ||
|
||
#include "FileIO.h" | ||
|
||
@@ -11,11 +12,14 @@ namespace NWindows { | ||
namespace NFile { | ||
namespace NDir { | ||
|
||
+class CDelayedSymLink; | ||
+ | ||
bool GetWindowsDir(FString &path); | ||
bool GetSystemDir(FString &path); | ||
|
||
bool SetDirTime(CFSTR path, const FILETIME *cTime, const FILETIME *aTime, const FILETIME *mTime); | ||
-bool SetFileAttrib(CFSTR path, DWORD attrib); | ||
+bool SetFileAttrib(CFSTR path, DWORD attrib, | ||
+ CObjectVector<CDelayedSymLink> *delayedSymLinks = 0); | ||
bool MyMoveFile(CFSTR existFileName, CFSTR newFileName); | ||
|
||
#ifndef UNDER_CE | ||
@@ -76,6 +80,31 @@ public: | ||
bool Remove(); | ||
}; | ||
|
||
+// Symbolic links must be created last so that they can't be used to | ||
+// create or overwrite files above the extraction directory. | ||
+class CDelayedSymLink | ||
+{ | ||
+#ifdef ENV_UNIX | ||
+ // Where the symlink should be created. The target is specified in | ||
+ // the placeholder file. | ||
+ AString _source; | ||
+ | ||
+ // Device and inode of the placeholder file. Before creating the | ||
+ // symlink, we must check that these haven't been changed by creation | ||
+ // of another symlink. | ||
+ dev_t _dev; | ||
+ ino_t _ino; | ||
+ | ||
+public: | ||
+ explicit CDelayedSymLink(const char * source); | ||
+ bool Create(); | ||
+#else // !ENV_UNIX | ||
+public: | ||
+ CDelayedSymLink(const char * source) {} | ||
+ bool Create() { return true; } | ||
+#endif // ENV_UNIX | ||
+}; | ||
+ | ||
#if !defined(UNDER_CE) | ||
class CCurrentDirRestorer | ||
{ |
Oops, something went wrong.