From cfede2f3e12c9a2ed79b451c202321e46fd6b6ca Mon Sep 17 00:00:00 2001
From: Syping <syping@syping.de>
Date: Mon, 12 Feb 2024 19:15:32 +0100
Subject: [PATCH] add Windows storage directory locking

---
 src/database_file.cpp | 23 +++++++++++++++++++----
 src/database_file.h   | 10 ++++++++--
 2 files changed, 27 insertions(+), 6 deletions(-)

diff --git a/src/database_file.cpp b/src/database_file.cpp
index fec8ca0..5f042fd 100644
--- a/src/database_file.cpp
+++ b/src/database_file.cpp
@@ -39,7 +39,7 @@ file::file(const std::filesystem::path &storage_path) : m_storagePath(storage_pa
         throw std::runtime_error("Storage directory can not be found");
     }
 
-#ifdef __unix__
+#if defined(__unix__)
     struct flock lock;
     lock.l_start = 0;
     lock.l_len = 0;
@@ -47,7 +47,7 @@ file::file(const std::filesystem::path &storage_path) : m_storagePath(storage_pa
     lock.l_type = F_WRLCK;
     lock.l_whence = SEEK_SET;
 
-    const std::string lock_file = storage_path / ".lock";
+    const std::filesystem::path lock_file = storage_path / ".lock";
     fd = open(lock_file.c_str(), O_CREAT | O_WRONLY | O_TRUNC, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
     if (fd == -1) {
         std::cerr << "[Error] Storage directory " << storage_path << " can not be locked" << std::endl;
@@ -58,14 +58,29 @@ file::file(const std::filesystem::path &storage_path) : m_storagePath(storage_pa
         std::cerr << "[Error] Storage directory " << storage_path << " can not be locked" << std::endl;
         throw std::system_error(errno, std::system_category());
     }
+#elif defined(_WIN32)
+    const std::filesystem::path lock_file = storage_path / ".lock";
+
+    fh = CreateFileW(lock_file.c_str(), GENERIC_WRITE, FILE_SHARE_READ, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_HIDDEN, NULL);
+    if (fh == INVALID_HANDLE_VALUE) {
+        std::cerr << "[Error] Storage directory " << storage_path << " can not be locked" << std::endl;
+        throw std::system_error(GetLastError(), std::system_category());
+    }
+    if (!LockFile(fh, NULL, NULL, NULL, NULL)) {
+        CloseHandle(fh);
+        std::cerr << "[Error] Storage directory " << storage_path << " can not be locked" << std::endl;
+        throw std::system_error(GetLastError(), std::system_category());
+    }
 #endif
 }
 
 file::~file()
 {
     const std::lock_guard<std::mutex> guard(m_mutex);
-#ifdef __unix__
+#if defined(__unix__)
     close(fd);
+#elif defined(_WIN32)
+    CloseHandle(fh);
 #endif
 }
 
@@ -268,7 +283,7 @@ bot::settings::channel file::get_channel(dpp::snowflake guild_id, dpp::snowflake
 
     bot::settings::channel channel;
     cache_get_channel(channel_id, &channel);
-    return std::move(channel);
+    return channel;
 }
 
 std::vector<dpp::snowflake> file::get_channels(dpp::snowflake guild_id)
diff --git a/src/database_file.h b/src/database_file.h
index ad9f2b0..167f252 100644
--- a/src/database_file.h
+++ b/src/database_file.h
@@ -21,6 +21,11 @@
 
 #include <mutex>
 #include <filesystem>
+#ifdef _WIN32
+#define VC_EXTRALEAN
+#define WIN32_LEAN_AND_MEAN
+#include <windows.h>
+#endif
 #include "database_core.h"
 
 namespace bot {
@@ -46,13 +51,14 @@ namespace bot {
 
         private:
             void cache_add_channel(dpp::snowflake guild_id, dpp::snowflake channel_id);
-            void cache_delete_channel(dpp::snowflake guild_id, dpp::snowflake channel_id);
             void cache_get_channel(dpp::snowflake channel_id, bot::settings::channel *channel);
             void cache_guild(dpp::snowflake guild_id, std::vector<dpp::snowflake> *channels);
             void list_guilds(std::vector<dpp::snowflake> *guilds);
             void sync_cache();
-#ifdef __unix__
+#if defined(__unix__)
             int fd;
+#elif defined(_WIN32)
+            HANDLE fh;
 #endif
             std::vector<bot::database::guild> m_channelCache;
             std::vector<bot::settings::guild> m_dataCache;