file_lock_win.cpp 1.9 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889
  1. // This file is part of Desktop App Toolkit,
  2. // a set of libraries for developing nice desktop applications.
  3. //
  4. // For license and copyright information please follow this link:
  5. // https://github.com/desktop-app/legal/blob/master/LEGAL
  6. //
  7. #include "base/file_lock.h"
  8. #include "base/platform/win/base_file_utilities_win.h"
  9. #include <QtCore/QDir>
  10. #include <windows.h>
  11. #include <io.h>
  12. #include <fileapi.h>
  13. namespace base {
  14. class FileLock::Lock {
  15. public:
  16. static int Acquire(const QFile &file);
  17. explicit Lock(int descriptor);
  18. ~Lock();
  19. private:
  20. static constexpr auto offsetLow = DWORD(kLockOffset);
  21. static constexpr auto offsetHigh = DWORD(0);
  22. static constexpr auto limitLow = DWORD(kLockLimit);
  23. static constexpr auto limitHigh = DWORD(0);
  24. int _descriptor = 0;
  25. };
  26. int FileLock::Lock::Acquire(const QFile &file) {
  27. const auto descriptor = file.handle();
  28. if (!descriptor || !file.isOpen()) {
  29. return false;
  30. }
  31. const auto handle = HANDLE(_get_osfhandle(descriptor));
  32. if (!handle) {
  33. return false;
  34. }
  35. return LockFile(handle, offsetLow, offsetHigh, limitLow, limitHigh)
  36. ? descriptor
  37. : 0;
  38. }
  39. FileLock::Lock::Lock(int descriptor) : _descriptor(descriptor) {
  40. }
  41. FileLock::Lock::~Lock() {
  42. if (const auto handle = HANDLE(_get_osfhandle(_descriptor))) {
  43. UnlockFile(handle, offsetLow, offsetHigh, limitLow, limitHigh);
  44. }
  45. }
  46. FileLock::FileLock() = default;
  47. bool FileLock::lock(QFile &file, QIODevice::OpenMode mode) {
  48. Expects(_lock == nullptr || file.isOpen());
  49. unlock();
  50. file.close();
  51. do {
  52. if (!file.open(mode)) {
  53. return false;
  54. } else if (const auto descriptor = Lock::Acquire(file)) {
  55. _lock = std::make_unique<Lock>(descriptor);
  56. return true;
  57. }
  58. file.close();
  59. } while (Platform::CloseProcesses(file.fileName()));
  60. return false;
  61. }
  62. bool FileLock::locked() const {
  63. return (_lock != nullptr);
  64. }
  65. void FileLock::unlock() {
  66. _lock = nullptr;
  67. }
  68. FileLock::~FileLock() = default;
  69. } // namespace base