util: add file_locker class

This commit is contained in:
stoffu 2018-06-21 17:19:16 +09:00
parent 1d176473e9
commit 59de6f8d99
No known key found for this signature in database
GPG key ID: 41DAB8343A9EC012
2 changed files with 81 additions and 0 deletions

View file

@ -195,6 +195,73 @@ namespace tools
catch (...) {} 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 #ifdef WIN32
std::string get_windows_version_display_string() std::string get_windows_version_display_string()
{ {

View file

@ -91,6 +91,20 @@ namespace tools
const std::string& filename() const noexcept { return m_filename; } 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. /*! \brief Returns the default data directory.
* *
* \details Windows < Vista: C:\\Documents and Settings\\Username\\Application Data\\CRYPTONOTE_NAME * \details Windows < Vista: C:\\Documents and Settings\\Username\\Application Data\\CRYPTONOTE_NAME