aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorstoffu <stoffu@protonmail.ch>2018-06-21 17:19:16 +0900
committerstoffu <stoffu@protonmail.ch>2018-06-28 09:40:31 +0900
commit59de6f8d99f07888c199b466dff9ff020e60dab6 (patch)
tree15e136f2cbeadda054ca14e6514bd0d8ccb5cd4e /src
parentepee.string_tools: add conversion between UTF-8 and UTF-16 (diff)
downloadmonero-59de6f8d99f07888c199b466dff9ff020e60dab6.tar.xz
util: add file_locker class
Diffstat (limited to 'src')
-rw-r--r--src/common/util.cpp67
-rw-r--r--src/common/util.h14
2 files changed, 81 insertions, 0 deletions
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