From 59de6f8d99f07888c199b466dff9ff020e60dab6 Mon Sep 17 00:00:00 2001 From: stoffu Date: Thu, 21 Jun 2018 17:19:16 +0900 Subject: [PATCH] util: add file_locker class --- src/common/util.cpp | 67 +++++++++++++++++++++++++++++++++++++++++++++ src/common/util.h | 14 ++++++++++ 2 files changed, 81 insertions(+) diff --git a/src/common/util.cpp b/src/common/util.cpp index 97c61a174..eed6fd8d2 100644 --- a/src/common/util.cpp +++ b/src/common/util.cpp @@ -195,6 +195,73 @@ namespace tools catch (...) {} } + file_locker::file_locker(const std::string &filename) + { +#ifdef WIN32 + m_fd = INVALID_HANDLE_VALUE; + std::wstring filename_wide; + try + { + filename_wide = string_tools::utf8_to_utf16(filename); + } + catch (const std::exception &e) + { + MERROR("Failed to convert path \"" << filename << "\" to UTF-16: " << e.what()); + return; + } + m_fd = CreateFileW(filename_wide.c_str(), GENERIC_READ, 0, NULL, OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL); + if (m_fd != INVALID_HANDLE_VALUE) + { + OVERLAPPED ov; + memset(&ov, 0, sizeof(ov)); + if (!LockFileEx(m_fd, LOCKFILE_FAIL_IMMEDIATELY | LOCKFILE_EXCLUSIVE_LOCK, 0, 1, 0, &ov)) + { + MERROR("Failed to lock " << filename << ": " << std::error_code(GetLastError(), std::system_category())); + CloseHandle(m_fd); + m_fd = INVALID_HANDLE_VALUE; + } + } + else + { + MERROR("Failed to open " << filename << ": " << std::error_code(GetLastError(), std::system_category())); + } +#else + m_fd = open(filename, O_RDONLY | O_CREAT, 0666); + if (m_fd != -1) + { + if (flock(m_fd, LOCK_EX | LOCK_NB) == -1) + { + MERROR("Failed to lock " << filename << ": " << std::strerr(errno)); + close(m_fd); + m_fd = -1; + } + } + else + { + MERROR("Failed to open " << filename << ": " << std::strerr(errno)); + } +#endif + } + file_locker::~file_locker() + { + if (locked()) + { +#ifdef WIN32 + CloseHandle(m_fd); +#else + close(m_fd); +#endif + } + } + bool file_locker::locked() const + { +#ifdef WIN32 + return m_fd != INVALID_HANDLE_VALUE; +#else + return m_fd != -1; +#endif + } + #ifdef WIN32 std::string get_windows_version_display_string() { diff --git a/src/common/util.h b/src/common/util.h index dc426830b..a57a85fee 100644 --- a/src/common/util.h +++ b/src/common/util.h @@ -91,6 +91,20 @@ namespace tools const std::string& filename() const noexcept { return m_filename; } }; + class file_locker + { + public: + file_locker(const std::string &filename); + ~file_locker(); + bool locked() const; + private: +#ifdef WIN32 + HANDLE m_fd; +#else + int m_fd; +#endif + }; + /*! \brief Returns the default data directory. * * \details Windows < Vista: C:\\Documents and Settings\\Username\\Application Data\\CRYPTONOTE_NAME