Compare commits
11 Commits
0e0eb9e729
...
cf901b11b0
Author | SHA1 | Date | |
---|---|---|---|
cf901b11b0 | |||
08a3b63fbe | |||
e8a2731bba | |||
9a9986afe7 | |||
0a0edb76f0 | |||
c172b3c83e | |||
613c501911 | |||
124f17b084 | |||
ad7a557601 | |||
e82fc08365 | |||
dc3bb025bf |
@ -115,6 +115,7 @@ googletest
|
|||||||
gpath
|
gpath
|
||||||
gtest_version
|
gtest_version
|
||||||
has_setxattr
|
has_setxattr
|
||||||
|
hkey
|
||||||
httpapi
|
httpapi
|
||||||
httplib
|
httplib
|
||||||
icudata
|
icudata
|
||||||
@ -144,6 +145,7 @@ libuuid_include_dirs
|
|||||||
libvlc
|
libvlc
|
||||||
linkflags
|
linkflags
|
||||||
localappdata
|
localappdata
|
||||||
|
lpbyte
|
||||||
lptr
|
lptr
|
||||||
lpwstr
|
lpwstr
|
||||||
markdownlint
|
markdownlint
|
||||||
|
@ -22,6 +22,13 @@
|
|||||||
#ifndef REPERTORY_INCLUDE_PLATFORM_PLATFORM_HPP_
|
#ifndef REPERTORY_INCLUDE_PLATFORM_PLATFORM_HPP_
|
||||||
#define REPERTORY_INCLUDE_PLATFORM_PLATFORM_HPP_
|
#define REPERTORY_INCLUDE_PLATFORM_PLATFORM_HPP_
|
||||||
|
|
||||||
|
#include "types/repertory.hpp"
|
||||||
|
|
||||||
|
namespace repertory {
|
||||||
|
[[nodiscard]] auto create_lock_id(provider_type prov,
|
||||||
|
std::string_view unique_id);
|
||||||
|
}
|
||||||
|
|
||||||
#if defined(_WIN32)
|
#if defined(_WIN32)
|
||||||
#include "platform/win32_platform.hpp"
|
#include "platform/win32_platform.hpp"
|
||||||
#include "utils/windows.hpp"
|
#include "utils/windows.hpp"
|
||||||
|
@ -30,7 +30,7 @@ class i_provider;
|
|||||||
|
|
||||||
class lock_data final {
|
class lock_data final {
|
||||||
public:
|
public:
|
||||||
explicit lock_data(const provider_type &prov, std::string unique_id /*= ""*/);
|
explicit lock_data(const provider_type &prov, std::string unique_id);
|
||||||
|
|
||||||
lock_data(const lock_data &) = delete;
|
lock_data(const lock_data &) = delete;
|
||||||
lock_data(lock_data &&) = delete;
|
lock_data(lock_data &&) = delete;
|
||||||
@ -41,8 +41,6 @@ public:
|
|||||||
~lock_data();
|
~lock_data();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
provider_type prov_;
|
|
||||||
std::string unique_id_;
|
|
||||||
std::string mutex_id_;
|
std::string mutex_id_;
|
||||||
int lock_fd_;
|
int lock_fd_;
|
||||||
int lock_status_{EWOULDBLOCK};
|
int lock_status_{EWOULDBLOCK};
|
||||||
@ -62,12 +60,12 @@ private:
|
|||||||
public:
|
public:
|
||||||
[[nodiscard]] auto get_mount_state(json &mount_state) -> bool;
|
[[nodiscard]] auto get_mount_state(json &mount_state) -> bool;
|
||||||
|
|
||||||
[[nodiscard]] auto grab_lock(std::uint8_t retry_count = 30u) -> lock_result;
|
[[nodiscard]] auto grab_lock(std::uint8_t retry_count = 30U) -> lock_result;
|
||||||
|
|
||||||
void release();
|
void release();
|
||||||
|
|
||||||
[[nodiscard]] auto set_mount_state(bool active,
|
[[nodiscard]] auto set_mount_state(bool active,
|
||||||
const std::string &mount_location, int pid)
|
std::string_view mount_location, int pid)
|
||||||
-> bool;
|
-> bool;
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -83,5 +81,5 @@ public:
|
|||||||
const api_file &file) -> api_error;
|
const api_file &file) -> api_error;
|
||||||
} // namespace repertory
|
} // namespace repertory
|
||||||
|
|
||||||
#endif // _WIN32
|
#endif // !defined(_WIN32)
|
||||||
#endif // REPERTORY_INCLUDE_PLATFORM_UNIXPLATFORM_HPP_
|
#endif // REPERTORY_INCLUDE_PLATFORM_UNIXPLATFORM_HPP_
|
||||||
|
@ -23,7 +23,6 @@
|
|||||||
#define REPERTORY_INCLUDE_PLATFORM_WINPLATFORM_HPP_
|
#define REPERTORY_INCLUDE_PLATFORM_WINPLATFORM_HPP_
|
||||||
#if defined(_WIN32)
|
#if defined(_WIN32)
|
||||||
|
|
||||||
#include "app_config.hpp"
|
|
||||||
#include "types/repertory.hpp"
|
#include "types/repertory.hpp"
|
||||||
|
|
||||||
namespace repertory {
|
namespace repertory {
|
||||||
@ -31,43 +30,32 @@ class i_provider;
|
|||||||
|
|
||||||
class lock_data final {
|
class lock_data final {
|
||||||
public:
|
public:
|
||||||
explicit lock_data(const provider_type &pt, std::string unique_id /*= ""*/)
|
explicit lock_data(provider_type prov, std::string unique_id);
|
||||||
: pt_(pt),
|
lock_data(const lock_data &) = delete;
|
||||||
unique_id_(std::move(unique_id)),
|
lock_data(lock_data &&) = delete;
|
||||||
mutex_id_("repertory_" + app_config::get_provider_name(pt) + "_" +
|
|
||||||
unique_id_),
|
|
||||||
mutex_handle_(::CreateMutex(nullptr, FALSE, &mutex_id_[0u])) {}
|
|
||||||
|
|
||||||
lock_data()
|
~lock_data();
|
||||||
: pt_(provider_type::sia),
|
|
||||||
unique_id_(""),
|
|
||||||
mutex_id_(""),
|
|
||||||
mutex_handle_(INVALID_HANDLE_VALUE) {}
|
|
||||||
|
|
||||||
~lock_data() { release(); }
|
auto operator=(const lock_data &) -> lock_data & = delete;
|
||||||
|
auto operator=(lock_data &&) -> lock_data & = delete;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
const provider_type pt_;
|
std::string mutex_id_;
|
||||||
const std::string unique_id_;
|
HANDLE mutex_handle_{INVALID_HANDLE_VALUE};
|
||||||
const std::string mutex_id_;
|
DWORD mutex_state_{WAIT_FAILED};
|
||||||
HANDLE mutex_handle_;
|
|
||||||
DWORD mutex_state_ = WAIT_FAILED;
|
[[nodiscard]] auto get_current_mount_state(json &mount_state) -> bool;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
[[nodiscard]] auto get_mount_state(const provider_type &pt,
|
|
||||||
json &mount_state) -> bool;
|
|
||||||
|
|
||||||
[[nodiscard]] auto get_mount_state(json &mount_state) -> bool;
|
[[nodiscard]] auto get_mount_state(json &mount_state) -> bool;
|
||||||
|
|
||||||
[[nodiscard]] auto get_unique_id() const -> std::string { return unique_id_; }
|
[[nodiscard]] auto grab_lock(std::uint8_t retry_count = 30U) -> lock_result;
|
||||||
|
|
||||||
[[nodiscard]] auto grab_lock(std::uint8_t retry_count = 30) -> lock_result;
|
|
||||||
|
|
||||||
void release();
|
void release();
|
||||||
|
|
||||||
[[nodiscard]] auto set_mount_state(bool active,
|
[[nodiscard]] auto set_mount_state(bool active,
|
||||||
const std::string &mount_location,
|
std::string_view mount_location,
|
||||||
const std::int64_t &pid) -> bool;
|
std::int64_t pid) -> bool;
|
||||||
};
|
};
|
||||||
|
|
||||||
[[nodiscard]] auto create_meta_attributes(
|
[[nodiscard]] auto create_meta_attributes(
|
||||||
|
@ -21,7 +21,7 @@
|
|||||||
*/
|
*/
|
||||||
#if !defined(_WIN32)
|
#if !defined(_WIN32)
|
||||||
|
|
||||||
#include "platform/unix_platform.hpp"
|
#include "platform/platform.hpp"
|
||||||
|
|
||||||
#include "app_config.hpp"
|
#include "app_config.hpp"
|
||||||
#include "events/event_system.hpp"
|
#include "events/event_system.hpp"
|
||||||
@ -36,49 +36,53 @@
|
|||||||
#include "utils/unix.hpp"
|
#include "utils/unix.hpp"
|
||||||
|
|
||||||
namespace repertory {
|
namespace repertory {
|
||||||
lock_data::lock_data(const provider_type &prov, std::string unique_id /*= ""*/)
|
lock_data::lock_data(const provider_type &prov, std::string unique_id)
|
||||||
: prov_(prov),
|
: mutex_id_(create_lock_id(prov, unique_id)) {
|
||||||
unique_id_(std::move(unique_id)),
|
|
||||||
mutex_id_("repertory_" + app_config::get_provider_name(prov) + "_" +
|
|
||||||
unique_id_) {
|
|
||||||
lock_fd_ = open(get_lock_file().c_str(), O_CREAT | O_RDWR, S_IWUSR | S_IRUSR);
|
lock_fd_ = open(get_lock_file().c_str(), O_CREAT | O_RDWR, S_IWUSR | S_IRUSR);
|
||||||
}
|
}
|
||||||
|
|
||||||
lock_data::~lock_data() { release(); }
|
lock_data::~lock_data() { release(); }
|
||||||
|
|
||||||
auto lock_data::get_lock_data_file() -> std::string {
|
auto lock_data::get_lock_data_file() -> std::string {
|
||||||
const auto dir = get_state_directory();
|
auto dir = get_state_directory();
|
||||||
if (not utils::file::directory(dir).create_directory()) {
|
if (not utils::file::directory(dir).create_directory()) {
|
||||||
throw startup_exception("failed to create directory|sp|" + dir + "|err|" +
|
throw startup_exception("failed to create directory|sp|" + dir + "|err|" +
|
||||||
std::to_string(utils::get_last_error_code()));
|
std::to_string(utils::get_last_error_code()));
|
||||||
}
|
}
|
||||||
|
|
||||||
return utils::path::combine(
|
return utils::path::combine(
|
||||||
dir, {"mountstate_" + std::to_string(getuid()) + ".json"});
|
dir, {
|
||||||
|
fmt::format("{}_{}.json", mutex_id_, getuid()),
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
auto lock_data::get_lock_file() -> std::string {
|
auto lock_data::get_lock_file() -> std::string {
|
||||||
const auto dir = get_state_directory();
|
auto dir = get_state_directory();
|
||||||
if (not utils::file::directory(dir).create_directory()) {
|
if (not utils::file::directory(dir).create_directory()) {
|
||||||
throw startup_exception("failed to create directory|sp|" + dir + "|err|" +
|
throw startup_exception("failed to create directory|sp|" + dir + "|err|" +
|
||||||
std::to_string(utils::get_last_error_code()));
|
std::to_string(utils::get_last_error_code()));
|
||||||
}
|
}
|
||||||
|
|
||||||
return utils::path::combine(dir,
|
return utils::path::combine(
|
||||||
{mutex_id_ + "_" + std::to_string(getuid())});
|
dir, {
|
||||||
|
fmt::format("{}_{}.lock", mutex_id_, getuid()),
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
auto lock_data::get_mount_state(json &mount_state) -> bool {
|
auto lock_data::get_mount_state(json &mount_state) -> bool {
|
||||||
auto ret = false;
|
|
||||||
auto fd =
|
auto fd =
|
||||||
open(get_lock_data_file().c_str(), O_CREAT | O_RDWR, S_IWUSR | S_IRUSR);
|
open(get_lock_data_file().c_str(), O_CREAT | O_RDWR, S_IWUSR | S_IRUSR);
|
||||||
if (fd != -1) {
|
if (fd == -1) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto ret{false};
|
||||||
if (wait_for_lock(fd) == 0) {
|
if (wait_for_lock(fd) == 0) {
|
||||||
ret = utils::file::read_json_file(get_lock_data_file(), mount_state);
|
ret = utils::file::read_json_file(get_lock_data_file(), mount_state);
|
||||||
flock(fd, LOCK_UN);
|
flock(fd, LOCK_UN);
|
||||||
}
|
}
|
||||||
|
|
||||||
close(fd);
|
close(fd);
|
||||||
}
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -93,8 +97,6 @@ auto lock_data::get_state_directory() -> std::string {
|
|||||||
}
|
}
|
||||||
|
|
||||||
auto lock_data::grab_lock(std::uint8_t retry_count) -> lock_result {
|
auto lock_data::grab_lock(std::uint8_t retry_count) -> lock_result {
|
||||||
REPERTORY_USES_FUNCTION_NAME();
|
|
||||||
|
|
||||||
if (lock_fd_ == -1) {
|
if (lock_fd_ == -1) {
|
||||||
return lock_result::failure;
|
return lock_result::failure;
|
||||||
}
|
}
|
||||||
@ -116,7 +118,7 @@ void lock_data::release() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (lock_status_ == 0) {
|
if (lock_status_ == 0) {
|
||||||
unlink(get_lock_file().c_str());
|
utils::file::file{get_lock_file()}.delete();
|
||||||
flock(lock_fd_, LOCK_UN);
|
flock(lock_fd_, LOCK_UN);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -128,38 +130,36 @@ auto lock_data::set_mount_state(bool active, const std::string &mount_location,
|
|||||||
int pid) -> bool {
|
int pid) -> bool {
|
||||||
REPERTORY_USES_FUNCTION_NAME();
|
REPERTORY_USES_FUNCTION_NAME();
|
||||||
|
|
||||||
auto ret = false;
|
|
||||||
auto handle =
|
auto handle =
|
||||||
open(get_lock_data_file().c_str(), O_CREAT | O_RDWR, S_IWUSR | S_IRUSR);
|
open(get_lock_data_file().c_str(), O_CREAT | O_RDWR, S_IWUSR | S_IRUSR);
|
||||||
if (handle != -1) {
|
if (handle == -1) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto ret{false};
|
||||||
if (wait_for_lock(handle) == 0) {
|
if (wait_for_lock(handle) == 0) {
|
||||||
const auto mount_id =
|
|
||||||
app_config::get_provider_display_name(prov_) + unique_id_;
|
|
||||||
json mount_state;
|
json mount_state;
|
||||||
if (not utils::file::read_json_file(get_lock_data_file(), mount_state)) {
|
if (not utils::file::read_json_file(get_lock_data_file(), mount_state)) {
|
||||||
utils::error::raise_error(function_name,
|
utils::error::raise_error(function_name,
|
||||||
"failed to read mount state file|sp|" +
|
"failed to read mount state file|sp|" +
|
||||||
get_lock_file());
|
get_lock_file());
|
||||||
}
|
}
|
||||||
if ((mount_state.find(mount_id) == mount_state.end()) ||
|
if ((mount_state.find("Active") == mount_state.end()) ||
|
||||||
(mount_state[mount_id].find("Active") ==
|
(mount_state["Active"].get<bool>() != active) ||
|
||||||
mount_state[mount_id].end()) ||
|
(active &&
|
||||||
(mount_state[mount_id]["Active"].get<bool>() != active) ||
|
((mount_state.find("Location") == mount_state.end()) ||
|
||||||
(active && ((mount_state[mount_id].find("Location") ==
|
(mount_state["Location"].get<std::string>() != mount_location)))) {
|
||||||
mount_state[mount_id].end()) ||
|
if (mount_location.empty() && not active) {
|
||||||
(mount_state[mount_id]["Location"].get<std::string>() !=
|
ret = utils::file::file{get_lock_data_file()}.delete();
|
||||||
mount_location)))) {
|
} else {
|
||||||
const auto lines = utils::file::read_file_lines(get_lock_data_file());
|
ret = utils::file::write_json_file(
|
||||||
const auto txt = std::accumulate(
|
get_lock_data_file(),
|
||||||
lines.begin(), lines.end(), std::string(),
|
{
|
||||||
[](auto &&val, auto &&line) -> auto { return val + line; });
|
|
||||||
auto json_data = json::parse(txt.empty() ? "{}" : txt);
|
|
||||||
json_data[mount_id] = {
|
|
||||||
{"Active", active},
|
{"Active", active},
|
||||||
{"Location", active ? mount_location : ""},
|
{"Location", active ? mount_location : ""},
|
||||||
{"PID", active ? pid : -1},
|
{"PID", active ? pid : -1},
|
||||||
};
|
});
|
||||||
ret = utils::file::write_json_file(get_lock_data_file(), json_data);
|
}
|
||||||
} else {
|
} else {
|
||||||
ret = true;
|
ret = true;
|
||||||
}
|
}
|
||||||
@ -168,15 +168,14 @@ auto lock_data::set_mount_state(bool active, const std::string &mount_location,
|
|||||||
}
|
}
|
||||||
|
|
||||||
close(handle);
|
close(handle);
|
||||||
}
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto lock_data::wait_for_lock(int fd, std::uint8_t retry_count) -> int {
|
auto lock_data::wait_for_lock(int fd, std::uint8_t retry_count) -> int {
|
||||||
static constexpr const std::uint32_t max_sleep = 100U;
|
static constexpr const std::uint32_t max_sleep{100U};
|
||||||
|
|
||||||
auto lock_status = EWOULDBLOCK;
|
auto lock_status{EWOULDBLOCK};
|
||||||
auto remain = static_cast<std::uint32_t>(retry_count * max_sleep);
|
auto remain{static_cast<std::uint32_t>(retry_count * max_sleep)};
|
||||||
while ((remain > 0) && (lock_status == EWOULDBLOCK)) {
|
while ((remain > 0) && (lock_status == EWOULDBLOCK)) {
|
||||||
lock_status = flock(fd, LOCK_EX | LOCK_NB);
|
lock_status = flock(fd, LOCK_EX | LOCK_NB);
|
||||||
if (lock_status == -1) {
|
if (lock_status == -1) {
|
||||||
@ -227,7 +226,7 @@ auto provider_meta_handler(i_provider &provider, bool directory,
|
|||||||
const api_file &file) -> api_error {
|
const api_file &file) -> api_error {
|
||||||
REPERTORY_USES_FUNCTION_NAME();
|
REPERTORY_USES_FUNCTION_NAME();
|
||||||
|
|
||||||
const auto meta = create_meta_attributes(
|
auto meta = create_meta_attributes(
|
||||||
file.accessed_date,
|
file.accessed_date,
|
||||||
directory ? FILE_ATTRIBUTE_DIRECTORY : FILE_ATTRIBUTE_ARCHIVE,
|
directory ? FILE_ATTRIBUTE_DIRECTORY : FILE_ATTRIBUTE_ARCHIVE,
|
||||||
file.changed_date, file.creation_date, directory, getgid(), file.key,
|
file.changed_date, file.creation_date, directory, getgid(), file.key,
|
||||||
|
@ -21,136 +21,171 @@
|
|||||||
*/
|
*/
|
||||||
#if defined(_WIN32)
|
#if defined(_WIN32)
|
||||||
|
|
||||||
#include "platform/win32_platform.hpp"
|
#include "platform/platform.hpp"
|
||||||
|
|
||||||
#include "events/event_system.hpp"
|
#include "events/event_system.hpp"
|
||||||
#include "events/types/filesystem_item_added.hpp"
|
#include "events/types/filesystem_item_added.hpp"
|
||||||
#include "providers/i_provider.hpp"
|
#include "providers/i_provider.hpp"
|
||||||
|
#include "utils/config.hpp"
|
||||||
#include "utils/error_utils.hpp"
|
#include "utils/error_utils.hpp"
|
||||||
#include "utils/string.hpp"
|
#include "utils/string.hpp"
|
||||||
|
|
||||||
namespace repertory {
|
namespace repertory {
|
||||||
auto lock_data::get_mount_state(const provider_type & /*pt*/, json &mount_state)
|
lock_data::lock_data(provider_type prov, std::string unique_id)
|
||||||
-> bool {
|
: mutex_id_(create_lock_id(prov, unique_id)),
|
||||||
const auto ret = get_mount_state(mount_state);
|
mutex_handle_(::CreateMutex(nullptr, FALSE,
|
||||||
if (ret) {
|
create_lock_id(prov, unique_id).c_str())) {}
|
||||||
const auto mount_id =
|
|
||||||
app_config::get_provider_display_name(pt_) + unique_id_;
|
lock_data::~lock_data() { release(); }
|
||||||
mount_state = mount_state[mount_id].empty()
|
|
||||||
? json({{"Active", false}, {"Location", ""}, {"PID", -1}})
|
auto lock_data::get_current_mount_state(json &mount_state) -> bool {
|
||||||
: mount_state[mount_id];
|
REPERTORY_USES_FUNCTION_NAME();
|
||||||
|
|
||||||
|
HKEY key{};
|
||||||
|
if (::RegOpenKeyEx(HKEY_CURRENT_USER,
|
||||||
|
fmt::format(R"(SOFTWARE\{}\Mounts\{})",
|
||||||
|
REPERTORY_DATA_NAME, mutex_id_)
|
||||||
|
.c_str(),
|
||||||
|
0, KEY_ALL_ACCESS, &key) != ERROR_SUCCESS) {
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::string data;
|
||||||
|
DWORD data_size{};
|
||||||
|
|
||||||
|
DWORD type{REG_SZ};
|
||||||
|
::RegGetValueA(key, nullptr, nullptr, RRF_RT_REG_SZ, &type, nullptr,
|
||||||
|
&data_size);
|
||||||
|
|
||||||
|
data.resize(data_size);
|
||||||
|
auto res = ::RegGetValueA(key, nullptr, nullptr, RRF_RT_REG_SZ, &type,
|
||||||
|
data.data(), &data_size);
|
||||||
|
auto ret = res == ERROR_SUCCESS || res == ERROR_FILE_NOT_FOUND;
|
||||||
|
if (ret && data_size != 0U) {
|
||||||
|
try {
|
||||||
|
mount_state = json::parse(data);
|
||||||
|
} catch (const std::exception &e) {
|
||||||
|
utils::error::raise_error(function_name, e, "failed to read mount state");
|
||||||
|
ret = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
::RegCloseKey(key);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto lock_data::get_mount_state(json &mount_state) -> bool {
|
auto lock_data::get_mount_state(json &mount_state) -> bool {
|
||||||
HKEY key;
|
if (not get_current_mount_state(mount_state)) {
|
||||||
auto ret = !::RegCreateKeyEx(
|
return false;
|
||||||
HKEY_CURRENT_USER,
|
|
||||||
("SOFTWARE\\" + std::string{REPERTORY_DATA_NAME} + "\\Mounts").c_str(), 0,
|
|
||||||
nullptr, 0, KEY_ALL_ACCESS, nullptr, &key, nullptr);
|
|
||||||
if (ret) {
|
|
||||||
DWORD i = 0u;
|
|
||||||
DWORD data_size = 0u;
|
|
||||||
std::string name;
|
|
||||||
name.resize(32767u);
|
|
||||||
auto name_size = static_cast<DWORD>(name.size());
|
|
||||||
while (ret &&
|
|
||||||
(::RegEnumValue(key, i, &name[0], &name_size, nullptr, nullptr,
|
|
||||||
nullptr, &data_size) == ERROR_SUCCESS)) {
|
|
||||||
std::string data;
|
|
||||||
data.resize(data_size);
|
|
||||||
name_size++;
|
|
||||||
if ((ret = !::RegEnumValue(key, i++, &name[0], &name_size, nullptr,
|
|
||||||
nullptr, reinterpret_cast<LPBYTE>(&data[0]),
|
|
||||||
&data_size))) {
|
|
||||||
mount_state[name.c_str()] = json::parse(data);
|
|
||||||
name_size = static_cast<DWORD>(name.size());
|
|
||||||
data_size = 0u;
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
::RegCloseKey(key);
|
mount_state = mount_state.empty() ? json({
|
||||||
}
|
{"Active", false},
|
||||||
return ret;
|
{"Location", ""},
|
||||||
|
{"PID", -1},
|
||||||
|
})
|
||||||
|
: mount_state;
|
||||||
|
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto lock_data::grab_lock(std::uint8_t retry_count) -> lock_result {
|
auto lock_data::grab_lock(std::uint8_t retry_count) -> lock_result {
|
||||||
REPERTORY_USES_FUNCTION_NAME();
|
static constexpr const std::uint32_t max_sleep{100U};
|
||||||
|
|
||||||
auto ret = lock_result::success;
|
|
||||||
if (mutex_handle_ == INVALID_HANDLE_VALUE) {
|
if (mutex_handle_ == INVALID_HANDLE_VALUE) {
|
||||||
ret = lock_result::failure;
|
return lock_result::failure;
|
||||||
} else {
|
}
|
||||||
for (auto i = 0;
|
|
||||||
(i <= retry_count) && ((mutex_state_ = ::WaitForSingleObject(
|
for (std::uint8_t idx = 0U;
|
||||||
mutex_handle_, 100)) == WAIT_TIMEOUT);
|
(idx <= retry_count) &&
|
||||||
i++) {
|
((mutex_state_ = ::WaitForSingleObject(mutex_handle_, max_sleep)) ==
|
||||||
|
WAIT_TIMEOUT);
|
||||||
|
++idx) {
|
||||||
}
|
}
|
||||||
|
|
||||||
switch (mutex_state_) {
|
switch (mutex_state_) {
|
||||||
case WAIT_OBJECT_0:
|
case WAIT_OBJECT_0:
|
||||||
ret = lock_result::success;
|
return lock_result::success;
|
||||||
break;
|
|
||||||
|
|
||||||
case WAIT_TIMEOUT:
|
case WAIT_TIMEOUT:
|
||||||
ret = lock_result::locked;
|
return lock_result::locked;
|
||||||
break;
|
|
||||||
|
|
||||||
default:
|
default:
|
||||||
ret = lock_result::failure;
|
return lock_result::failure;
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
void lock_data::release() {
|
void lock_data::release() {
|
||||||
if (mutex_handle_ != INVALID_HANDLE_VALUE) {
|
if (mutex_handle_ == INVALID_HANDLE_VALUE) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if ((mutex_state_ == WAIT_OBJECT_0) || (mutex_state_ == WAIT_ABANDONED)) {
|
if ((mutex_state_ == WAIT_OBJECT_0) || (mutex_state_ == WAIT_ABANDONED)) {
|
||||||
|
if (mutex_state_ == WAIT_OBJECT_0) {
|
||||||
|
[[maybe_unused]] auto success{set_mount_state(false, "", -1)};
|
||||||
|
}
|
||||||
|
|
||||||
::ReleaseMutex(mutex_handle_);
|
::ReleaseMutex(mutex_handle_);
|
||||||
}
|
}
|
||||||
|
|
||||||
::CloseHandle(mutex_handle_);
|
::CloseHandle(mutex_handle_);
|
||||||
mutex_handle_ = INVALID_HANDLE_VALUE;
|
mutex_handle_ = INVALID_HANDLE_VALUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
auto lock_data::set_mount_state(bool active, std::string_view mount_location,
|
||||||
|
std::int64_t pid) -> bool {
|
||||||
|
if (mutex_handle_ == INVALID_HANDLE_VALUE) {
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto lock_data::set_mount_state(bool active, const std::string &mount_location,
|
|
||||||
const std::int64_t &pid) -> bool {
|
|
||||||
auto ret = false;
|
|
||||||
if (mutex_handle_ != INVALID_HANDLE_VALUE) {
|
|
||||||
const auto mount_id =
|
|
||||||
app_config::get_provider_display_name(pt_) + unique_id_;
|
|
||||||
json mount_state;
|
json mount_state;
|
||||||
[[maybe_unused]] auto success = get_mount_state(mount_state);
|
[[maybe_unused]] auto success{get_mount_state(mount_state)};
|
||||||
if ((mount_state.find(mount_id) == mount_state.end()) ||
|
if (not((mount_state.find("Active") == mount_state.end()) ||
|
||||||
(mount_state[mount_id].find("Active") == mount_state[mount_id].end()) ||
|
(mount_state["Active"].get<bool>() != active) ||
|
||||||
(mount_state[mount_id]["Active"].get<bool>() != active) ||
|
(active &&
|
||||||
(active && ((mount_state[mount_id].find("Location") ==
|
((mount_state.find("Location") == mount_state.end()) ||
|
||||||
mount_state[mount_id].end()) ||
|
(mount_state["Location"].get<std::string>() != mount_location))))) {
|
||||||
(mount_state[mount_id]["Location"].get<std::string>() !=
|
return true;
|
||||||
mount_location)))) {
|
|
||||||
HKEY key;
|
|
||||||
if ((ret = !::RegCreateKeyEx(
|
|
||||||
HKEY_CURRENT_USER,
|
|
||||||
("SOFTWARE\\" + std::string{REPERTORY_DATA_NAME} + "\\Mounts")
|
|
||||||
.c_str(),
|
|
||||||
0, nullptr, 0, KEY_ALL_ACCESS, nullptr, &key, nullptr))) {
|
|
||||||
const auto str = json({{"Active", active},
|
|
||||||
{"Location", active ? mount_location : ""},
|
|
||||||
{"PID", active ? pid : -1}})
|
|
||||||
.dump(0);
|
|
||||||
ret = !::RegSetValueEx(key, &mount_id[0], 0, REG_SZ,
|
|
||||||
reinterpret_cast<const BYTE *>(&str[0]),
|
|
||||||
static_cast<DWORD>(str.size()));
|
|
||||||
::RegCloseKey(key);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
ret = true;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
HKEY key{};
|
||||||
|
if (::RegCreateKeyExA(HKEY_CURRENT_USER,
|
||||||
|
fmt::format(R"(SOFTWARE\{}\Mounts\{})",
|
||||||
|
REPERTORY_DATA_NAME, mutex_id_)
|
||||||
|
.c_str(),
|
||||||
|
0, nullptr, 0, KEY_ALL_ACCESS, nullptr, &key,
|
||||||
|
nullptr) != ERROR_SUCCESS) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto ret{false};
|
||||||
|
if (mount_location.empty() && not active) {
|
||||||
|
::RegCloseKey(key);
|
||||||
|
|
||||||
|
if (::RegCreateKeyExA(
|
||||||
|
HKEY_CURRENT_USER,
|
||||||
|
fmt::format(R"(SOFTWARE\{}\Mounts)", REPERTORY_DATA_NAME).c_str(),
|
||||||
|
0, nullptr, 0, KEY_ALL_ACCESS, nullptr, &key,
|
||||||
|
nullptr) != ERROR_SUCCESS) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
ret = (::RegDeleteKeyA(key, mutex_id_.c_str()) == ERROR_SUCCESS);
|
||||||
|
} else {
|
||||||
|
auto data{
|
||||||
|
json({
|
||||||
|
{"Active", active},
|
||||||
|
{"Location", active ? mount_location : ""},
|
||||||
|
{"PID", active ? pid : -1},
|
||||||
|
})
|
||||||
|
.dump(),
|
||||||
|
};
|
||||||
|
ret = (::RegSetValueEx(key, nullptr, 0, REG_SZ,
|
||||||
|
reinterpret_cast<const BYTE *>(data.c_str()),
|
||||||
|
static_cast<DWORD>(data.size())) == ERROR_SUCCESS);
|
||||||
|
}
|
||||||
|
|
||||||
|
::RegCloseKey(key);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -201,4 +236,4 @@ auto provider_meta_handler(i_provider &provider, bool directory,
|
|||||||
}
|
}
|
||||||
} // namespace repertory
|
} // namespace repertory
|
||||||
|
|
||||||
#endif //_WIN32
|
#endif // defined(_WIN32)
|
||||||
|
31
repertory/librepertory/src/utils/platform.cpp
Normal file
31
repertory/librepertory/src/utils/platform.cpp
Normal file
@ -0,0 +1,31 @@
|
|||||||
|
/*
|
||||||
|
Copyright <2018-2025> <scott.e.graves@protonmail.com>
|
||||||
|
|
||||||
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
of this software and associated documentation files (the "Software"), to deal
|
||||||
|
in the Software without restriction, including without limitation the rights
|
||||||
|
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
copies of the Software, and to permit persons to whom the Software is
|
||||||
|
furnished to do so, subject to the following conditions:
|
||||||
|
|
||||||
|
The above copyright notice and this permission notice shall be included in all
|
||||||
|
copies or substantial portions of the Software.
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
SOFTWARE.
|
||||||
|
*/
|
||||||
|
#include "platform/platform.hpp"
|
||||||
|
|
||||||
|
#include "app_config.hpp"
|
||||||
|
|
||||||
|
namespace repertory {
|
||||||
|
auto create_lock_id(provider_type prov, std::string_view unique_id) {
|
||||||
|
return fmt::format("{}_{}_{}", REPERTORY_DATA_NAME,
|
||||||
|
app_config::get_provider_name(prov), unique_id);
|
||||||
|
}
|
||||||
|
} // namespace repertory
|
@ -428,8 +428,6 @@ void handlers::handle_get_mount_location(const httplib::Request &req,
|
|||||||
|
|
||||||
void handlers::handle_get_mount_status(const httplib::Request &req,
|
void handlers::handle_get_mount_status(const httplib::Request &req,
|
||||||
httplib::Response &res) const {
|
httplib::Response &res) const {
|
||||||
REPERTORY_USES_FUNCTION_NAME();
|
|
||||||
|
|
||||||
auto name = req.get_param_value("name");
|
auto name = req.get_param_value("name");
|
||||||
auto prov = provider_type_from_string(req.get_param_value("type"));
|
auto prov = provider_type_from_string(req.get_param_value("type"));
|
||||||
|
|
||||||
@ -438,34 +436,9 @@ void handlers::handle_get_mount_status(const httplib::Request &req,
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto status_name = app_config::get_provider_display_name(prov);
|
|
||||||
|
|
||||||
switch (prov) {
|
|
||||||
case provider_type::remote: {
|
|
||||||
auto parts = utils::string::split(name, '_', false);
|
|
||||||
status_name =
|
|
||||||
fmt::format("{}{}:{}", status_name, parts.at(0U), parts.at(1U));
|
|
||||||
} break;
|
|
||||||
|
|
||||||
case provider_type::encrypt:
|
|
||||||
case provider_type::sia:
|
|
||||||
case provider_type::s3:
|
|
||||||
status_name = fmt::format("{}{}", status_name, name);
|
|
||||||
break;
|
|
||||||
|
|
||||||
default:
|
|
||||||
throw utils::error::create_exception(function_name,
|
|
||||||
{
|
|
||||||
"provider is not supported",
|
|
||||||
provider_type_to_string(prov),
|
|
||||||
name,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
auto lines = launch_process(prov, name, {"-status"});
|
auto lines = launch_process(prov, name, {"-status"});
|
||||||
|
|
||||||
nlohmann::json result(
|
auto result = nlohmann::json::parse(utils::string::join(lines, '\n'));
|
||||||
nlohmann::json::parse(utils::string::join(lines, '\n')).at(status_name));
|
|
||||||
if (result.at("Location").get<std::string>().empty()) {
|
if (result.at("Location").get<std::string>().empty()) {
|
||||||
result.at("Location") = config_->get_mount_location(prov, name);
|
result.at("Location") = config_->get_mount_location(prov, name);
|
||||||
} else if (result.at("Active").get<bool>()) {
|
} else if (result.at("Active").get<bool>()) {
|
||||||
@ -603,7 +576,7 @@ void handlers::handle_put_set_value_by_name(const httplib::Request &req,
|
|||||||
|
|
||||||
void handlers::handle_put_settings(const httplib::Request &req,
|
void handlers::handle_put_settings(const httplib::Request &req,
|
||||||
httplib::Response &res) const {
|
httplib::Response &res) const {
|
||||||
nlohmann::json data = nlohmann::json::parse(req.get_param_value("data"));
|
auto data = nlohmann::json::parse(req.get_param_value("data"));
|
||||||
|
|
||||||
if (data.contains(JSON_API_PASSWORD)) {
|
if (data.contains(JSON_API_PASSWORD)) {
|
||||||
auto password = decrypt(data.at(JSON_API_PASSWORD).get<std::string>(),
|
auto password = decrypt(data.at(JSON_API_PASSWORD).get<std::string>(),
|
||||||
|
@ -62,13 +62,16 @@ TEST(lock_data_test, set_and_unset_mount_state) {
|
|||||||
|
|
||||||
json mount_state;
|
json mount_state;
|
||||||
EXPECT_TRUE(l.get_mount_state(mount_state));
|
EXPECT_TRUE(l.get_mount_state(mount_state));
|
||||||
|
|
||||||
EXPECT_STREQ(R"({"Active":true,"Location":"C:","PID":99})",
|
EXPECT_STREQ(R"({"Active":true,"Location":"C:","PID":99})",
|
||||||
mount_state["Sia1"].dump().c_str());
|
mount_state.dump().c_str());
|
||||||
|
|
||||||
|
EXPECT_TRUE(l2.get_mount_state(mount_state));
|
||||||
EXPECT_STREQ(R"({"Active":true,"Location":"D:","PID":97})",
|
EXPECT_STREQ(R"({"Active":true,"Location":"D:","PID":97})",
|
||||||
mount_state["Remote1"].dump().c_str());
|
mount_state.dump().c_str());
|
||||||
|
|
||||||
|
EXPECT_TRUE(l3.get_mount_state(mount_state));
|
||||||
EXPECT_STREQ(R"({"Active":true,"Location":"E:","PID":96})",
|
EXPECT_STREQ(R"({"Active":true,"Location":"E:","PID":96})",
|
||||||
mount_state["Remote2"].dump().c_str());
|
mount_state.dump().c_str());
|
||||||
|
|
||||||
EXPECT_TRUE(l.set_mount_state(false, "C:", 99));
|
EXPECT_TRUE(l.set_mount_state(false, "C:", 99));
|
||||||
EXPECT_TRUE(l2.set_mount_state(false, "D:", 98));
|
EXPECT_TRUE(l2.set_mount_state(false, "D:", 98));
|
||||||
@ -76,11 +79,15 @@ TEST(lock_data_test, set_and_unset_mount_state) {
|
|||||||
|
|
||||||
EXPECT_TRUE(l.get_mount_state(mount_state));
|
EXPECT_TRUE(l.get_mount_state(mount_state));
|
||||||
EXPECT_STREQ(R"({"Active":false,"Location":"","PID":-1})",
|
EXPECT_STREQ(R"({"Active":false,"Location":"","PID":-1})",
|
||||||
mount_state["Sia1"].dump().c_str());
|
mount_state.dump().c_str());
|
||||||
|
|
||||||
|
EXPECT_TRUE(l2.get_mount_state(mount_state));
|
||||||
EXPECT_STREQ(R"({"Active":false,"Location":"","PID":-1})",
|
EXPECT_STREQ(R"({"Active":false,"Location":"","PID":-1})",
|
||||||
mount_state["Remote1"].dump().c_str());
|
mount_state.dump().c_str());
|
||||||
|
|
||||||
|
EXPECT_TRUE(l3.get_mount_state(mount_state));
|
||||||
EXPECT_STREQ(R"({"Active":false,"Location":"","PID":-1})",
|
EXPECT_STREQ(R"({"Active":false,"Location":"","PID":-1})",
|
||||||
mount_state["Remote2"].dump().c_str());
|
mount_state.dump().c_str());
|
||||||
}
|
}
|
||||||
#else
|
#else
|
||||||
TEST(lock_data_test, set_and_unset_mount_state) {
|
TEST(lock_data_test, set_and_unset_mount_state) {
|
||||||
@ -91,14 +98,13 @@ TEST(lock_data_test, set_and_unset_mount_state) {
|
|||||||
EXPECT_TRUE(l.get_mount_state(mount_state));
|
EXPECT_TRUE(l.get_mount_state(mount_state));
|
||||||
|
|
||||||
EXPECT_STREQ(R"({"Active":true,"Location":"/mnt/1","PID":99})",
|
EXPECT_STREQ(R"({"Active":true,"Location":"/mnt/1","PID":99})",
|
||||||
mount_state["Sia1"].dump().c_str());
|
mount_state.dump().c_str());
|
||||||
|
|
||||||
EXPECT_TRUE(l.set_mount_state(false, "/mnt/1", 99));
|
EXPECT_TRUE(l.set_mount_state(false, "/mnt/1", 99));
|
||||||
|
|
||||||
EXPECT_TRUE(l.get_mount_state(mount_state));
|
EXPECT_TRUE(l.get_mount_state(mount_state));
|
||||||
|
|
||||||
EXPECT_STREQ(R"({"Active":false,"Location":"","PID":-1})",
|
EXPECT_STREQ(R"({"Active":false,"Location":"","PID":-1})",
|
||||||
mount_state["Sia1"].dump().c_str());
|
mount_state.dump().c_str());
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
} // namespace repertory
|
} // namespace repertory
|
||||||
|
Loading…
x
Reference in New Issue
Block a user