diff options
Diffstat (limited to '')
-rw-r--r-- | src/common/util.cpp | 76 |
1 files changed, 55 insertions, 21 deletions
diff --git a/src/common/util.cpp b/src/common/util.cpp index 046961b06..74a6babf1 100644 --- a/src/common/util.cpp +++ b/src/common/util.cpp @@ -39,11 +39,13 @@ using namespace epee; #include "net/http_client.h" // epee::net_utils::... #ifdef WIN32 -#include <windows.h> -#include <shlobj.h> -#include <strsafe.h> + #include <windows.h> + #include <shlobj.h> + #include <strsafe.h> #else -#include <sys/utsname.h> + #include <sys/file.h> + #include <sys/utsname.h> + #include <sys/stat.h> #endif #include <boost/filesystem.hpp> #include <boost/asio.hpp> @@ -53,7 +55,12 @@ namespace tools { std::function<void(int)> signal_handler::m_handler; - std::unique_ptr<std::FILE, tools::close_file> create_private_file(const std::string& name) + private_file::private_file() noexcept : m_handle(), m_filename() {} + + private_file::private_file(std::FILE* handle, std::string&& filename) noexcept + : m_handle(handle), m_filename(std::move(filename)) {} + + private_file private_file::create(std::string name) { #ifdef WIN32 struct close_handle @@ -70,17 +77,17 @@ namespace tools const bool fail = OpenProcessToken(GetCurrentProcess(), TOKEN_QUERY, std::addressof(temp)) == 0; process.reset(temp); if (fail) - return nullptr; + return {}; } DWORD sid_size = 0; GetTokenInformation(process.get(), TokenOwner, nullptr, 0, std::addressof(sid_size)); if (GetLastError() != ERROR_INSUFFICIENT_BUFFER) - return nullptr; + return {}; std::unique_ptr<char[]> sid{new char[sid_size]}; if (!GetTokenInformation(process.get(), TokenOwner, sid.get(), sid_size, std::addressof(sid_size))) - return nullptr; + return {}; const PSID psid = reinterpret_cast<const PTOKEN_OWNER>(sid.get())->Owner; const DWORD daclSize = @@ -88,17 +95,17 @@ namespace tools const std::unique_ptr<char[]> dacl{new char[daclSize]}; if (!InitializeAcl(reinterpret_cast<PACL>(dacl.get()), daclSize, ACL_REVISION)) - return nullptr; + return {}; if (!AddAccessAllowedAce(reinterpret_cast<PACL>(dacl.get()), ACL_REVISION, (READ_CONTROL | FILE_GENERIC_READ | DELETE), psid)) - return nullptr; + return {}; SECURITY_DESCRIPTOR descriptor{}; if (!InitializeSecurityDescriptor(std::addressof(descriptor), SECURITY_DESCRIPTOR_REVISION)) - return nullptr; + return {}; if (!SetSecurityDescriptorDacl(std::addressof(descriptor), true, reinterpret_cast<PACL>(dacl.get()), false)) - return nullptr; + return {}; SECURITY_ATTRIBUTES attributes{sizeof(SECURITY_ATTRIBUTES), std::addressof(descriptor), false}; std::unique_ptr<void, close_handle> file{ @@ -106,7 +113,7 @@ namespace tools name.c_str(), GENERIC_WRITE, FILE_SHARE_READ, std::addressof(attributes), - CREATE_NEW, FILE_ATTRIBUTE_TEMPORARY, + CREATE_NEW, (FILE_ATTRIBUTE_TEMPORARY | FILE_FLAG_DELETE_ON_CLOSE), nullptr ) }; @@ -121,22 +128,49 @@ namespace tools { _close(fd); } - return {real_file, tools::close_file{}}; + return {real_file, std::move(name)}; } } #else - const int fd = open(name.c_str(), (O_RDWR | O_EXCL | O_CREAT), S_IRUSR); - if (0 <= fd) + const int fdr = open(name.c_str(), (O_RDONLY | O_CREAT), S_IRUSR); + if (0 <= fdr) { - std::FILE* file = fdopen(fd, "w"); - if (!file) + struct stat rstats = {}; + if (fstat(fdr, std::addressof(rstats)) != 0) { - close(fd); + close(fdr); + return {}; + } + fchmod(fdr, (S_IRUSR | S_IWUSR)); + const int fdw = open(name.c_str(), O_RDWR); + fchmod(fdr, rstats.st_mode); + close(fdr); + + if (0 <= fdw) + { + struct stat wstats = {}; + if (fstat(fdw, std::addressof(wstats)) == 0 && + rstats.st_dev == wstats.st_dev && rstats.st_ino == wstats.st_ino && + flock(fdw, (LOCK_EX | LOCK_NB)) == 0 && ftruncate(fdw, 0) == 0) + { + std::FILE* file = fdopen(fdw, "w"); + if (file) return {file, std::move(name)}; + } + close(fdw); } - return {file, tools::close_file{}}; } #endif - return nullptr; + return {}; + } + + private_file::~private_file() noexcept + { + try + { + boost::system::error_code ec{}; + boost::filesystem::remove(filename(), ec); + } + catch (...) {} } #ifdef WIN32 |