revert
This commit is contained in:
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
Copyright <2018-2023> <scott.e.graves@protonmail.com>
|
||||
Copyright <2018-2024> <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
|
||||
@@ -28,52 +28,73 @@
|
||||
#include "utils/unix/unix_utils.hpp"
|
||||
#include "utils/utils.hpp"
|
||||
|
||||
namespace {
|
||||
constexpr const auto default_api_auth_size = 48U;
|
||||
constexpr const auto default_download_timeout_ces = 30U;
|
||||
constexpr const auto default_eviction_delay_mins = 10U;
|
||||
constexpr const auto default_high_freq_interval_secs = 30U;
|
||||
constexpr const auto default_low_freq_interval_secs = 60U * 60U;
|
||||
constexpr const auto default_max_cache_size_bytes =
|
||||
20ULL * 1024ULL * 1024ULL * 1024ULL;
|
||||
constexpr const auto default_max_upload_count = 5U;
|
||||
constexpr const auto default_min_download_timeout_secs = 5U;
|
||||
constexpr const auto default_online_check_retry_secs = 60U;
|
||||
constexpr const auto default_orphaned_file_retention_days = 15U;
|
||||
constexpr const auto default_read_ahead_count = 4U;
|
||||
constexpr const auto default_remote_client_pool_size = 10U;
|
||||
constexpr const auto default_remote_host_name_or_ip = "";
|
||||
constexpr const auto default_remote_max_connections = 20U;
|
||||
constexpr const auto default_remote_receive_timeout_secs = 120U;
|
||||
constexpr const auto default_remote_send_timeout_secs = 30U;
|
||||
constexpr const auto default_remote_token = "";
|
||||
constexpr const auto default_retry_read_count = 6U;
|
||||
constexpr const auto default_ring_buffer_file_size = 512U;
|
||||
constexpr const auto retry_save_count = 5U;
|
||||
} // namespace
|
||||
|
||||
namespace repertory {
|
||||
app_config::app_config(const provider_type &prov,
|
||||
const std::string &data_directory)
|
||||
: prov_(prov),
|
||||
api_auth_(utils::generate_random_string(48U)),
|
||||
api_auth_(utils::generate_random_string(default_api_auth_size)),
|
||||
api_port_(default_rpc_port(prov)),
|
||||
api_user_("repertory"),
|
||||
api_user_(REPERTORY),
|
||||
config_changed_(false),
|
||||
data_directory_(data_directory.empty()
|
||||
? default_data_directory(prov)
|
||||
: utils::path::absolute(data_directory)),
|
||||
download_timeout_secs_(30),
|
||||
download_timeout_secs_(default_download_timeout_ces),
|
||||
enable_chunk_downloader_timeout_(true),
|
||||
enable_comm_duration_events_(false),
|
||||
enable_drive_events_(false),
|
||||
enable_max_cache_size_(true),
|
||||
enable_max_cache_size_(false),
|
||||
#ifdef _WIN32
|
||||
enable_mount_manager_(false),
|
||||
#endif
|
||||
enable_remote_mount_(false),
|
||||
event_level_(event_level::normal),
|
||||
eviction_delay_mins_(30),
|
||||
eviction_delay_mins_(default_eviction_delay_mins),
|
||||
eviction_uses_accessed_time_(false),
|
||||
high_freq_interval_secs_(30),
|
||||
high_freq_interval_secs_(default_high_freq_interval_secs),
|
||||
is_remote_mount_(false),
|
||||
low_freq_interval_secs_(60 * 60),
|
||||
max_cache_size_bytes_(20 * 1024 * 1024 * 1024ULL),
|
||||
max_upload_count_(5U),
|
||||
min_download_timeout_secs_(5),
|
||||
online_check_retry_secs_(60),
|
||||
orphaned_file_retention_days_(15),
|
||||
low_freq_interval_secs_(default_low_freq_interval_secs),
|
||||
max_cache_size_bytes_(default_max_cache_size_bytes),
|
||||
max_upload_count_(default_max_upload_count),
|
||||
min_download_timeout_secs_(default_min_download_timeout_secs),
|
||||
online_check_retry_secs_(default_online_check_retry_secs),
|
||||
orphaned_file_retention_days_(default_orphaned_file_retention_days),
|
||||
preferred_download_type_(
|
||||
utils::download_type_to_string(download_type::fallback)),
|
||||
read_ahead_count_(4),
|
||||
remote_client_pool_size_(10),
|
||||
remote_host_name_or_ip_(""),
|
||||
remote_max_connections_(20),
|
||||
remote_port_((prov == provider_type::sia) ? 20000
|
||||
: (prov == provider_type::s3) ? 20001
|
||||
: (prov == provider_type::encrypt) ? 20002
|
||||
: 20003),
|
||||
remote_receive_timeout_secs_(120),
|
||||
remote_send_timeout_secs_(30),
|
||||
remote_token_(""),
|
||||
retry_read_count_(6),
|
||||
ring_buffer_file_size_(512) {
|
||||
read_ahead_count_(default_read_ahead_count),
|
||||
remote_client_pool_size_(default_remote_client_pool_size),
|
||||
remote_host_name_or_ip_(default_remote_host_name_or_ip),
|
||||
remote_max_connections_(default_remote_max_connections),
|
||||
remote_port_(default_remote_port(prov)),
|
||||
remote_receive_timeout_secs_(default_remote_receive_timeout_secs),
|
||||
remote_send_timeout_secs_(default_remote_send_timeout_secs),
|
||||
remote_token_(default_remote_token),
|
||||
retry_read_count_(default_retry_read_count),
|
||||
ring_buffer_file_size_(default_ring_buffer_file_size) {
|
||||
cache_directory_ = utils::path::combine(data_directory_, {"cache"});
|
||||
log_directory_ = utils::path::combine(data_directory_, {"logs"});
|
||||
|
||||
@@ -105,16 +126,26 @@ auto app_config::get_config_file_path() const -> std::string {
|
||||
auto app_config::default_agent_name(const provider_type &prov) -> std::string {
|
||||
static const std::array<std::string,
|
||||
static_cast<std::size_t>(provider_type::unknown)>
|
||||
PROVIDER_AGENT_NAMES = {"Sia-Agent", "", "", ""};
|
||||
PROVIDER_AGENT_NAMES = {
|
||||
"Sia-Agent",
|
||||
"",
|
||||
"",
|
||||
"",
|
||||
};
|
||||
|
||||
return PROVIDER_AGENT_NAMES[static_cast<std::size_t>(prov)];
|
||||
return PROVIDER_AGENT_NAMES.at(static_cast<std::size_t>(prov));
|
||||
}
|
||||
|
||||
auto app_config::default_api_port(const provider_type &prov) -> std::uint16_t {
|
||||
static const std::array<std::uint16_t,
|
||||
static_cast<std::size_t>(provider_type::unknown)>
|
||||
PROVIDER_API_PORTS = {9980U, 0U, 0U, 0U};
|
||||
return PROVIDER_API_PORTS[static_cast<std::size_t>(prov)];
|
||||
PROVIDER_API_PORTS = {
|
||||
9980U,
|
||||
0U,
|
||||
0U,
|
||||
0U,
|
||||
};
|
||||
return PROVIDER_API_PORTS.at(static_cast<std::size_t>(prov));
|
||||
}
|
||||
|
||||
auto app_config::default_data_directory(const provider_type &prov)
|
||||
@@ -137,16 +168,28 @@ auto app_config::default_data_directory(const provider_type &prov)
|
||||
return data_directory;
|
||||
}
|
||||
|
||||
auto app_config::default_remote_port(const provider_type &prov)
|
||||
-> std::uint16_t {
|
||||
static const std::array<std::uint16_t,
|
||||
static_cast<std::size_t>(provider_type::unknown)>
|
||||
PROVIDER_REMOTE_PORTS = {
|
||||
20000U,
|
||||
20010U,
|
||||
20100U,
|
||||
20001U,
|
||||
};
|
||||
return PROVIDER_REMOTE_PORTS.at(static_cast<std::size_t>(prov));
|
||||
}
|
||||
auto app_config::default_rpc_port(const provider_type &prov) -> std::uint16_t {
|
||||
static const std::array<std::uint16_t,
|
||||
static_cast<std::size_t>(provider_type::unknown)>
|
||||
PROVIDER_RPC_PORTS = {
|
||||
11101U,
|
||||
11102U,
|
||||
11103U,
|
||||
11104U,
|
||||
10000U,
|
||||
10010U,
|
||||
10100U,
|
||||
10002U,
|
||||
};
|
||||
return PROVIDER_RPC_PORTS[static_cast<std::size_t>(prov)];
|
||||
return PROVIDER_RPC_PORTS.at(static_cast<std::size_t>(prov));
|
||||
}
|
||||
|
||||
auto app_config::get_json() const -> json {
|
||||
@@ -289,7 +332,7 @@ auto app_config::get_provider_api_password(const provider_type &prov)
|
||||
#endif
|
||||
#endif
|
||||
auto lines = utils::file::read_file_lines(api_file);
|
||||
return lines.empty() ? "" : utils::string::trim(lines[0]);
|
||||
return lines.empty() ? "" : utils::string::trim(lines[0U]);
|
||||
}
|
||||
|
||||
auto app_config::get_provider_display_name(const provider_type &prov)
|
||||
@@ -302,7 +345,7 @@ auto app_config::get_provider_display_name(const provider_type &prov)
|
||||
"S3",
|
||||
"Encrypt",
|
||||
};
|
||||
return PROVIDER_DISPLAY_NAMES[static_cast<std::size_t>(prov)];
|
||||
return PROVIDER_DISPLAY_NAMES.at(static_cast<std::size_t>(prov));
|
||||
}
|
||||
|
||||
auto app_config::get_provider_name(const provider_type &prov) -> std::string {
|
||||
@@ -314,10 +357,12 @@ auto app_config::get_provider_name(const provider_type &prov) -> std::string {
|
||||
"s3",
|
||||
"encrypt",
|
||||
};
|
||||
return PROVIDER_NAMES[static_cast<std::size_t>(prov)];
|
||||
return PROVIDER_NAMES.at(static_cast<std::size_t>(prov));
|
||||
}
|
||||
|
||||
auto app_config::get_value_by_name(const std::string &name) -> std::string {
|
||||
constexpr const auto *function_name = static_cast<const char *>(__FUNCTION__);
|
||||
|
||||
try {
|
||||
if (name == "ApiAuth") {
|
||||
return api_auth_;
|
||||
@@ -332,16 +377,16 @@ auto app_config::get_value_by_name(const std::string &name) -> std::string {
|
||||
return std::to_string(get_chunk_downloader_timeout_secs());
|
||||
}
|
||||
if (name == "EnableChunkDownloaderTimeout") {
|
||||
return std::to_string(get_enable_chunk_download_timeout());
|
||||
return utils::string::from_bool(get_enable_chunk_download_timeout());
|
||||
}
|
||||
if (name == "GetEnableCommDurationEvents") {
|
||||
return std::to_string(get_enable_comm_duration_events());
|
||||
return utils::string::from_bool(get_enable_comm_duration_events());
|
||||
}
|
||||
if (name == "EnableDriveEvents") {
|
||||
return std::to_string(get_enable_drive_events());
|
||||
return utils::string::from_bool(get_enable_drive_events());
|
||||
}
|
||||
if (name == "EnableMaxCacheSize") {
|
||||
return std::to_string(get_enable_max_cache_size());
|
||||
return utils::string::from_bool(get_enable_max_cache_size());
|
||||
#ifdef _WIN32
|
||||
}
|
||||
if (name == "EnableMountManager") {
|
||||
@@ -361,7 +406,7 @@ auto app_config::get_value_by_name(const std::string &name) -> std::string {
|
||||
return std::to_string(get_eviction_delay_mins());
|
||||
}
|
||||
if (name == "EvictionUsesAccessedTime") {
|
||||
return std::to_string(get_eviction_uses_accessed_time());
|
||||
return utils::string::from_bool(get_eviction_uses_accessed_time());
|
||||
}
|
||||
if (name == "HighFreqIntervalSeconds") {
|
||||
return std::to_string(get_high_frequency_interval_secs());
|
||||
@@ -404,10 +449,10 @@ auto app_config::get_value_by_name(const std::string &name) -> std::string {
|
||||
return std::to_string(get_read_ahead_count());
|
||||
}
|
||||
if (name == "RemoteMount.EnableRemoteMount") {
|
||||
return std::to_string(get_enable_remote_mount());
|
||||
return utils::string::from_bool(get_enable_remote_mount());
|
||||
}
|
||||
if (name == "RemoteMount.IsRemoteMount") {
|
||||
return std::to_string(get_is_remote_mount());
|
||||
return utils::string::from_bool(get_is_remote_mount());
|
||||
}
|
||||
if (name == "RemoteMount.RemoteClientPoolSize") {
|
||||
return std::to_string(get_remote_client_pool_size());
|
||||
@@ -467,12 +512,14 @@ auto app_config::get_value_by_name(const std::string &name) -> std::string {
|
||||
return std::to_string(s3_config_.timeout_ms);
|
||||
}
|
||||
} catch (const std::exception &e) {
|
||||
utils::error::raise_error(__FUNCTION__, e, "exception occurred");
|
||||
utils::error::raise_error(function_name, e, "exception occurred");
|
||||
}
|
||||
return "";
|
||||
}
|
||||
|
||||
auto app_config::load() -> bool {
|
||||
constexpr const auto *function_name = static_cast<const char *>(__FUNCTION__);
|
||||
|
||||
auto ret = false;
|
||||
|
||||
const auto config_file_path = get_config_file_path();
|
||||
@@ -485,7 +532,8 @@ auto app_config::load() -> bool {
|
||||
stream << config_file.rdbuf();
|
||||
const auto json_text = stream.str();
|
||||
config_file.close();
|
||||
if ((ret = not json_text.empty())) {
|
||||
ret = not json_text.empty();
|
||||
if (ret) {
|
||||
const auto json_document = json::parse(json_text);
|
||||
|
||||
get_value(json_document, "ApiAuth", api_auth_, ret);
|
||||
@@ -627,7 +675,7 @@ auto app_config::load() -> bool {
|
||||
config_changed_ = true;
|
||||
}
|
||||
} catch (const std::exception &ex) {
|
||||
utils::error::raise_error(__FUNCTION__, ex, "exception occurred");
|
||||
utils::error::raise_error(function_name, ex, "exception occurred");
|
||||
ret = false;
|
||||
}
|
||||
}
|
||||
@@ -636,22 +684,25 @@ auto app_config::load() -> bool {
|
||||
}
|
||||
|
||||
void app_config::save() {
|
||||
constexpr const auto *function_name = static_cast<const char *>(__FUNCTION__);
|
||||
|
||||
const auto file_path = get_config_file_path();
|
||||
recur_mutex_lock lock(read_write_mutex_);
|
||||
if (config_changed_ || not utils::file::is_file(file_path)) {
|
||||
if (not utils::file::is_directory(data_directory_)) {
|
||||
if (not utils::file::create_full_directory_path(data_directory_)) {
|
||||
utils::error::raise_error(
|
||||
__FUNCTION__, "failed to create directory|sp|" + data_directory_ +
|
||||
"|err|" +
|
||||
std::to_string(utils::get_last_error_code()));
|
||||
function_name, "failed to create directory|sp|" + data_directory_ +
|
||||
"|err|" +
|
||||
std::to_string(utils::get_last_error_code()));
|
||||
}
|
||||
}
|
||||
config_changed_ = false;
|
||||
json data = get_json();
|
||||
auto success = false;
|
||||
for (auto i = 0; not success && (i < 5); i++) {
|
||||
if (not(success = utils::file::write_json_file(file_path, data))) {
|
||||
for (auto i = 0U; not success && (i < retry_save_count); i++) {
|
||||
success = utils::file::write_json_file(file_path, data);
|
||||
if (not success) {
|
||||
std::this_thread::sleep_for(1s);
|
||||
}
|
||||
}
|
||||
@@ -680,6 +731,8 @@ void app_config::set_is_remote_mount(bool is_remote_mount) {
|
||||
|
||||
auto app_config::set_value_by_name(const std::string &name,
|
||||
const std::string &value) -> std::string {
|
||||
constexpr const auto *function_name = static_cast<const char *>(__FUNCTION__);
|
||||
|
||||
try {
|
||||
if (name == "ApiAuth") {
|
||||
set_api_auth(value);
|
||||
@@ -879,8 +932,9 @@ auto app_config::set_value_by_name(const std::string &name,
|
||||
return s3_config_.encryption_token;
|
||||
}
|
||||
} catch (const std::exception &e) {
|
||||
utils::error::raise_error(__FUNCTION__, e, "exception occurred");
|
||||
utils::error::raise_error(function_name, e, "exception occurred");
|
||||
}
|
||||
|
||||
return "";
|
||||
}
|
||||
} // namespace repertory
|
||||
|
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
Copyright <2018-2023> <scott.e.graves@protonmail.com>
|
||||
Copyright <2018-2024> <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
|
||||
@@ -154,6 +154,16 @@ auto curl_comm::make_request(const curl::requests::http_head &head,
|
||||
head, response_code, stop_requested);
|
||||
}
|
||||
|
||||
auto curl_comm::make_request(const curl::requests::http_post &post,
|
||||
long &response_code,
|
||||
stop_type &stop_requested) const -> bool {
|
||||
return make_request(
|
||||
s3_config_.has_value()
|
||||
? create_host_config(s3_config_.value(), use_s3_path_style_)
|
||||
: host_config_.value_or(host_config{}),
|
||||
post, response_code, stop_requested);
|
||||
}
|
||||
|
||||
auto curl_comm::make_request(const curl::requests::http_put_file &put_file,
|
||||
long &response_code,
|
||||
stop_type &stop_requested) const -> bool {
|
||||
|
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
Copyright <2018-2023> <scott.e.graves@protonmail.com>
|
||||
Copyright <2018-2024> <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
|
||||
|
@@ -1,45 +1,3 @@
|
||||
<<<<<<< HEAD:include/utils/rocksdb_utils.hpp
|
||||
/*
|
||||
Copyright <2018-2023> <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.
|
||||
*/
|
||||
#ifndef INCLUDE_UTILS_ROCKSDB_UTILS_HPP_
|
||||
#define INCLUDE_UTILS_ROCKSDB_UTILS_HPP_
|
||||
|
||||
namespace repertory {
|
||||
class app_config;
|
||||
|
||||
namespace utils::db {
|
||||
void create_rocksdb(const app_config &config, const std::string &name,
|
||||
std::unique_ptr<rocksdb::DB> &db);
|
||||
|
||||
void create_rocksdb(
|
||||
const app_config &config, const std::string &name,
|
||||
const std::vector<rocksdb::ColumnFamilyDescriptor> &families,
|
||||
std::vector<rocksdb::ColumnFamilyHandle *> &handles,
|
||||
std::unique_ptr<rocksdb::DB> &db);
|
||||
} // namespace utils::db
|
||||
} // namespace repertory
|
||||
|
||||
#endif // INCLUDE_UTILS_ROCKSDB_UTILS_HPP_
|
||||
=======
|
||||
/*
|
||||
Copyright <2018-2024> <scott.e.graves@protonmail.com>
|
||||
|
||||
@@ -85,4 +43,3 @@ auto http_post::set_method(CURL *curl, stop_type & /*stop_requested*/) const
|
||||
return true;
|
||||
}
|
||||
} // namespace repertory::curl::requests
|
||||
>>>>>>> 9b453327a81e182a9ec87ef1aae13169516436e0:src/comm/curl/requests/http_post.cpp
|
||||
|
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
Copyright <2018-2023> <scott.e.graves@protonmail.com>
|
||||
Copyright <2018-2024> <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
|
||||
|
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
Copyright <2018-2023> <scott.e.graves@protonmail.com>
|
||||
Copyright <2018-2024> <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
|
||||
@@ -40,6 +40,8 @@ void client_pool::pool::execute(
|
||||
}
|
||||
|
||||
client_pool::pool::pool(std::uint8_t pool_size) {
|
||||
constexpr const auto *function_name = static_cast<const char *>(__FUNCTION__);
|
||||
|
||||
event_system::instance().raise<service_started>("client_pool");
|
||||
|
||||
for (std::uint8_t i = 0U; i < pool_size; i++) {
|
||||
@@ -75,7 +77,7 @@ client_pool::pool::pool(std::uint8_t pool_size) {
|
||||
item->work_complete(result);
|
||||
} catch (const std::exception &e) {
|
||||
item->work_complete(utils::from_api_error(api_error::error));
|
||||
utils::error::raise_error(__FUNCTION__, e,
|
||||
utils::error::raise_error(function_name, e,
|
||||
"exception occurred in work item");
|
||||
}
|
||||
|
||||
|
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
Copyright <2018-2023> <scott.e.graves@protonmail.com>
|
||||
Copyright <2018-2024> <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
|
||||
@@ -219,13 +219,16 @@ auto packet::decode(remote::file_info &val) -> packet::error_type {
|
||||
}
|
||||
|
||||
auto packet::decode_json(packet &response, json &json_data) -> int {
|
||||
constexpr const auto *function_name = static_cast<const char *>(__FUNCTION__);
|
||||
|
||||
std::string data;
|
||||
auto ret = response.decode(data);
|
||||
if (ret == 0) {
|
||||
try {
|
||||
json_data = json::parse(data);
|
||||
} catch (const std::exception &e) {
|
||||
utils::error::raise_error(__FUNCTION__, e, "failed to parse json string");
|
||||
utils::error::raise_error(function_name, e,
|
||||
"failed to parse json string");
|
||||
ret = -EIO;
|
||||
}
|
||||
}
|
||||
@@ -234,6 +237,8 @@ auto packet::decode_json(packet &response, json &json_data) -> int {
|
||||
}
|
||||
|
||||
auto packet::decrypt(const std::string &token) -> packet::error_type {
|
||||
constexpr const auto *function_name = static_cast<const char *>(__FUNCTION__);
|
||||
|
||||
auto ret = utils::from_api_error(api_error::success);
|
||||
try {
|
||||
data_buffer result;
|
||||
@@ -245,7 +250,7 @@ auto packet::decrypt(const std::string &token) -> packet::error_type {
|
||||
buffer_ = std::move(result);
|
||||
decode_offset_ = 0;
|
||||
} catch (const std::exception &e) {
|
||||
utils::error::raise_error(__FUNCTION__, e, "exception occurred");
|
||||
utils::error::raise_error(function_name, e, "exception occurred");
|
||||
ret = utils::from_api_error(api_error::error);
|
||||
}
|
||||
|
||||
@@ -514,13 +519,15 @@ void packet::encode_top(remote::file_info val) {
|
||||
}
|
||||
|
||||
void packet::encrypt(const std::string &token) {
|
||||
constexpr const auto *function_name = static_cast<const char *>(__FUNCTION__);
|
||||
|
||||
try {
|
||||
data_buffer result;
|
||||
utils::encryption::encrypt_data(token, buffer_, result);
|
||||
buffer_ = std::move(result);
|
||||
encode_top(static_cast<std::uint32_t>(buffer_.size()));
|
||||
} catch (const std::exception &e) {
|
||||
utils::error::raise_error(__FUNCTION__, e, "exception occurred");
|
||||
utils::error::raise_error(function_name, e, "exception occurred");
|
||||
}
|
||||
}
|
||||
|
||||
|
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
Copyright <2018-2023> <scott.e.graves@protonmail.com>
|
||||
Copyright <2018-2024> <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
|
||||
@@ -39,9 +39,8 @@ packet_client::packet_client(std::string host_name_or_ip,
|
||||
std::uint16_t receive_timeout,
|
||||
std::uint16_t send_timeout,
|
||||
std::string encryption_token)
|
||||
: io_context_(),
|
||||
host_name_or_ip_(std::move(host_name_or_ip)),
|
||||
max_connections_(max_connections ? max_connections : 20u),
|
||||
: host_name_or_ip_(std::move(host_name_or_ip)),
|
||||
max_connections_(max_connections == 0U ? 20U : max_connections),
|
||||
port_(port),
|
||||
receive_timeout_(receive_timeout),
|
||||
send_timeout_(send_timeout),
|
||||
@@ -54,38 +53,40 @@ packet_client::~packet_client() {
|
||||
io_context_.stop();
|
||||
}
|
||||
|
||||
void packet_client::close(client &cli) const {
|
||||
void packet_client::close(client &cli) {
|
||||
try {
|
||||
boost::system::error_code ec;
|
||||
cli.socket.close(ec);
|
||||
boost::system::error_code err;
|
||||
cli.socket.close(err);
|
||||
} catch (...) {
|
||||
}
|
||||
}
|
||||
|
||||
void packet_client::close_all() {
|
||||
unique_mutex_lock clients_lock(clients_mutex_);
|
||||
for (auto &c : clients_) {
|
||||
close(*c.get());
|
||||
for (auto &cli : clients_) {
|
||||
close(*cli);
|
||||
}
|
||||
|
||||
clients_.clear();
|
||||
unique_id_ = utils::create_uuid_string();
|
||||
}
|
||||
|
||||
void packet_client::connect(client &c) {
|
||||
void packet_client::connect(client &cli) {
|
||||
constexpr const auto *function_name = static_cast<const char *>(__FUNCTION__);
|
||||
|
||||
try {
|
||||
resolve();
|
||||
boost::asio::connect(c.socket, resolve_results_);
|
||||
c.socket.set_option(boost::asio::ip::tcp::no_delay(true));
|
||||
c.socket.set_option(boost::asio::socket_base::linger(false, 0));
|
||||
boost::asio::connect(cli.socket, resolve_results_);
|
||||
cli.socket.set_option(boost::asio::ip::tcp::no_delay(true));
|
||||
cli.socket.set_option(boost::asio::socket_base::linger(false, 0));
|
||||
|
||||
packet response;
|
||||
const auto res = read_packet(c, response);
|
||||
const auto res = read_packet(cli, response);
|
||||
if (res != 0) {
|
||||
throw std::runtime_error(std::to_string(res));
|
||||
}
|
||||
} catch (const std::exception &e) {
|
||||
utils::error::raise_error(__FUNCTION__, e, "connection handshake failed");
|
||||
utils::error::raise_error(function_name, e, "connection handshake failed");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -99,7 +100,7 @@ auto packet_client::get_client() -> std::shared_ptr<packet_client::client> {
|
||||
ret = std::make_shared<client>(io_context_);
|
||||
connect(*ret);
|
||||
} else {
|
||||
ret = clients_[0u];
|
||||
ret = clients_[0U];
|
||||
utils::remove_element_from(clients_, ret);
|
||||
clients_lock.unlock();
|
||||
}
|
||||
@@ -108,21 +109,21 @@ auto packet_client::get_client() -> std::shared_ptr<packet_client::client> {
|
||||
return ret;
|
||||
}
|
||||
|
||||
void packet_client::put_client(std::shared_ptr<client> &c) {
|
||||
void packet_client::put_client(std::shared_ptr<client> &cli) {
|
||||
mutex_lock clientsLock(clients_mutex_);
|
||||
if (clients_.size() < max_connections_) {
|
||||
clients_.emplace_back(c);
|
||||
clients_.emplace_back(cli);
|
||||
}
|
||||
}
|
||||
|
||||
auto packet_client::read_packet(client &c, packet &response)
|
||||
auto packet_client::read_packet(client &cli, packet &response)
|
||||
-> packet::error_type {
|
||||
data_buffer buffer(sizeof(std::uint32_t));
|
||||
const auto read_buffer = [&]() {
|
||||
std::uint32_t offset = 0u;
|
||||
std::uint32_t offset{};
|
||||
while (offset < buffer.size()) {
|
||||
const auto bytes_read = boost::asio::read(
|
||||
c.socket,
|
||||
cli.socket,
|
||||
boost::asio::buffer(&buffer[offset], buffer.size() - offset));
|
||||
if (bytes_read <= 0) {
|
||||
throw std::runtime_error("read failed|" + std::to_string(bytes_read));
|
||||
@@ -133,7 +134,7 @@ auto packet_client::read_packet(client &c, packet &response)
|
||||
read_buffer();
|
||||
|
||||
const auto size = boost::endian::big_to_native(
|
||||
*reinterpret_cast<std::uint32_t *>(&buffer[0u]));
|
||||
*reinterpret_cast<std::uint32_t *>(buffer.data()));
|
||||
buffer.resize(size);
|
||||
|
||||
read_buffer();
|
||||
@@ -141,7 +142,7 @@ auto packet_client::read_packet(client &c, packet &response)
|
||||
|
||||
auto ret = response.decrypt(encryption_token_);
|
||||
if (ret == 0) {
|
||||
ret = response.decode(c.nonce);
|
||||
ret = response.decode(cli.nonce);
|
||||
}
|
||||
|
||||
return ret;
|
||||
@@ -169,6 +170,8 @@ auto packet_client::send(const std::string &method, packet &request,
|
||||
auto packet_client::send(const std::string &method, packet &request,
|
||||
packet &response, std::uint32_t &service_flags)
|
||||
-> packet::error_type {
|
||||
constexpr const auto *function_name = static_cast<const char *>(__FUNCTION__);
|
||||
|
||||
auto success = false;
|
||||
packet::error_type ret = utils::from_api_error(api_error::error);
|
||||
request.encode_top(method);
|
||||
@@ -177,28 +180,29 @@ auto packet_client::send(const std::string &method, packet &request,
|
||||
request.encode_top(PACKET_SERVICE_FLAGS);
|
||||
request.encode_top(get_repertory_version());
|
||||
|
||||
static const std::uint8_t max_attempts = 5u;
|
||||
for (std::uint8_t i = 1u;
|
||||
static const std::uint8_t max_attempts{5U};
|
||||
for (std::uint8_t i = 1U;
|
||||
allow_connections_ && not success && (i <= max_attempts); i++) {
|
||||
auto c = get_client();
|
||||
if (c) {
|
||||
auto current_client = get_client();
|
||||
if (current_client) {
|
||||
try {
|
||||
request.encode_top(c->nonce);
|
||||
request.encode_top(current_client->nonce);
|
||||
request.encrypt(encryption_token_);
|
||||
|
||||
timeout request_timeout(
|
||||
[this, method, c]() {
|
||||
[method, current_client]() {
|
||||
event_system::instance().raise<packet_client_timeout>("request",
|
||||
method);
|
||||
close(*c.get());
|
||||
packet_client::close(*current_client);
|
||||
},
|
||||
std::chrono::seconds(send_timeout_));
|
||||
|
||||
std::uint32_t offset = 0u;
|
||||
std::uint32_t offset{};
|
||||
while (offset < request.get_size()) {
|
||||
const auto bytes_written = boost::asio::write(
|
||||
c->socket, boost::asio::buffer(&request[offset],
|
||||
request.get_size() - offset));
|
||||
current_client->socket,
|
||||
boost::asio::buffer(&request[offset],
|
||||
request.get_size() - offset));
|
||||
if (bytes_written <= 0) {
|
||||
throw std::runtime_error("write failed|" +
|
||||
std::to_string(bytes_written));
|
||||
@@ -208,27 +212,29 @@ auto packet_client::send(const std::string &method, packet &request,
|
||||
request_timeout.disable();
|
||||
|
||||
timeout response_timeout(
|
||||
[this, method, c]() {
|
||||
[method, current_client]() {
|
||||
event_system::instance().raise<packet_client_timeout>("response",
|
||||
method);
|
||||
close(*c.get());
|
||||
packet_client::close(*current_client);
|
||||
},
|
||||
std::chrono::seconds(receive_timeout_));
|
||||
|
||||
ret = read_packet(*c, response);
|
||||
ret = read_packet(*current_client, response);
|
||||
response_timeout.disable();
|
||||
if (ret == 0) {
|
||||
if ((ret = response.decode(service_flags)) == 0) {
|
||||
ret = response.decode(service_flags);
|
||||
if (ret == 0) {
|
||||
packet::error_type res{};
|
||||
if ((ret = response.decode(res)) == 0) {
|
||||
ret = response.decode(res);
|
||||
if (ret == 0) {
|
||||
ret = res;
|
||||
success = true;
|
||||
put_client(c);
|
||||
put_client(current_client);
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch (const std::exception &e) {
|
||||
utils::error::raise_error(__FUNCTION__, e, "send failed");
|
||||
utils::error::raise_error(function_name, e, "send failed");
|
||||
close_all();
|
||||
if (allow_connections_ && (i < max_attempts)) {
|
||||
std::this_thread::sleep_for(1s);
|
||||
|
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
Copyright <2018-2023> <scott.e.graves@protonmail.com>
|
||||
Copyright <2018-2024> <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
|
||||
@@ -45,7 +45,7 @@ packet_server::packet_server(std::uint16_t port, std::string token,
|
||||
packet_server::~packet_server() {
|
||||
event_system::instance().raise<service_shutdown_begin>("packet_server");
|
||||
std::thread([this]() {
|
||||
for (std::size_t i = 0u; i < service_threads_.size(); i++) {
|
||||
for (std::size_t i = 0U; i < service_threads_.size(); i++) {
|
||||
io_context_.stop();
|
||||
}
|
||||
}).detach();
|
||||
@@ -55,19 +55,21 @@ packet_server::~packet_server() {
|
||||
event_system::instance().raise<service_shutdown_end>("packet_server");
|
||||
}
|
||||
|
||||
void packet_server::add_client(connection &c, const std::string &client_id) {
|
||||
c.client_id = client_id;
|
||||
void packet_server::add_client(connection &conn, const std::string &client_id) {
|
||||
conn.client_id = client_id;
|
||||
|
||||
recur_mutex_lock connection_lock(connection_mutex_);
|
||||
if (connection_lookup_.find(client_id) == connection_lookup_.end()) {
|
||||
connection_lookup_[client_id] = 1u;
|
||||
connection_lookup_[client_id] = 1U;
|
||||
} else {
|
||||
connection_lookup_[client_id]++;
|
||||
connection_lookup_.at(client_id)++;
|
||||
}
|
||||
}
|
||||
|
||||
void packet_server::initialize(const uint16_t &port, uint8_t pool_size) {
|
||||
pool_size = std::max(uint8_t(1u), pool_size);
|
||||
constexpr const auto *function_name = static_cast<const char *>(__FUNCTION__);
|
||||
|
||||
pool_size = std::max(uint8_t(1U), pool_size);
|
||||
server_thread_ = std::make_unique<std::thread>([this, port, pool_size]() {
|
||||
tcp::acceptor acceptor(io_context_);
|
||||
try {
|
||||
@@ -77,72 +79,79 @@ void packet_server::initialize(const uint16_t &port, uint8_t pool_size) {
|
||||
acceptor.bind(endpoint);
|
||||
acceptor.listen();
|
||||
} catch (const std::exception &e) {
|
||||
repertory::utils::error::raise_error(__FUNCTION__, e,
|
||||
repertory::utils::error::raise_error(function_name, e,
|
||||
"exception occurred");
|
||||
}
|
||||
listen_for_connection(acceptor);
|
||||
|
||||
for (std::uint8_t i = 0u; i < pool_size; i++) {
|
||||
for (std::uint8_t i = 0U; i < pool_size; i++) {
|
||||
service_threads_.emplace_back([this]() { io_context_.run(); });
|
||||
}
|
||||
|
||||
for (auto &th : service_threads_) {
|
||||
th.join();
|
||||
for (auto &thread : service_threads_) {
|
||||
thread.join();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
void packet_server::listen_for_connection(tcp::acceptor &acceptor) {
|
||||
auto c = std::make_shared<packet_server::connection>(io_context_, acceptor);
|
||||
acceptor.async_accept(c->socket,
|
||||
boost::bind(&packet_server::on_accept, this, c,
|
||||
boost::asio::placeholders::error));
|
||||
auto conn =
|
||||
std::make_shared<packet_server::connection>(io_context_, acceptor);
|
||||
acceptor.async_accept(conn->socket, [this, conn](auto &&err) {
|
||||
on_accept(conn, std::forward<decltype(err)>(err));
|
||||
});
|
||||
}
|
||||
|
||||
void packet_server::on_accept(std::shared_ptr<connection> c,
|
||||
boost::system::error_code ec) {
|
||||
listen_for_connection(c->acceptor);
|
||||
if (ec) {
|
||||
utils::error::raise_error(__FUNCTION__, ec.message());
|
||||
void packet_server::on_accept(std::shared_ptr<connection> conn,
|
||||
boost::system::error_code err) {
|
||||
constexpr const auto *function_name = static_cast<const char *>(__FUNCTION__);
|
||||
|
||||
listen_for_connection(conn->acceptor);
|
||||
if (err) {
|
||||
utils::error::raise_error(function_name, err.message());
|
||||
std::this_thread::sleep_for(1s);
|
||||
} else {
|
||||
c->socket.set_option(boost::asio::ip::tcp::no_delay(true));
|
||||
c->socket.set_option(boost::asio::socket_base::linger(false, 0));
|
||||
conn->socket.set_option(boost::asio::ip::tcp::no_delay(true));
|
||||
conn->socket.set_option(boost::asio::socket_base::linger(false, 0));
|
||||
|
||||
c->generate_nonce();
|
||||
conn->generate_nonce();
|
||||
|
||||
packet response;
|
||||
send_response(c, 0, response);
|
||||
send_response(conn, 0, response);
|
||||
}
|
||||
}
|
||||
|
||||
void packet_server::read_header(std::shared_ptr<connection> c) {
|
||||
static const std::string function_name = __FUNCTION__;
|
||||
void packet_server::read_header(std::shared_ptr<connection> conn) {
|
||||
constexpr const auto *function_name = static_cast<const char *>(__FUNCTION__);
|
||||
|
||||
c->buffer.resize(sizeof(std::uint32_t));
|
||||
conn->buffer.resize(sizeof(std::uint32_t));
|
||||
boost::asio::async_read(
|
||||
c->socket, boost::asio::buffer(&c->buffer[0u], c->buffer.size()),
|
||||
[this, c](boost::system::error_code ec, std::size_t) {
|
||||
if (ec) {
|
||||
remove_client(*c);
|
||||
repertory::utils::error::raise_error(function_name, ec.message());
|
||||
conn->socket,
|
||||
boost::asio::buffer(conn->buffer.data(), conn->buffer.size()),
|
||||
[this, conn](boost::system::error_code err, std::size_t) {
|
||||
if (err) {
|
||||
remove_client(*conn);
|
||||
repertory::utils::error::raise_error(function_name, err.message());
|
||||
} else {
|
||||
auto to_read = *reinterpret_cast<std::uint32_t *>(&c->buffer[0u]);
|
||||
auto to_read =
|
||||
*reinterpret_cast<std::uint32_t *>(conn->buffer.data());
|
||||
boost::endian::big_to_native_inplace(to_read);
|
||||
read_packet(c, to_read);
|
||||
read_packet(conn, to_read);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
void packet_server::read_packet(std::shared_ptr<connection> c,
|
||||
void packet_server::read_packet(std::shared_ptr<connection> conn,
|
||||
std::uint32_t data_size) {
|
||||
constexpr const auto *function_name = static_cast<const char *>(__FUNCTION__);
|
||||
|
||||
try {
|
||||
const auto read_buffer = [&]() {
|
||||
std::uint32_t offset = 0u;
|
||||
while (offset < c->buffer.size()) {
|
||||
std::uint32_t offset{};
|
||||
while (offset < conn->buffer.size()) {
|
||||
const auto bytes_read = boost::asio::read(
|
||||
c->socket,
|
||||
boost::asio::buffer(&c->buffer[offset], c->buffer.size() - offset));
|
||||
conn->socket, boost::asio::buffer(&conn->buffer[offset],
|
||||
conn->buffer.size() - offset));
|
||||
if (bytes_read <= 0) {
|
||||
throw std::runtime_error("read failed|" + std::to_string(bytes_read));
|
||||
}
|
||||
@@ -152,46 +161,48 @@ void packet_server::read_packet(std::shared_ptr<connection> c,
|
||||
|
||||
auto should_send_response = true;
|
||||
auto response = std::make_shared<packet>();
|
||||
c->buffer.resize(data_size);
|
||||
conn->buffer.resize(data_size);
|
||||
read_buffer();
|
||||
|
||||
packet::error_type ret;
|
||||
auto request = std::make_shared<packet>(c->buffer);
|
||||
packet::error_type ret{};
|
||||
auto request = std::make_shared<packet>(conn->buffer);
|
||||
if (request->decrypt(encryption_token_) == 0) {
|
||||
std::string nonce;
|
||||
if ((ret = request->decode(nonce)) == 0) {
|
||||
if (nonce != c->nonce) {
|
||||
ret = request->decode(nonce);
|
||||
if (ret == 0) {
|
||||
if (nonce != conn->nonce) {
|
||||
throw std::runtime_error("invalid nonce");
|
||||
}
|
||||
c->generate_nonce();
|
||||
conn->generate_nonce();
|
||||
|
||||
std::string version;
|
||||
if ((ret = request->decode(version)) == 0) {
|
||||
ret = request->decode(version);
|
||||
if (ret == 0) {
|
||||
if (utils::compare_version_strings(
|
||||
version, REPERTORY_MIN_REMOTE_VERSION) >= 0) {
|
||||
std::uint32_t service_flags = 0u;
|
||||
std::uint32_t service_flags{};
|
||||
DECODE_OR_IGNORE(request, service_flags);
|
||||
|
||||
std::string client_id;
|
||||
DECODE_OR_IGNORE(request, client_id);
|
||||
|
||||
std::uint64_t thread_id = 0u;
|
||||
std::uint64_t thread_id{};
|
||||
DECODE_OR_IGNORE(request, thread_id);
|
||||
|
||||
std::string method;
|
||||
DECODE_OR_IGNORE(request, method);
|
||||
|
||||
if (ret == 0) {
|
||||
if (c->client_id.empty()) {
|
||||
add_client(*c, client_id);
|
||||
if (conn->client_id.empty()) {
|
||||
add_client(*conn, client_id);
|
||||
}
|
||||
|
||||
should_send_response = false;
|
||||
message_handler_(service_flags, client_id, thread_id, method,
|
||||
request.get(), *response,
|
||||
[this, c, request,
|
||||
[this, conn, request,
|
||||
response](const packet::error_type &result) {
|
||||
this->send_response(c, result, *response);
|
||||
this->send_response(conn, result, *response);
|
||||
});
|
||||
}
|
||||
} else {
|
||||
@@ -207,43 +218,43 @@ void packet_server::read_packet(std::shared_ptr<connection> c,
|
||||
throw std::runtime_error("decryption failed");
|
||||
}
|
||||
if (should_send_response) {
|
||||
send_response(c, ret, *response);
|
||||
send_response(conn, ret, *response);
|
||||
}
|
||||
} catch (const std::exception &e) {
|
||||
remove_client(*c);
|
||||
utils::error::raise_error(__FUNCTION__, e, "exception occurred");
|
||||
remove_client(*conn);
|
||||
utils::error::raise_error(function_name, e, "exception occurred");
|
||||
}
|
||||
}
|
||||
|
||||
void packet_server::remove_client(connection &c) {
|
||||
if (not c.client_id.empty()) {
|
||||
void packet_server::remove_client(connection &conn) {
|
||||
if (not conn.client_id.empty()) {
|
||||
recur_mutex_lock connection_lock(connection_mutex_);
|
||||
if (not --connection_lookup_[c.client_id]) {
|
||||
connection_lookup_.erase(c.client_id);
|
||||
closed_(c.client_id);
|
||||
if (--connection_lookup_[conn.client_id] == 0U) {
|
||||
connection_lookup_.erase(conn.client_id);
|
||||
closed_(conn.client_id);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void packet_server::send_response(std::shared_ptr<connection> c,
|
||||
void packet_server::send_response(std::shared_ptr<connection> conn,
|
||||
const packet::error_type &result,
|
||||
packet &response) {
|
||||
static const std::string function_name = __FUNCTION__;
|
||||
constexpr const auto *function_name = static_cast<const char *>(__FUNCTION__);
|
||||
|
||||
response.encode_top(result);
|
||||
response.encode_top(PACKET_SERVICE_FLAGS);
|
||||
response.encode_top(c->nonce);
|
||||
response.encode_top(conn->nonce);
|
||||
response.encrypt(encryption_token_);
|
||||
response.transfer_into(c->buffer);
|
||||
response.transfer_into(conn->buffer);
|
||||
|
||||
boost::asio::async_write(
|
||||
c->socket, boost::asio::buffer(c->buffer),
|
||||
[this, c](boost::system::error_code ec, std::size_t /*length*/) {
|
||||
if (ec) {
|
||||
remove_client(*c);
|
||||
utils::error::raise_error(function_name, ec.message());
|
||||
conn->socket, boost::asio::buffer(conn->buffer),
|
||||
[this, conn](boost::system::error_code err, std::size_t /*length*/) {
|
||||
if (err) {
|
||||
remove_client(*conn);
|
||||
utils::error::raise_error(function_name, err.message());
|
||||
} else {
|
||||
read_header(c);
|
||||
read_header(conn);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
Copyright <2018-2023> <scott.e.graves@protonmail.com>
|
||||
Copyright <2018-2024> <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
|
||||
@@ -49,7 +49,11 @@ void repertory_init() {
|
||||
}
|
||||
|
||||
curl_global_init(CURL_GLOBAL_DEFAULT);
|
||||
sqlite3_initialize();
|
||||
}
|
||||
|
||||
void repertory_shutdown() { curl_global_cleanup(); }
|
||||
void repertory_shutdown() {
|
||||
curl_global_cleanup();
|
||||
sqlite3_shutdown();
|
||||
}
|
||||
} // namespace repertory
|
||||
|
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
Copyright <2018-2023> <scott.e.graves@protonmail.com>
|
||||
Copyright <2018-2024> <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
|
||||
|
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
Copyright <2018-2023> <scott.e.graves@protonmail.com>
|
||||
Copyright <2018-2024> <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
|
||||
@@ -31,6 +31,8 @@ auto directory_iterator::fill_buffer(const remote::file_offset &offset,
|
||||
void *buffer,
|
||||
populate_stat_callback populate_stat)
|
||||
-> int {
|
||||
constexpr const auto *function_name = static_cast<const char *>(__FUNCTION__);
|
||||
|
||||
if (offset < items_.size()) {
|
||||
try {
|
||||
std::string item_name;
|
||||
@@ -54,16 +56,18 @@ auto directory_iterator::fill_buffer(const remote::file_offset &offset,
|
||||
}
|
||||
|
||||
#if FUSE_USE_VERSION >= 30
|
||||
if (filler_function(buffer, &item_name[0], pst, offset + 1,
|
||||
if (filler_function(buffer, item_name.data(), pst,
|
||||
static_cast<off_t>(offset + 1),
|
||||
FUSE_FILL_DIR_PLUS) != 0) {
|
||||
#else
|
||||
if (filler_function(buffer, &item_name[0], pst, offset + 1) != 0) {
|
||||
if (filler_function(buffer, item_name.data(), pst,
|
||||
static_cast<off_t>(offset + 1)) != 0) {
|
||||
#endif
|
||||
errno = ENOMEM;
|
||||
return -1;
|
||||
}
|
||||
} catch (const std::exception &e) {
|
||||
utils::error::raise_error(__FUNCTION__, e,
|
||||
utils::error::raise_error(function_name, e,
|
||||
"failed to fill fuse directory buffer");
|
||||
}
|
||||
|
||||
@@ -121,13 +125,14 @@ auto directory_iterator::get_json(std::size_t offset, json &item) -> int {
|
||||
|
||||
auto directory_iterator::get_next_directory_offset(
|
||||
const std::string &api_path) const -> std::size_t {
|
||||
const auto it = std::find_if(
|
||||
items_.begin(), items_.end(),
|
||||
[&api_path](const auto &di) -> bool { return api_path == di.api_path; });
|
||||
const auto iter = std::find_if(items_.begin(), items_.end(),
|
||||
[&api_path](const auto &dir_item) -> bool {
|
||||
return api_path == dir_item.api_path;
|
||||
});
|
||||
|
||||
return (it == items_.end())
|
||||
? 0
|
||||
: std::distance(items_.begin(), it) + std::size_t(1u);
|
||||
return (iter == items_.end()) ? 0U
|
||||
: static_cast<std::size_t>(
|
||||
std::distance(items_.begin(), iter) + 1);
|
||||
}
|
||||
|
||||
auto directory_iterator::operator=(const directory_iterator &iterator) noexcept
|
||||
|
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
Copyright <2018-2023> <scott.e.graves@protonmail.com>
|
||||
Copyright <2018-2024> <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
|
||||
@@ -33,31 +33,34 @@
|
||||
namespace repertory {
|
||||
auto eviction::check_minimum_requirements(const std::string &file_path)
|
||||
-> bool {
|
||||
constexpr const auto *function_name = static_cast<const char *>(__FUNCTION__);
|
||||
|
||||
std::uint64_t file_size{};
|
||||
if (not utils::file::get_file_size(file_path, file_size)) {
|
||||
utils::error::raise_error(__FUNCTION__, utils::get_last_error_code(),
|
||||
utils::error::raise_error(function_name, utils::get_last_error_code(),
|
||||
file_path, "failed to get file size");
|
||||
return false;
|
||||
}
|
||||
|
||||
auto ret = false;
|
||||
if (file_size) {
|
||||
if (file_size != 0U) {
|
||||
std::uint64_t reference_time{};
|
||||
if ((ret =
|
||||
config_.get_eviction_uses_accessed_time()
|
||||
? utils::file::get_accessed_time(file_path, reference_time)
|
||||
: utils::file::get_modified_time(file_path, reference_time))) {
|
||||
ret = config_.get_eviction_uses_accessed_time()
|
||||
? utils::file::get_accessed_time(file_path, reference_time)
|
||||
: utils::file::get_modified_time(file_path, reference_time);
|
||||
if (ret) {
|
||||
#ifdef _WIN32
|
||||
const auto now = std::chrono::system_clock::now();
|
||||
const auto delay =
|
||||
std::chrono::minutes(config_.get_eviction_delay_mins());
|
||||
ret = ((std::chrono::system_clock::from_time_t(reference_time) + delay) <=
|
||||
now);
|
||||
ret = ((std::chrono::system_clock::from_time_t(
|
||||
static_cast<time_t>(reference_time)) +
|
||||
delay) <= now);
|
||||
#else
|
||||
const auto now = utils::get_time_now();
|
||||
const auto delay =
|
||||
(config_.get_eviction_delay_mins() * 60L) * NANOS_PER_SECOND;
|
||||
ret = ((reference_time + delay) <= now);
|
||||
ret = ((reference_time + static_cast<std::uint64_t>(delay)) <= now);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
@@ -77,6 +80,8 @@ auto eviction::get_filtered_cached_files() -> std::deque<std::string> {
|
||||
}
|
||||
|
||||
void eviction::service_function() {
|
||||
constexpr const auto *function_name = static_cast<const char *>(__FUNCTION__);
|
||||
|
||||
auto should_evict = true;
|
||||
|
||||
// Handle maximum cache size eviction
|
||||
@@ -116,13 +121,13 @@ void eviction::service_function() {
|
||||
}
|
||||
} else {
|
||||
utils::error::raise_api_path_error(
|
||||
__FUNCTION__, file.api_path, file.source_path,
|
||||
function_name, file.api_path, file.source_path,
|
||||
utils::get_last_error_code(), "failed to get file size");
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch (const std::exception &ex) {
|
||||
utils::error::raise_error(__FUNCTION__, ex,
|
||||
utils::error::raise_error(function_name, ex,
|
||||
"failed to process cached file|sp|" +
|
||||
cached_files_list.front());
|
||||
}
|
||||
|
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
Copyright <2018-2023> <scott.e.graves@protonmail.com>
|
||||
Copyright <2018-2024> <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
|
||||
@@ -19,6 +19,7 @@
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
*/
|
||||
#include "common.hpp"
|
||||
#ifndef _WIN32
|
||||
|
||||
#include "drives/fuse/fuse_base.hpp"
|
||||
@@ -28,6 +29,7 @@
|
||||
#include "events/event_system.hpp"
|
||||
#include "events/events.hpp"
|
||||
#include "providers/i_provider.hpp"
|
||||
#include "utils/file_utils.hpp"
|
||||
#include "utils/path_utils.hpp"
|
||||
#include "utils/string_utils.hpp"
|
||||
#include "utils/utils.hpp"
|
||||
@@ -99,16 +101,20 @@ fuse_base::fuse_base(app_config &config) : config_(config) {
|
||||
fuse_base::~fuse_base() { E_CONSUMER_RELEASE(); }
|
||||
|
||||
auto fuse_base::access_(const char *path, int mask) -> int {
|
||||
constexpr const auto *function_name = static_cast<const char *>(__FUNCTION__);
|
||||
|
||||
return instance().instance().execute_callback(
|
||||
__FUNCTION__, path, [&](const std::string &api_path) -> api_error {
|
||||
function_name, path, [&](const std::string &api_path) -> api_error {
|
||||
return instance().access_impl(api_path, mask);
|
||||
});
|
||||
}
|
||||
|
||||
#ifdef __APPLE__
|
||||
auto fuse_base::chflags_(const char *path, uint32_t flags) -> int {
|
||||
constexpr const auto *function_name = static_cast<const char *>(__FUNCTION__);
|
||||
|
||||
return instance().instance().execute_callback(
|
||||
__FUNCTION__, path, [&](const std::string &api_path) -> api_error {
|
||||
function_name, path, [&](const std::string &api_path) -> api_error {
|
||||
return instance().chflags_impl(api_path, flags);
|
||||
});
|
||||
}
|
||||
@@ -117,15 +123,19 @@ auto fuse_base::chflags_(const char *path, uint32_t flags) -> int {
|
||||
#if FUSE_USE_VERSION >= 30
|
||||
auto fuse_base::chmod_(const char *path, mode_t mode, struct fuse_file_info *fi)
|
||||
-> int {
|
||||
constexpr const auto *function_name = static_cast<const char *>(__FUNCTION__);
|
||||
|
||||
return instance().execute_callback(
|
||||
__FUNCTION__, path, [&](const std::string &api_path) -> api_error {
|
||||
function_name, path, [&](const std::string &api_path) -> api_error {
|
||||
return instance().chmod_impl(api_path, mode, fi);
|
||||
});
|
||||
}
|
||||
#else
|
||||
auto fuse_base::chmod_(const char *path, mode_t mode) -> int {
|
||||
constexpr const auto *function_name = static_cast<const char *>(__FUNCTION__);
|
||||
|
||||
return instance().execute_callback(
|
||||
__FUNCTION__, path, [&](const std::string &api_path) -> api_error {
|
||||
function_name, path, [&](const std::string &api_path) -> api_error {
|
||||
return instance().chmod_impl(api_path, mode);
|
||||
});
|
||||
}
|
||||
@@ -134,15 +144,19 @@ auto fuse_base::chmod_(const char *path, mode_t mode) -> int {
|
||||
#if FUSE_USE_VERSION >= 30
|
||||
auto fuse_base::chown_(const char *path, uid_t uid, gid_t gid,
|
||||
struct fuse_file_info *fi) -> int {
|
||||
constexpr const auto *function_name = static_cast<const char *>(__FUNCTION__);
|
||||
|
||||
return instance().execute_callback(
|
||||
__FUNCTION__, path, [&](const std::string &api_path) -> api_error {
|
||||
function_name, path, [&](const std::string &api_path) -> api_error {
|
||||
return instance().chown_impl(api_path, uid, gid, fi);
|
||||
});
|
||||
}
|
||||
#else
|
||||
auto fuse_base::chown_(const char *path, uid_t uid, gid_t gid) -> int {
|
||||
constexpr const auto *function_name = static_cast<const char *>(__FUNCTION__);
|
||||
|
||||
return instance().execute_callback(
|
||||
__FUNCTION__, path, [&](const std::string &api_path) -> api_error {
|
||||
function_name, path, [&](const std::string &api_path) -> api_error {
|
||||
return instance().chown_impl(api_path, uid, gid);
|
||||
});
|
||||
}
|
||||
@@ -150,16 +164,22 @@ auto fuse_base::chown_(const char *path, uid_t uid, gid_t gid) -> int {
|
||||
|
||||
auto fuse_base::create_(const char *path, mode_t mode,
|
||||
struct fuse_file_info *fi) -> int {
|
||||
constexpr const auto *function_name = static_cast<const char *>(__FUNCTION__);
|
||||
|
||||
return instance().execute_callback(
|
||||
__FUNCTION__, path, [&](const std::string &api_path) -> api_error {
|
||||
function_name, path, [&](const std::string &api_path) -> api_error {
|
||||
return instance().create_impl(api_path, mode, fi);
|
||||
});
|
||||
}
|
||||
|
||||
void fuse_base::destroy_(void *ptr) {
|
||||
execute_void_callback(__FUNCTION__, [&]() { instance().destroy_impl(ptr); });
|
||||
constexpr const auto *function_name = static_cast<const char *>(__FUNCTION__);
|
||||
|
||||
execute_void_callback(function_name, [&]() { instance().destroy_impl(ptr); });
|
||||
}
|
||||
|
||||
void fuse_base::destroy_impl(void * /* ptr */) { repertory_shutdown(); }
|
||||
|
||||
void fuse_base::display_options(
|
||||
[[maybe_unused]] std::vector<const char *> args) {
|
||||
#if FUSE_USE_VERSION >= 30
|
||||
@@ -176,7 +196,7 @@ void fuse_base::display_options(
|
||||
|
||||
void fuse_base::display_version_information(std::vector<const char *> args) {
|
||||
struct fuse_operations fuse_ops {};
|
||||
fuse_main(args.size(),
|
||||
fuse_main(static_cast<int>(args.size()),
|
||||
reinterpret_cast<char **>(const_cast<char **>(args.data())),
|
||||
&fuse_ops, nullptr);
|
||||
}
|
||||
@@ -224,8 +244,10 @@ auto fuse_base::execute_void_pointer_callback(const std::string &function_name,
|
||||
|
||||
auto fuse_base::fallocate_(const char *path, int mode, off_t offset,
|
||||
off_t length, struct fuse_file_info *fi) -> int {
|
||||
constexpr const auto *function_name = static_cast<const char *>(__FUNCTION__);
|
||||
|
||||
return instance().execute_callback(
|
||||
__FUNCTION__, path, [&](const std::string &api_path) -> api_error {
|
||||
function_name, path, [&](const std::string &api_path) -> api_error {
|
||||
return instance().fallocate_impl(api_path, mode, offset, length, fi);
|
||||
});
|
||||
}
|
||||
@@ -233,8 +255,10 @@ auto fuse_base::fallocate_(const char *path, int mode, off_t offset,
|
||||
#if FUSE_USE_VERSION < 30
|
||||
auto fuse_base::fgetattr_(const char *path, struct stat *st,
|
||||
struct fuse_file_info *fi) -> int {
|
||||
constexpr const auto *function_name = static_cast<const char *>(__FUNCTION__);
|
||||
|
||||
return instance().execute_callback(
|
||||
__FUNCTION__, path, [&](const std::string &api_path) -> api_error {
|
||||
function_name, path, [&](const std::string &api_path) -> api_error {
|
||||
return instance().fgetattr_impl(api_path, st, fi);
|
||||
});
|
||||
}
|
||||
@@ -243,8 +267,10 @@ auto fuse_base::fgetattr_(const char *path, struct stat *st,
|
||||
#ifdef __APPLE__
|
||||
auto fuse_base::fsetattr_x_(const char *path, struct setattr_x *attr,
|
||||
struct fuse_file_info *fi) -> int {
|
||||
constexpr const auto *function_name = static_cast<const char *>(__FUNCTION__);
|
||||
|
||||
return instance().execute_callback(
|
||||
__FUNCTION__, path, [&](const std::string &api_path) -> api_error {
|
||||
function_name, path, [&](const std::string &api_path) -> api_error {
|
||||
return instance().fsetattr_x_impl(api_path, attr, fi);
|
||||
});
|
||||
}
|
||||
@@ -252,8 +278,10 @@ auto fuse_base::fsetattr_x_(const char *path, struct setattr_x *attr,
|
||||
|
||||
auto fuse_base::fsync_(const char *path, int datasync,
|
||||
struct fuse_file_info *fi) -> int {
|
||||
constexpr const auto *function_name = static_cast<const char *>(__FUNCTION__);
|
||||
|
||||
return instance().execute_callback(
|
||||
__FUNCTION__, path, [&](const std::string &api_path) -> api_error {
|
||||
function_name, path, [&](const std::string &api_path) -> api_error {
|
||||
return instance().fsync_impl(api_path, datasync, fi);
|
||||
});
|
||||
}
|
||||
@@ -261,8 +289,10 @@ auto fuse_base::fsync_(const char *path, int datasync,
|
||||
#if FUSE_USE_VERSION < 30
|
||||
auto fuse_base::ftruncate_(const char *path, off_t size,
|
||||
struct fuse_file_info *fi) -> int {
|
||||
constexpr const auto *function_name = static_cast<const char *>(__FUNCTION__);
|
||||
|
||||
return instance().execute_callback(
|
||||
__FUNCTION__, path, [&](const std::string &api_path) -> api_error {
|
||||
function_name, path, [&](const std::string &api_path) -> api_error {
|
||||
return instance().ftruncate_impl(api_path, size, fi);
|
||||
});
|
||||
}
|
||||
@@ -271,15 +301,19 @@ auto fuse_base::ftruncate_(const char *path, off_t size,
|
||||
#if FUSE_USE_VERSION >= 30
|
||||
auto fuse_base::getattr_(const char *path, struct stat *st,
|
||||
struct fuse_file_info *fi) -> int {
|
||||
constexpr const auto *function_name = static_cast<const char *>(__FUNCTION__);
|
||||
|
||||
return instance().execute_callback(
|
||||
__FUNCTION__, path, [&](const std::string &api_path) -> api_error {
|
||||
function_name, path, [&](const std::string &api_path) -> api_error {
|
||||
return instance().getattr_impl(api_path, st, fi);
|
||||
});
|
||||
}
|
||||
#else
|
||||
auto fuse_base::getattr_(const char *path, struct stat *st) -> int {
|
||||
constexpr const auto *function_name = static_cast<const char *>(__FUNCTION__);
|
||||
|
||||
return instance().execute_callback(
|
||||
__FUNCTION__, path, [&](const std::string &api_path) -> api_error {
|
||||
function_name, path, [&](const std::string &api_path) -> api_error {
|
||||
return instance().getattr_impl(api_path, st);
|
||||
});
|
||||
}
|
||||
@@ -288,8 +322,10 @@ auto fuse_base::getattr_(const char *path, struct stat *st) -> int {
|
||||
#ifdef __APPLE__
|
||||
auto fuse_base::getxtimes_(const char *path, struct timespec *bkuptime,
|
||||
struct timespec *crtime) -> int {
|
||||
constexpr const auto *function_name = static_cast<const char *>(__FUNCTION__);
|
||||
|
||||
return instance().execute_callback(
|
||||
__FUNCTION__, path, [&](const std::string &api_path) -> api_error {
|
||||
function_name, path, [&](const std::string &api_path) -> api_error {
|
||||
return instance().getxtimes_impl(api_path, bkuptime, crtime);
|
||||
});
|
||||
}
|
||||
@@ -298,20 +334,27 @@ auto fuse_base::getxtimes_(const char *path, struct timespec *bkuptime,
|
||||
#if FUSE_USE_VERSION >= 30
|
||||
auto fuse_base::init_(struct fuse_conn_info *conn, struct fuse_config *cfg)
|
||||
-> void * {
|
||||
return execute_void_pointer_callback(__FUNCTION__, [&]() -> void * {
|
||||
constexpr const auto *function_name = static_cast<const char *>(__FUNCTION__);
|
||||
|
||||
return execute_void_pointer_callback(function_name, [&]() -> void * {
|
||||
return instance().init_impl(conn, cfg);
|
||||
});
|
||||
}
|
||||
#else
|
||||
auto fuse_base::init_(struct fuse_conn_info *conn) -> void * {
|
||||
constexpr const auto *function_name = static_cast<const char *>(__FUNCTION__);
|
||||
|
||||
return execute_void_pointer_callback(
|
||||
__FUNCTION__, [&]() -> void * { return instance().init_impl(conn); });
|
||||
function_name, [&]() -> void * { return instance().init_impl(conn); });
|
||||
}
|
||||
#endif
|
||||
|
||||
#if FUSE_USE_VERSION >= 30
|
||||
auto fuse_base::init_impl([[maybe_unused]] struct fuse_conn_info *conn,
|
||||
struct fuse_config *cfg) -> void * {
|
||||
utils::file::change_to_process_directory();
|
||||
repertory_init();
|
||||
|
||||
#ifdef __APPLE__
|
||||
conn->want |= FUSE_CAP_VOL_RENAME;
|
||||
conn->want |= FUSE_CAP_XTIMES;
|
||||
@@ -324,6 +367,9 @@ auto fuse_base::init_impl([[maybe_unused]] struct fuse_conn_info *conn,
|
||||
}
|
||||
#else
|
||||
auto fuse_base::init_impl(struct fuse_conn_info *conn) -> void * {
|
||||
utils::file::change_to_process_directory();
|
||||
repertory_init();
|
||||
|
||||
#ifdef __APPLE__
|
||||
conn->want |= FUSE_CAP_VOL_RENAME;
|
||||
conn->want |= FUSE_CAP_XTIMES;
|
||||
@@ -336,8 +382,10 @@ auto fuse_base::init_impl(struct fuse_conn_info *conn) -> void * {
|
||||
#endif
|
||||
|
||||
auto fuse_base::mkdir_(const char *path, mode_t mode) -> int {
|
||||
constexpr const auto *function_name = static_cast<const char *>(__FUNCTION__);
|
||||
|
||||
return instance().execute_callback(
|
||||
__FUNCTION__, path, [&](const std::string &api_path) -> api_error {
|
||||
function_name, path, [&](const std::string &api_path) -> api_error {
|
||||
return instance().mkdir_impl(api_path, mode);
|
||||
});
|
||||
}
|
||||
@@ -351,8 +399,9 @@ auto fuse_base::mount(std::vector<std::string> args) -> int {
|
||||
}
|
||||
|
||||
{
|
||||
struct fuse_args fa = FUSE_ARGS_INIT(static_cast<int>(fuse_argv.size()),
|
||||
(char **)&fuse_argv[0]);
|
||||
struct fuse_args fa = FUSE_ARGS_INIT(
|
||||
static_cast<int>(fuse_argv.size()),
|
||||
reinterpret_cast<char **>(const_cast<char **>(fuse_argv.data())));
|
||||
|
||||
char *mount_location{nullptr};
|
||||
#if FUSE_USE_VERSION >= 30
|
||||
@@ -374,8 +423,10 @@ auto fuse_base::mount(std::vector<std::string> args) -> int {
|
||||
#if FUSE_USE_VERSION < 30
|
||||
umask(0);
|
||||
#endif
|
||||
ret = fuse_main(static_cast<int>(fuse_argv.size()), (char **)&fuse_argv[0],
|
||||
&fuse_ops_, this);
|
||||
ret = fuse_main(
|
||||
static_cast<int>(fuse_argv.size()),
|
||||
reinterpret_cast<char **>(const_cast<char **>(fuse_argv.data())),
|
||||
&fuse_ops_, this);
|
||||
notify_fuse_main_exit(ret);
|
||||
}
|
||||
|
||||
@@ -383,24 +434,30 @@ auto fuse_base::mount(std::vector<std::string> args) -> int {
|
||||
}
|
||||
|
||||
auto fuse_base::open_(const char *path, struct fuse_file_info *fi) -> int {
|
||||
constexpr const auto *function_name = static_cast<const char *>(__FUNCTION__);
|
||||
|
||||
return instance().execute_callback(
|
||||
__FUNCTION__, path, [&](const std::string &api_path) -> api_error {
|
||||
function_name, path, [&](const std::string &api_path) -> api_error {
|
||||
return instance().open_impl(api_path, fi);
|
||||
});
|
||||
}
|
||||
|
||||
auto fuse_base::opendir_(const char *path, struct fuse_file_info *fi) -> int {
|
||||
constexpr const auto *function_name = static_cast<const char *>(__FUNCTION__);
|
||||
|
||||
return instance().execute_callback(
|
||||
__FUNCTION__, path, [&](const std::string &api_path) -> api_error {
|
||||
function_name, path, [&](const std::string &api_path) -> api_error {
|
||||
return instance().opendir_impl(api_path, fi);
|
||||
});
|
||||
}
|
||||
|
||||
auto fuse_base::read_(const char *path, char *buffer, size_t read_size,
|
||||
off_t read_offset, struct fuse_file_info *fi) -> int {
|
||||
constexpr const auto *function_name = static_cast<const char *>(__FUNCTION__);
|
||||
|
||||
std::size_t bytes_read{};
|
||||
const auto res = instance().execute_callback(
|
||||
__FUNCTION__, path,
|
||||
function_name, path,
|
||||
[&](const std::string &api_path) -> api_error {
|
||||
return instance().read_impl(api_path, buffer, read_size, read_offset,
|
||||
fi, bytes_read);
|
||||
@@ -414,8 +471,10 @@ auto fuse_base::readdir_(const char *path, void *buf,
|
||||
fuse_fill_dir_t fuse_fill_dir, off_t offset,
|
||||
struct fuse_file_info *fi, fuse_readdir_flags flags)
|
||||
-> int {
|
||||
constexpr const auto *function_name = static_cast<const char *>(__FUNCTION__);
|
||||
|
||||
return instance().execute_callback(
|
||||
__FUNCTION__, path, [&](const std::string &api_path) -> api_error {
|
||||
function_name, path, [&](const std::string &api_path) -> api_error {
|
||||
return instance().readdir_impl(api_path, buf, fuse_fill_dir, offset, fi,
|
||||
flags);
|
||||
});
|
||||
@@ -424,8 +483,10 @@ auto fuse_base::readdir_(const char *path, void *buf,
|
||||
auto fuse_base::readdir_(const char *path, void *buf,
|
||||
fuse_fill_dir_t fuse_fill_dir, off_t offset,
|
||||
struct fuse_file_info *fi) -> int {
|
||||
constexpr const auto *function_name = static_cast<const char *>(__FUNCTION__);
|
||||
|
||||
return instance().execute_callback(
|
||||
__FUNCTION__, path, [&](const std::string &api_path) -> api_error {
|
||||
function_name, path, [&](const std::string &api_path) -> api_error {
|
||||
return instance().readdir_impl(api_path, buf, fuse_fill_dir, offset,
|
||||
fi);
|
||||
});
|
||||
@@ -433,16 +494,20 @@ auto fuse_base::readdir_(const char *path, void *buf,
|
||||
#endif
|
||||
|
||||
auto fuse_base::release_(const char *path, struct fuse_file_info *fi) -> int {
|
||||
constexpr const auto *function_name = static_cast<const char *>(__FUNCTION__);
|
||||
|
||||
return instance().execute_callback(
|
||||
__FUNCTION__, path, [&](const std::string &api_path) -> api_error {
|
||||
function_name, path, [&](const std::string &api_path) -> api_error {
|
||||
return instance().release_impl(api_path, fi);
|
||||
});
|
||||
}
|
||||
|
||||
auto fuse_base::releasedir_(const char *path, struct fuse_file_info *fi)
|
||||
-> int {
|
||||
constexpr const auto *function_name = static_cast<const char *>(__FUNCTION__);
|
||||
|
||||
return instance().execute_callback(
|
||||
__FUNCTION__, path, [&](const std::string &api_path) -> api_error {
|
||||
function_name, path, [&](const std::string &api_path) -> api_error {
|
||||
return instance().releasedir_impl(api_path, fi);
|
||||
});
|
||||
}
|
||||
@@ -450,8 +515,10 @@ auto fuse_base::releasedir_(const char *path, struct fuse_file_info *fi)
|
||||
#if FUSE_USE_VERSION >= 30
|
||||
auto fuse_base::rename_(const char *from, const char *to, unsigned int flags)
|
||||
-> int {
|
||||
constexpr const auto *function_name = static_cast<const char *>(__FUNCTION__);
|
||||
|
||||
return instance().execute_callback(
|
||||
__FUNCTION__, from, to,
|
||||
function_name, from, to,
|
||||
[&](const std::string &from_api_file,
|
||||
const std::string &to_api_path) -> api_error {
|
||||
return instance().rename_impl(from_api_file, to_api_path, flags);
|
||||
@@ -459,8 +526,10 @@ auto fuse_base::rename_(const char *from, const char *to, unsigned int flags)
|
||||
}
|
||||
#else
|
||||
auto fuse_base::rename_(const char *from, const char *to) -> int {
|
||||
constexpr const auto *function_name = static_cast<const char *>(__FUNCTION__);
|
||||
|
||||
return instance().execute_callback(
|
||||
__FUNCTION__, from, to,
|
||||
function_name, from, to,
|
||||
[&](const std::string &from_api_file,
|
||||
const std::string &to_api_path) -> api_error {
|
||||
return instance().rename_impl(from_api_file, to_api_path);
|
||||
@@ -469,8 +538,10 @@ auto fuse_base::rename_(const char *from, const char *to) -> int {
|
||||
#endif
|
||||
|
||||
auto fuse_base::rmdir_(const char *path) -> int {
|
||||
constexpr const auto *function_name = static_cast<const char *>(__FUNCTION__);
|
||||
|
||||
return instance().execute_callback(
|
||||
__FUNCTION__, path, [&](const std::string &api_path) -> api_error {
|
||||
function_name, path, [&](const std::string &api_path) -> api_error {
|
||||
return instance().rmdir_impl(api_path);
|
||||
});
|
||||
}
|
||||
@@ -479,9 +550,11 @@ auto fuse_base::rmdir_(const char *path) -> int {
|
||||
#ifdef __APPLE__
|
||||
auto fuse_base::getxattr_(const char *path, const char *name, char *value,
|
||||
size_t size, uint32_t position) -> int {
|
||||
constexpr const auto *function_name = static_cast<const char *>(__FUNCTION__);
|
||||
|
||||
int attribute_size = 0;
|
||||
const auto res = instance().execute_callback(
|
||||
__FUNCTION__, path, [&](const std::string &api_path) -> api_error {
|
||||
function_name, path, [&](const std::string &api_path) -> api_error {
|
||||
return instance().getxattr_impl(api_path, name, value, size, position,
|
||||
attribute_size);
|
||||
});
|
||||
@@ -491,9 +564,11 @@ auto fuse_base::getxattr_(const char *path, const char *name, char *value,
|
||||
#else // __APPLE__
|
||||
auto fuse_base::getxattr_(const char *path, const char *name, char *value,
|
||||
size_t size) -> int {
|
||||
constexpr const auto *function_name = static_cast<const char *>(__FUNCTION__);
|
||||
|
||||
int attribute_size = 0;
|
||||
const auto res = instance().execute_callback(
|
||||
__FUNCTION__, path, [&](const std::string &api_path) -> api_error {
|
||||
function_name, path, [&](const std::string &api_path) -> api_error {
|
||||
return instance().getxattr_impl(api_path, name, value, size,
|
||||
attribute_size);
|
||||
});
|
||||
@@ -503,11 +578,13 @@ auto fuse_base::getxattr_(const char *path, const char *name, char *value,
|
||||
#endif // __APPLE__
|
||||
|
||||
auto fuse_base::listxattr_(const char *path, char *buffer, size_t size) -> int {
|
||||
constexpr const auto *function_name = static_cast<const char *>(__FUNCTION__);
|
||||
|
||||
int required_size = 0;
|
||||
bool return_size = false;
|
||||
|
||||
const auto res = instance().execute_callback(
|
||||
__FUNCTION__, path, [&](const std::string &api_path) -> api_error {
|
||||
function_name, path, [&](const std::string &api_path) -> api_error {
|
||||
return instance().listxattr_impl(api_path, buffer, size, required_size,
|
||||
return_size);
|
||||
});
|
||||
@@ -620,8 +697,10 @@ void fuse_base::raise_fuse_event(std::string function_name,
|
||||
}
|
||||
|
||||
auto fuse_base::removexattr_(const char *path, const char *name) -> int {
|
||||
constexpr const auto *function_name = static_cast<const char *>(__FUNCTION__);
|
||||
|
||||
return instance().execute_callback(
|
||||
__FUNCTION__, path, [&](const std::string &api_path) -> api_error {
|
||||
function_name, path, [&](const std::string &api_path) -> api_error {
|
||||
return instance().removexattr_impl(api_path, name);
|
||||
});
|
||||
}
|
||||
@@ -629,8 +708,10 @@ auto fuse_base::removexattr_(const char *path, const char *name) -> int {
|
||||
#ifdef __APPLE__
|
||||
auto fuse_base::setxattr_(const char *path, const char *name, const char *value,
|
||||
size_t size, int flags, uint32_t position) -> int {
|
||||
constexpr const auto *function_name = static_cast<const char *>(__FUNCTION__);
|
||||
|
||||
const auto res = instance().execute_callback(
|
||||
__FUNCTION__, path, [&](const std::string &api_path) -> api_error {
|
||||
function_name, path, [&](const std::string &api_path) -> api_error {
|
||||
return instance().setxattr_impl(api_path, name, value, size, flags,
|
||||
position);
|
||||
});
|
||||
@@ -643,8 +724,10 @@ auto fuse_base::setxattr_(const char *path, const char *name, const char *value,
|
||||
#else // __APPLE__
|
||||
auto fuse_base::setxattr_(const char *path, const char *name, const char *value,
|
||||
size_t size, int flags) -> int {
|
||||
constexpr const auto *function_name = static_cast<const char *>(__FUNCTION__);
|
||||
|
||||
const auto res = instance().execute_callback(
|
||||
__FUNCTION__, path, [&](const std::string &api_path) -> api_error {
|
||||
function_name, path, [&](const std::string &api_path) -> api_error {
|
||||
return instance().setxattr_impl(api_path, name, value, size, flags);
|
||||
});
|
||||
if (res != 0) {
|
||||
@@ -664,53 +747,67 @@ void fuse_base::shutdown() {
|
||||
|
||||
#ifdef __APPLE__
|
||||
auto fuse_base::setattr_x_(const char *path, struct setattr_x *attr) -> int {
|
||||
constexpr const auto *function_name = static_cast<const char *>(__FUNCTION__);
|
||||
|
||||
return instance().execute_callback(
|
||||
__FUNCTION__, path, [&](const std::string &api_path) -> api_error {
|
||||
function_name, path, [&](const std::string &api_path) -> api_error {
|
||||
return instance().setattr_x_impl(api_path, attr);
|
||||
});
|
||||
}
|
||||
|
||||
auto fuse_base::setbkuptime_(const char *path, const struct timespec *bkuptime)
|
||||
-> int {
|
||||
constexpr const auto *function_name = static_cast<const char *>(__FUNCTION__);
|
||||
|
||||
return instance().execute_callback(
|
||||
__FUNCTION__, path, [&](const std::string &api_path) -> api_error {
|
||||
function_name, path, [&](const std::string &api_path) -> api_error {
|
||||
return instance().setbkuptime_impl(api_path, bkuptime);
|
||||
});
|
||||
}
|
||||
|
||||
auto fuse_base::setchgtime_(const char *path, const struct timespec *chgtime)
|
||||
-> int {
|
||||
constexpr const auto *function_name = static_cast<const char *>(__FUNCTION__);
|
||||
|
||||
return instance().execute_callback(
|
||||
__FUNCTION__, path, [&](const std::string &api_path) -> api_error {
|
||||
function_name, path, [&](const std::string &api_path) -> api_error {
|
||||
return instance().setchgtime_impl(api_path, chgtime);
|
||||
});
|
||||
}
|
||||
|
||||
auto fuse_base::setcrtime_(const char *path, const struct timespec *crtime)
|
||||
-> int {
|
||||
constexpr const auto *function_name = static_cast<const char *>(__FUNCTION__);
|
||||
|
||||
return instance().execute_callback(
|
||||
__FUNCTION__, path, [&](const std::string &api_path) -> api_error {
|
||||
function_name, path, [&](const std::string &api_path) -> api_error {
|
||||
return instance().setcrtime_impl(api_path, crtime);
|
||||
});
|
||||
}
|
||||
|
||||
auto fuse_base::setvolname_(const char *volname) -> int {
|
||||
constexpr const auto *function_name = static_cast<const char *>(__FUNCTION__);
|
||||
|
||||
return instance().execute_callback(
|
||||
__FUNCTION__, volname, [&](const std::string &api_path) -> api_error {
|
||||
function_name, volname, [&](const std::string &api_path) -> api_error {
|
||||
return instance().setvolname_impl(volname);
|
||||
});
|
||||
}
|
||||
|
||||
auto fuse_base::statfs_x_(const char *path, struct statfs *stbuf) -> int {
|
||||
constexpr const auto *function_name = static_cast<const char *>(__FUNCTION__);
|
||||
|
||||
return instance().execute_callback(
|
||||
__FUNCTION__, path, [&](const std::string &api_path) -> api_error {
|
||||
function_name, path, [&](const std::string &api_path) -> api_error {
|
||||
return instance().statfs_x_impl(api_path, stbuf);
|
||||
});
|
||||
}
|
||||
#else // __APPLE__
|
||||
auto fuse_base::statfs_(const char *path, struct statvfs *stbuf) -> int {
|
||||
constexpr const auto *function_name = static_cast<const char *>(__FUNCTION__);
|
||||
|
||||
return instance().execute_callback(
|
||||
__FUNCTION__, path, [&](const std::string &api_path) -> api_error {
|
||||
function_name, path, [&](const std::string &api_path) -> api_error {
|
||||
return instance().statfs_impl(api_path, stbuf);
|
||||
});
|
||||
}
|
||||
@@ -719,23 +816,29 @@ auto fuse_base::statfs_(const char *path, struct statvfs *stbuf) -> int {
|
||||
#if FUSE_USE_VERSION >= 30
|
||||
auto fuse_base::truncate_(const char *path, off_t size,
|
||||
struct fuse_file_info *fi) -> int {
|
||||
constexpr const auto *function_name = static_cast<const char *>(__FUNCTION__);
|
||||
|
||||
return instance().execute_callback(
|
||||
__FUNCTION__, path, [&](const std::string &api_path) -> api_error {
|
||||
function_name, path, [&](const std::string &api_path) -> api_error {
|
||||
return instance().truncate_impl(api_path, size, fi);
|
||||
});
|
||||
}
|
||||
#else
|
||||
auto fuse_base::truncate_(const char *path, off_t size) -> int {
|
||||
constexpr const auto *function_name = static_cast<const char *>(__FUNCTION__);
|
||||
|
||||
return instance().execute_callback(
|
||||
__FUNCTION__, path, [&](const std::string &api_path) -> api_error {
|
||||
function_name, path, [&](const std::string &api_path) -> api_error {
|
||||
return instance().truncate_impl(api_path, size);
|
||||
});
|
||||
}
|
||||
#endif
|
||||
|
||||
auto fuse_base::unlink_(const char *path) -> int {
|
||||
constexpr const auto *function_name = static_cast<const char *>(__FUNCTION__);
|
||||
|
||||
return instance().execute_callback(
|
||||
__FUNCTION__, path, [&](const std::string &api_path) -> api_error {
|
||||
function_name, path, [&](const std::string &api_path) -> api_error {
|
||||
return instance().unlink_impl(api_path);
|
||||
});
|
||||
}
|
||||
@@ -757,15 +860,19 @@ auto fuse_base::unmount(const std::string &mount_location) -> int {
|
||||
#if FUSE_USE_VERSION >= 30
|
||||
auto fuse_base::utimens_(const char *path, const struct timespec tv[2],
|
||||
struct fuse_file_info *fi) -> int {
|
||||
constexpr const auto *function_name = static_cast<const char *>(__FUNCTION__);
|
||||
|
||||
return instance().execute_callback(
|
||||
__FUNCTION__, path, [&](const std::string &api_path) -> api_error {
|
||||
function_name, path, [&](const std::string &api_path) -> api_error {
|
||||
return instance().utimens_impl(api_path, tv, fi);
|
||||
});
|
||||
}
|
||||
#else
|
||||
auto fuse_base::utimens_(const char *path, const struct timespec tv[2]) -> int {
|
||||
constexpr const auto *function_name = static_cast<const char *>(__FUNCTION__);
|
||||
|
||||
return instance().execute_callback(
|
||||
__FUNCTION__, path, [&](const std::string &api_path) -> api_error {
|
||||
function_name, path, [&](const std::string &api_path) -> api_error {
|
||||
return instance().utimens_impl(api_path, tv);
|
||||
});
|
||||
}
|
||||
@@ -773,10 +880,12 @@ auto fuse_base::utimens_(const char *path, const struct timespec tv[2]) -> int {
|
||||
|
||||
auto fuse_base::write_(const char *path, const char *buffer, size_t write_size,
|
||||
off_t write_offset, struct fuse_file_info *fi) -> int {
|
||||
constexpr const auto *function_name = static_cast<const char *>(__FUNCTION__);
|
||||
|
||||
std::size_t bytes_written{};
|
||||
|
||||
const auto res = instance().execute_callback(
|
||||
__FUNCTION__, path,
|
||||
function_name, path,
|
||||
[&](const std::string &api_path) -> api_error {
|
||||
return instance().write_impl(api_path, buffer, write_size, write_offset,
|
||||
fi, bytes_written);
|
||||
|
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
Copyright <2018-2023> <scott.e.graves@protonmail.com>
|
||||
Copyright <2018-2024> <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
|
||||
@@ -204,7 +204,9 @@ auto fuse_drive::create_impl(std::string api_path, mode_t mode,
|
||||
return api_error::success;
|
||||
}
|
||||
|
||||
void fuse_drive::destroy_impl(void * /* ptr */) {
|
||||
void fuse_drive::destroy_impl(void *ptr) {
|
||||
constexpr const auto *function_name = static_cast<const char *>(__FUNCTION__);
|
||||
|
||||
event_system::instance().raise<drive_unmount_pending>(get_mount_location());
|
||||
|
||||
remote_server_.reset();
|
||||
@@ -240,8 +242,10 @@ void fuse_drive::destroy_impl(void * /* ptr */) {
|
||||
config_.save();
|
||||
|
||||
if (not lock_data_.set_mount_state(false, "", -1)) {
|
||||
utils::error::raise_error(__FUNCTION__, "failed to set mount state");
|
||||
utils::error::raise_error(function_name, "failed to set mount state");
|
||||
}
|
||||
|
||||
fuse_base::destroy_impl(ptr);
|
||||
}
|
||||
|
||||
auto fuse_drive::fallocate_impl(std::string /*api_path*/, int mode,
|
||||
@@ -387,10 +391,12 @@ auto fuse_drive::get_directory_item_count(const std::string &api_path) const
|
||||
|
||||
auto fuse_drive::get_directory_items(const std::string &api_path) const
|
||||
-> directory_item_list {
|
||||
constexpr const auto *function_name = static_cast<const char *>(__FUNCTION__);
|
||||
|
||||
directory_item_list list{};
|
||||
auto res = provider_.get_directory_items(api_path, list);
|
||||
if (res != api_error::success) {
|
||||
utils::error::raise_api_path_error(__FUNCTION__, api_path, res,
|
||||
utils::error::raise_api_path_error(function_name, api_path, res,
|
||||
"failed to get directory items");
|
||||
}
|
||||
|
||||
@@ -399,10 +405,12 @@ auto fuse_drive::get_directory_items(const std::string &api_path) const
|
||||
|
||||
auto fuse_drive::get_file_size(const std::string &api_path) const
|
||||
-> std::uint64_t {
|
||||
constexpr const auto *function_name = static_cast<const char *>(__FUNCTION__);
|
||||
|
||||
std::uint64_t file_size{};
|
||||
auto res = provider_.get_file_size(api_path, file_size);
|
||||
if (res == api_error::success) {
|
||||
utils::error::raise_api_path_error(__FUNCTION__, api_path, res,
|
||||
utils::error::raise_api_path_error(function_name, api_path, res,
|
||||
"failed to get file size from provider");
|
||||
}
|
||||
|
||||
@@ -519,7 +527,13 @@ auto fuse_drive::init_impl(struct fuse_conn_info *conn, struct fuse_config *cfg)
|
||||
#else
|
||||
void *fuse_drive::init_impl(struct fuse_conn_info *conn) {
|
||||
#endif
|
||||
utils::file::change_to_process_directory();
|
||||
constexpr const auto *function_name = static_cast<const char *>(__FUNCTION__);
|
||||
|
||||
#if FUSE_USE_VERSION >= 30
|
||||
auto *ret = fuse_drive_base::init_impl(conn, cfg);
|
||||
#else
|
||||
auto *ret = fuse_drive_base::init_impl(conn);
|
||||
#endif
|
||||
|
||||
if (console_enabled_) {
|
||||
console_consumer_ = std::make_unique<console_consumer>();
|
||||
@@ -562,22 +576,18 @@ void *fuse_drive::init_impl(struct fuse_conn_info *conn) {
|
||||
}
|
||||
|
||||
if (not lock_data_.set_mount_state(true, get_mount_location(), getpid())) {
|
||||
utils::error::raise_error(__FUNCTION__, "failed to set mount state");
|
||||
utils::error::raise_error(function_name, "failed to set mount state");
|
||||
}
|
||||
event_system::instance().raise<drive_mounted>(get_mount_location());
|
||||
} catch (const std::exception &e) {
|
||||
utils::error::raise_error(__FUNCTION__, e, "exception during fuse init");
|
||||
utils::error::raise_error(function_name, e, "exception during fuse init");
|
||||
|
||||
destroy_impl(this);
|
||||
|
||||
fuse_exit(fuse_get_context()->fuse);
|
||||
}
|
||||
|
||||
#if FUSE_USE_VERSION >= 30
|
||||
return fuse_drive_base::init_impl(conn, cfg);
|
||||
#else
|
||||
return fuse_drive_base::init_impl(conn);
|
||||
#endif
|
||||
return ret;
|
||||
}
|
||||
|
||||
auto fuse_drive::is_processing(const std::string &api_path) const -> bool {
|
||||
@@ -585,6 +595,8 @@ auto fuse_drive::is_processing(const std::string &api_path) const -> bool {
|
||||
}
|
||||
|
||||
auto fuse_drive::mkdir_impl(std::string api_path, mode_t mode) -> api_error {
|
||||
constexpr const auto *function_name = static_cast<const char *>(__FUNCTION__);
|
||||
|
||||
auto res = check_parent_access(api_path, W_OK | X_OK);
|
||||
if (res != api_error::success) {
|
||||
return res;
|
||||
@@ -594,17 +606,18 @@ auto fuse_drive::mkdir_impl(std::string api_path, mode_t mode) -> api_error {
|
||||
auto meta = create_meta_attributes(now, FILE_ATTRIBUTE_DIRECTORY, now, now,
|
||||
true, get_effective_gid(), "", mode, now,
|
||||
0U, 0U, 0U, "", get_effective_uid(), now);
|
||||
if ((res = provider_.create_directory(api_path, meta)) !=
|
||||
api_error::success) {
|
||||
res = provider_.create_directory(api_path, meta);
|
||||
if (res != api_error::success) {
|
||||
return res;
|
||||
}
|
||||
|
||||
if (api_path != "/") {
|
||||
if ((res = provider_.set_item_meta(
|
||||
utils::path::get_parent_api_path(api_path), META_MODIFIED,
|
||||
std::to_string(now))) != api_error::success) {
|
||||
res = provider_.set_item_meta(utils::path::get_parent_api_path(api_path),
|
||||
META_MODIFIED, std::to_string(now));
|
||||
if (res != api_error::success) {
|
||||
utils::error::raise_api_path_error(
|
||||
__FUNCTION__, api_path, res, "failed to set directory modified time");
|
||||
function_name, api_path, res,
|
||||
"failed to set directory modified time");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -661,13 +674,6 @@ auto fuse_drive::opendir_impl(std::string api_path,
|
||||
return api_error::success;
|
||||
}
|
||||
|
||||
void fuse_drive::populate_stat(const directory_item &dir_item,
|
||||
struct stat &st) const {
|
||||
fuse_drive_base::populate_stat(dir_item.api_path, dir_item.size,
|
||||
dir_item.meta, dir_item.directory, provider_,
|
||||
&st);
|
||||
}
|
||||
|
||||
auto fuse_drive::read_impl(std::string api_path, char *buffer, size_t read_size,
|
||||
off_t read_offset, struct fuse_file_info *file_info,
|
||||
std::size_t &bytes_read) -> api_error {
|
||||
@@ -910,8 +916,8 @@ auto fuse_drive::listxattr_impl(std::string api_path, char *buffer, size_t size,
|
||||
#endif
|
||||
const auto attribute_name_size = strlen(attribute_name.c_str()) + 1U;
|
||||
if (size >= attribute_name_size) {
|
||||
strncpy(&buffer[required_size], attribute_name.c_str(),
|
||||
attribute_name_size);
|
||||
std::memcpy(&buffer[required_size], attribute_name.data(),
|
||||
attribute_name_size);
|
||||
size -= attribute_name_size;
|
||||
} else {
|
||||
res = api_error::xattr_buffer_small;
|
||||
@@ -1024,9 +1030,11 @@ auto fuse_drive::setxattr_impl(std::string api_path, const char *name,
|
||||
void fuse_drive::set_item_meta(const std::string &api_path,
|
||||
const std::string &key,
|
||||
const std::string &value) {
|
||||
constexpr const auto *function_name = static_cast<const char *>(__FUNCTION__);
|
||||
|
||||
auto res = provider_.set_item_meta(api_path, key, value);
|
||||
if (res != api_error::success) {
|
||||
utils::error::raise_api_path_error(__FUNCTION__, api_path, res,
|
||||
utils::error::raise_api_path_error(function_name, api_path, res,
|
||||
"key|" + key + "|value|" + value);
|
||||
}
|
||||
}
|
||||
@@ -1187,10 +1195,11 @@ auto fuse_drive::statfs_x_impl(std::string /*api_path*/, struct statfs *stbuf)
|
||||
stbuf->f_files = 4294967295;
|
||||
stbuf->f_ffree = stbuf->f_files - provider_.get_total_item_count();
|
||||
stbuf->f_owner = getuid();
|
||||
strncpy(&stbuf->f_mntonname[0], get_mount_location().c_str(), MNAMELEN);
|
||||
strncpy(&stbuf->f_mntfromname[0],
|
||||
strncpy(&stbuf->f_mntonname[0U], get_mount_location().c_str(),
|
||||
get_mount_location().size());
|
||||
strncpy(&stbuf->f_mntfromname[0U],
|
||||
(utils::create_volume_label(config_.get_provider_type())).c_str(),
|
||||
MNAMELEN);
|
||||
sizeof(stbuf->f_mntfromname) - 1U);
|
||||
|
||||
return api_error::success;
|
||||
}
|
||||
@@ -1203,11 +1212,10 @@ auto fuse_drive::statfs_impl(std::string /*api_path*/, struct statvfs *stbuf)
|
||||
|
||||
const auto total_bytes = provider_.get_total_drive_space();
|
||||
const auto total_used = provider_.get_used_drive_space();
|
||||
const auto used_blocks = utils::divide_with_ceiling(
|
||||
total_used, static_cast<std::uint64_t>(stbuf->f_frsize));
|
||||
const auto used_blocks =
|
||||
utils::divide_with_ceiling(total_used, stbuf->f_frsize);
|
||||
stbuf->f_files = 4294967295;
|
||||
stbuf->f_blocks = utils::divide_with_ceiling(
|
||||
total_bytes, static_cast<std::uint64_t>(stbuf->f_frsize));
|
||||
stbuf->f_blocks = utils::divide_with_ceiling(total_bytes, stbuf->f_frsize);
|
||||
stbuf->f_bavail = stbuf->f_bfree =
|
||||
stbuf->f_blocks == 0U ? 0 : (stbuf->f_blocks - used_blocks);
|
||||
stbuf->f_ffree = stbuf->f_favail =
|
||||
@@ -1345,11 +1353,13 @@ auto fuse_drive::write_impl(std::string /*api_path*/
|
||||
}
|
||||
|
||||
void fuse_drive::update_accessed_time(const std::string &api_path) {
|
||||
constexpr const auto *function_name = static_cast<const char *>(__FUNCTION__);
|
||||
|
||||
if (atime_enabled_) {
|
||||
auto res = provider_.set_item_meta(
|
||||
api_path, META_ACCESSED, std::to_string(utils::get_file_time_now()));
|
||||
if (res != api_error::success) {
|
||||
utils::error::raise_api_path_error(__FUNCTION__, api_path, res,
|
||||
utils::error::raise_api_path_error(function_name, api_path, res,
|
||||
"failed to set accessed time");
|
||||
}
|
||||
}
|
||||
|
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
Copyright <2018-2023> <scott.e.graves@protonmail.com>
|
||||
Copyright <2018-2024> <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
|
||||
@@ -232,9 +232,9 @@ auto fuse_drive_base::get_mode_from_meta(const api_meta_map &meta) -> mode_t {
|
||||
void fuse_drive_base::get_timespec_from_meta(const api_meta_map &meta,
|
||||
const std::string &name,
|
||||
struct timespec &ts) {
|
||||
const auto t = utils::string::to_uint64(meta.at(name));
|
||||
ts.tv_nsec = t % NANOS_PER_SECOND;
|
||||
ts.tv_sec = t / NANOS_PER_SECOND;
|
||||
const auto meta_time = utils::string::to_int64(meta.at(name));
|
||||
ts.tv_nsec = meta_time % NANOS_PER_SECOND;
|
||||
ts.tv_sec = meta_time / NANOS_PER_SECOND;
|
||||
}
|
||||
|
||||
auto fuse_drive_base::get_uid_from_meta(const api_meta_map &meta) -> uid_t {
|
||||
@@ -304,22 +304,23 @@ void fuse_drive_base::populate_stat(const std::string &api_path,
|
||||
const api_meta_map &meta, bool directory,
|
||||
i_provider &provider, struct stat *st) {
|
||||
memset(st, 0, sizeof(struct stat));
|
||||
st->st_nlink =
|
||||
(directory
|
||||
? 2 + (size_or_count ? size_or_count
|
||||
: provider.get_directory_item_count(api_path))
|
||||
: 1);
|
||||
st->st_nlink = static_cast<nlink_t>(
|
||||
directory ? 2 + (size_or_count == 0U
|
||||
? provider.get_directory_item_count(api_path)
|
||||
: size_or_count)
|
||||
: 1);
|
||||
if (directory) {
|
||||
st->st_blocks = 0;
|
||||
} else {
|
||||
st->st_size = size_or_count;
|
||||
static const auto block_size_stat = static_cast<std::uint64_t>(512u);
|
||||
static const auto block_size = static_cast<std::uint64_t>(4096u);
|
||||
st->st_size = static_cast<off_t>(size_or_count);
|
||||
static const auto block_size_stat = static_cast<std::uint64_t>(512U);
|
||||
static const auto block_size = static_cast<std::uint64_t>(4096U);
|
||||
const auto size = utils::divide_with_ceiling(
|
||||
static_cast<std::uint64_t>(st->st_size), block_size) *
|
||||
block_size;
|
||||
st->st_blocks = std::max(block_size / block_size_stat,
|
||||
utils::divide_with_ceiling(size, block_size_stat));
|
||||
st->st_blocks = static_cast<blkcnt_t>(
|
||||
std::max(block_size / block_size_stat,
|
||||
utils::divide_with_ceiling(size, block_size_stat)));
|
||||
}
|
||||
st->st_gid = get_gid_from_meta(meta);
|
||||
st->st_mode = (directory ? S_IFDIR : S_IFREG) | get_mode_from_meta(meta);
|
||||
@@ -344,9 +345,9 @@ void fuse_drive_base::populate_stat(const std::string &api_path,
|
||||
void fuse_drive_base::set_timespec_from_meta(const api_meta_map &meta,
|
||||
const std::string &name,
|
||||
struct timespec &ts) {
|
||||
const auto t = utils::string::to_uint64(meta.at(name));
|
||||
ts.tv_nsec = t % NANOS_PER_SECOND;
|
||||
ts.tv_sec = t / NANOS_PER_SECOND;
|
||||
const auto meta_time = utils::string::to_int64(meta.at(name));
|
||||
ts.tv_nsec = meta_time % NANOS_PER_SECOND;
|
||||
ts.tv_sec = meta_time / NANOS_PER_SECOND;
|
||||
}
|
||||
} // namespace repertory
|
||||
|
||||
|
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
Copyright <2018-2023> <scott.e.graves@protonmail.com>
|
||||
Copyright <2018-2024> <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
|
||||
@@ -36,49 +36,59 @@ remote_client::remote_client(const app_config &config)
|
||||
|
||||
auto remote_client::fuse_access(const char *path, const std::int32_t &mask)
|
||||
-> packet::error_type {
|
||||
constexpr const auto *function_name = static_cast<const char *>(__FUNCTION__);
|
||||
|
||||
packet request;
|
||||
request.encode(path);
|
||||
request.encode(mask);
|
||||
|
||||
std::uint32_t service_flags = 0u;
|
||||
return packet_client_.send(__FUNCTION__, request, service_flags);
|
||||
std::uint32_t service_flags{};
|
||||
return packet_client_.send(function_name, request, service_flags);
|
||||
}
|
||||
|
||||
auto remote_client::fuse_chflags(const char *path, std::uint32_t flags)
|
||||
-> packet::error_type {
|
||||
constexpr const auto *function_name = static_cast<const char *>(__FUNCTION__);
|
||||
|
||||
packet request;
|
||||
request.encode(path);
|
||||
request.encode(flags);
|
||||
|
||||
std::uint32_t service_flags = 0u;
|
||||
return packet_client_.send(__FUNCTION__, request, service_flags);
|
||||
std::uint32_t service_flags{};
|
||||
return packet_client_.send(function_name, request, service_flags);
|
||||
}
|
||||
|
||||
auto remote_client::fuse_chmod(const char *path, const remote::file_mode &mode)
|
||||
-> packet::error_type {
|
||||
constexpr const auto *function_name = static_cast<const char *>(__FUNCTION__);
|
||||
|
||||
packet request;
|
||||
request.encode(path);
|
||||
request.encode(mode);
|
||||
|
||||
std::uint32_t service_flags = 0u;
|
||||
return packet_client_.send(__FUNCTION__, request, service_flags);
|
||||
std::uint32_t service_flags{};
|
||||
return packet_client_.send(function_name, request, service_flags);
|
||||
}
|
||||
|
||||
auto remote_client::fuse_chown(const char *path, const remote::user_id &uid,
|
||||
const remote::group_id &gid)
|
||||
-> packet::error_type {
|
||||
constexpr const auto *function_name = static_cast<const char *>(__FUNCTION__);
|
||||
|
||||
packet request;
|
||||
request.encode(path);
|
||||
request.encode(uid);
|
||||
request.encode(gid);
|
||||
|
||||
std::uint32_t service_flags = 0u;
|
||||
return packet_client_.send(__FUNCTION__, request, service_flags);
|
||||
std::uint32_t service_flags{};
|
||||
return packet_client_.send(function_name, request, service_flags);
|
||||
}
|
||||
|
||||
auto remote_client::fuse_destroy() -> packet::error_type {
|
||||
std::uint32_t service_flags = 0u;
|
||||
return packet_client_.send(__FUNCTION__, service_flags);
|
||||
constexpr const auto *function_name = static_cast<const char *>(__FUNCTION__);
|
||||
|
||||
std::uint32_t service_flags{};
|
||||
return packet_client_.send(function_name, service_flags);
|
||||
}
|
||||
|
||||
/*packet::error_type remote_client::fuse_fallocate(const char *path, const
|
||||
@@ -90,14 +100,16 @@ std::int32_t &mode, const remote::file_offset &offset, const remote::file_offset
|
||||
request.encode(length);
|
||||
request.encode(handle);
|
||||
|
||||
std::uint32_t service_flags = 0u;
|
||||
return packetClient_.send(__FUNCTION__, request, service_flags);
|
||||
std::uint32_t service_flags {};
|
||||
return packetClient_.send(function_name, request, service_flags);
|
||||
}*/
|
||||
|
||||
auto remote_client::fuse_fgetattr(const char *path, remote::stat &st,
|
||||
bool &directory,
|
||||
const remote::file_handle &handle)
|
||||
-> packet::error_type {
|
||||
constexpr const auto *function_name = static_cast<const char *>(__FUNCTION__);
|
||||
|
||||
packet request;
|
||||
request.encode(path);
|
||||
request.encode(handle);
|
||||
@@ -105,12 +117,12 @@ auto remote_client::fuse_fgetattr(const char *path, remote::stat &st,
|
||||
request.encode(gid_);
|
||||
|
||||
packet response;
|
||||
std::uint32_t service_flags = 0u;
|
||||
std::uint32_t service_flags{};
|
||||
auto ret =
|
||||
packet_client_.send(__FUNCTION__, request, response, service_flags);
|
||||
packet_client_.send(function_name, request, response, service_flags);
|
||||
if (ret == 0) {
|
||||
if ((ret = response.decode(st)) == 0) {
|
||||
std::uint8_t d = 0u;
|
||||
std::uint8_t d{};
|
||||
if ((ret = response.decode(d)) == 0) {
|
||||
directory = static_cast<bool>(d);
|
||||
}
|
||||
@@ -124,51 +136,59 @@ auto remote_client::fuse_fsetattr_x(const char *path,
|
||||
const remote::setattr_x &attr,
|
||||
const remote::file_handle &handle)
|
||||
-> packet::error_type {
|
||||
constexpr const auto *function_name = static_cast<const char *>(__FUNCTION__);
|
||||
|
||||
packet request;
|
||||
request.encode(path);
|
||||
request.encode(attr);
|
||||
request.encode(handle);
|
||||
|
||||
std::uint32_t service_flags = 0u;
|
||||
return packet_client_.send(__FUNCTION__, request, service_flags);
|
||||
std::uint32_t service_flags{};
|
||||
return packet_client_.send(function_name, request, service_flags);
|
||||
}
|
||||
|
||||
auto remote_client::fuse_fsync(const char *path, const std::int32_t &datasync,
|
||||
const remote::file_handle &handle)
|
||||
-> packet::error_type {
|
||||
constexpr const auto *function_name = static_cast<const char *>(__FUNCTION__);
|
||||
|
||||
packet request;
|
||||
request.encode(path);
|
||||
request.encode(datasync);
|
||||
request.encode(handle);
|
||||
|
||||
std::uint32_t service_flags = 0u;
|
||||
return packet_client_.send(__FUNCTION__, request, service_flags);
|
||||
std::uint32_t service_flags{};
|
||||
return packet_client_.send(function_name, request, service_flags);
|
||||
}
|
||||
|
||||
auto remote_client::fuse_ftruncate(const char *path,
|
||||
const remote::file_offset &size,
|
||||
const remote::file_handle &handle)
|
||||
-> packet::error_type {
|
||||
constexpr const auto *function_name = static_cast<const char *>(__FUNCTION__);
|
||||
|
||||
packet request;
|
||||
request.encode(path);
|
||||
request.encode(size);
|
||||
request.encode(handle);
|
||||
|
||||
std::uint32_t service_flags = 0u;
|
||||
return packet_client_.send(__FUNCTION__, request, service_flags);
|
||||
std::uint32_t service_flags{};
|
||||
return packet_client_.send(function_name, request, service_flags);
|
||||
}
|
||||
|
||||
auto remote_client::fuse_getattr(const char *path, remote::stat &st,
|
||||
bool &directory) -> packet::error_type {
|
||||
constexpr const auto *function_name = static_cast<const char *>(__FUNCTION__);
|
||||
|
||||
packet request;
|
||||
request.encode(path);
|
||||
request.encode(uid_);
|
||||
request.encode(gid_);
|
||||
|
||||
packet response;
|
||||
std::uint32_t service_flags = 0u;
|
||||
std::uint32_t service_flags{};
|
||||
auto ret =
|
||||
packet_client_.send(__FUNCTION__, request, response, service_flags);
|
||||
packet_client_.send(function_name, request, response, service_flags);
|
||||
if (ret == 0) {
|
||||
if ((ret = response.decode(st)) == 0) {
|
||||
std::uint8_t d = 0;
|
||||
@@ -188,8 +208,8 @@ packet request; request.encode(path); request.encode(name);
|
||||
request.encode(size);
|
||||
|
||||
packet response;
|
||||
std::uint32_t service_flags = 0u;
|
||||
if ((ret = packetClient_.send(__FUNCTION__, request, response,
|
||||
std::uint32_t service_flags {};
|
||||
if ((ret = packetClient_.send(function_name, request, response,
|
||||
service_flags)) == 0) { remote::file_size size2; if ((ret =
|
||||
response.decode(size2)) == 0) { if (size2 >
|
||||
std::numeric_limits<std::size_t>::max()) { ret = -ERANGE; } else { memcpy(value,
|
||||
@@ -211,8 +231,8 @@ packet::error_type ret = 0; if (size > std::numeric_limits<std::size_t>::max())
|
||||
request.encode(position);
|
||||
|
||||
packet response;
|
||||
std::uint32_t service_flags = 0u;
|
||||
if ((ret = packetClient_.send(__FUNCTION__, request, response,
|
||||
std::uint32_t service_flags {};
|
||||
if ((ret = packetClient_.send(function_name, request, response,
|
||||
service_flags)) == 0) { remote::file_size size2; if ((ret =
|
||||
response.decode(size2)) == 0) { if (size2 >
|
||||
std::numeric_limits<std::size_t>::max()) { ret = -ERANGE; } else { memcpy(value,
|
||||
@@ -229,13 +249,15 @@ auto remote_client::fuse_getxtimes(const char *path,
|
||||
remote::file_time &bkuptime,
|
||||
remote::file_time &crtime)
|
||||
-> packet::error_type {
|
||||
constexpr const auto *function_name = static_cast<const char *>(__FUNCTION__);
|
||||
|
||||
packet request;
|
||||
request.encode(path);
|
||||
|
||||
packet response;
|
||||
std::uint32_t service_flags = 0u;
|
||||
std::uint32_t service_flags{};
|
||||
auto ret =
|
||||
packet_client_.send(__FUNCTION__, request, response, service_flags);
|
||||
packet_client_.send(function_name, request, response, service_flags);
|
||||
if (ret == 0) {
|
||||
DECODE_OR_RETURN(&response, bkuptime);
|
||||
DECODE_OR_RETURN(&response, crtime);
|
||||
@@ -245,8 +267,10 @@ auto remote_client::fuse_getxtimes(const char *path,
|
||||
}
|
||||
|
||||
auto remote_client::fuse_init() -> packet::error_type {
|
||||
std::uint32_t service_flags = 0u;
|
||||
return packet_client_.send(__FUNCTION__, service_flags);
|
||||
constexpr const auto *function_name = static_cast<const char *>(__FUNCTION__);
|
||||
|
||||
std::uint32_t service_flags{};
|
||||
return packet_client_.send(function_name, service_flags);
|
||||
}
|
||||
|
||||
/*packet::error_type remote_client::fuse_listxattr(const char *path, char
|
||||
@@ -255,8 +279,8 @@ std::numeric_limits<std::size_t>::max()) { ret = -ERANGE; } else { packet
|
||||
request; request.encode(path); request.encode(size);
|
||||
|
||||
packet response;
|
||||
std::uint32_t service_flags = 0u;
|
||||
if ((ret = packetClient_.send(__FUNCTION__, request, response,
|
||||
std::uint32_t service_flags {};
|
||||
if ((ret = packetClient_.send(function_name, request, response,
|
||||
service_flags)) == 0) { remote::file_size size2; if ((ret =
|
||||
response.decode(size2)) == 0) { if (size2 >
|
||||
std::numeric_limits<std::size_t>::max()) { ret = -ERANGE; } else {
|
||||
@@ -272,23 +296,27 @@ static_cast<std::size_t>(size2));
|
||||
|
||||
auto remote_client::fuse_mkdir(const char *path, const remote::file_mode &mode)
|
||||
-> packet::error_type {
|
||||
constexpr const auto *function_name = static_cast<const char *>(__FUNCTION__);
|
||||
|
||||
packet request;
|
||||
request.encode(path);
|
||||
request.encode(mode);
|
||||
|
||||
std::uint32_t service_flags = 0u;
|
||||
return packet_client_.send(__FUNCTION__, request, service_flags);
|
||||
std::uint32_t service_flags{};
|
||||
return packet_client_.send(function_name, request, service_flags);
|
||||
}
|
||||
|
||||
auto remote_client::fuse_opendir(const char *path, remote::file_handle &handle)
|
||||
-> packet::error_type {
|
||||
constexpr const auto *function_name = static_cast<const char *>(__FUNCTION__);
|
||||
|
||||
packet request;
|
||||
request.encode(path);
|
||||
|
||||
packet response;
|
||||
std::uint32_t service_flags = 0u;
|
||||
std::uint32_t service_flags{};
|
||||
auto ret =
|
||||
packet_client_.send(__FUNCTION__, request, response, service_flags);
|
||||
packet_client_.send(function_name, request, response, service_flags);
|
||||
if (ret == 0) {
|
||||
ret = response.decode(handle);
|
||||
}
|
||||
@@ -300,15 +328,17 @@ auto remote_client::fuse_create(const char *path, const remote::file_mode &mode,
|
||||
const remote::open_flags &flags,
|
||||
remote::file_handle &handle)
|
||||
-> packet::error_type {
|
||||
constexpr const auto *function_name = static_cast<const char *>(__FUNCTION__);
|
||||
|
||||
packet request;
|
||||
request.encode(path);
|
||||
request.encode(mode);
|
||||
request.encode(flags);
|
||||
|
||||
packet response;
|
||||
std::uint32_t service_flags = 0u;
|
||||
std::uint32_t service_flags{};
|
||||
auto ret =
|
||||
packet_client_.send(__FUNCTION__, request, response, service_flags);
|
||||
packet_client_.send(function_name, request, response, service_flags);
|
||||
if (ret == 0) {
|
||||
ret = response.decode(handle);
|
||||
}
|
||||
@@ -319,14 +349,16 @@ auto remote_client::fuse_create(const char *path, const remote::file_mode &mode,
|
||||
auto remote_client::fuse_open(const char *path, const remote::open_flags &flags,
|
||||
remote::file_handle &handle)
|
||||
-> packet::error_type {
|
||||
constexpr const auto *function_name = static_cast<const char *>(__FUNCTION__);
|
||||
|
||||
packet request;
|
||||
request.encode(path);
|
||||
request.encode(flags);
|
||||
|
||||
packet response;
|
||||
std::uint32_t service_flags = 0u;
|
||||
std::uint32_t service_flags{};
|
||||
auto ret =
|
||||
packet_client_.send(__FUNCTION__, request, response, service_flags);
|
||||
packet_client_.send(function_name, request, response, service_flags);
|
||||
if (ret == 0) {
|
||||
ret = response.decode(handle);
|
||||
}
|
||||
@@ -339,6 +371,8 @@ auto remote_client::fuse_read(const char *path, char *buffer,
|
||||
const remote::file_offset &read_offset,
|
||||
const remote::file_handle &handle)
|
||||
-> packet::error_type {
|
||||
constexpr const auto *function_name = static_cast<const char *>(__FUNCTION__);
|
||||
|
||||
packet request;
|
||||
request.encode(path);
|
||||
request.encode(read_size);
|
||||
@@ -346,11 +380,11 @@ auto remote_client::fuse_read(const char *path, char *buffer,
|
||||
request.encode(handle);
|
||||
|
||||
packet response;
|
||||
std::uint32_t service_flags = 0u;
|
||||
std::uint32_t service_flags{};
|
||||
auto ret =
|
||||
packet_client_.send(__FUNCTION__, request, response, service_flags);
|
||||
packet_client_.send(function_name, request, response, service_flags);
|
||||
if (ret > 0) {
|
||||
memcpy(buffer, response.current_pointer(), ret);
|
||||
memcpy(buffer, response.current_pointer(), static_cast<std::size_t>(ret));
|
||||
}
|
||||
|
||||
return ret;
|
||||
@@ -358,12 +392,14 @@ auto remote_client::fuse_read(const char *path, char *buffer,
|
||||
|
||||
auto remote_client::fuse_rename(const char *from, const char *to)
|
||||
-> packet::error_type {
|
||||
constexpr const auto *function_name = static_cast<const char *>(__FUNCTION__);
|
||||
|
||||
packet request;
|
||||
request.encode(from);
|
||||
request.encode(to);
|
||||
|
||||
std::uint32_t service_flags = 0u;
|
||||
return packet_client_.send(__FUNCTION__, request, service_flags);
|
||||
std::uint32_t service_flags{};
|
||||
return packet_client_.send(function_name, request, service_flags);
|
||||
}
|
||||
|
||||
auto remote_client::fuse_write(const char *path, const char *buffer,
|
||||
@@ -371,6 +407,8 @@ auto remote_client::fuse_write(const char *path, const char *buffer,
|
||||
const remote::file_offset &write_offset,
|
||||
const remote::file_handle &handle)
|
||||
-> packet::error_type {
|
||||
constexpr const auto *function_name = static_cast<const char *>(__FUNCTION__);
|
||||
|
||||
if (write_size > std::numeric_limits<std::size_t>::max()) {
|
||||
return -ERANGE;
|
||||
}
|
||||
@@ -382,8 +420,8 @@ auto remote_client::fuse_write(const char *path, const char *buffer,
|
||||
request.encode(write_offset);
|
||||
request.encode(handle);
|
||||
|
||||
std::uint32_t service_flags = 0u;
|
||||
return packet_client_.send(__FUNCTION__, request, service_flags);
|
||||
std::uint32_t service_flags{};
|
||||
return packet_client_.send(function_name, request, service_flags);
|
||||
}
|
||||
|
||||
auto remote_client::fuse_write_base64(const char *path, const char *buffer,
|
||||
@@ -391,6 +429,8 @@ auto remote_client::fuse_write_base64(const char *path, const char *buffer,
|
||||
const remote::file_offset &write_offset,
|
||||
const remote::file_handle &handle)
|
||||
-> packet::error_type {
|
||||
constexpr const auto *function_name = static_cast<const char *>(__FUNCTION__);
|
||||
|
||||
if (write_size > std::numeric_limits<std::size_t>::max()) {
|
||||
return -ERANGE;
|
||||
}
|
||||
@@ -402,23 +442,25 @@ auto remote_client::fuse_write_base64(const char *path, const char *buffer,
|
||||
request.encode(write_offset);
|
||||
request.encode(handle);
|
||||
|
||||
std::uint32_t service_flags = 0u;
|
||||
return packet_client_.send(__FUNCTION__, request, service_flags);
|
||||
std::uint32_t service_flags{};
|
||||
return packet_client_.send(function_name, request, service_flags);
|
||||
}
|
||||
|
||||
auto remote_client::fuse_readdir(const char *path,
|
||||
const remote::file_offset &offset,
|
||||
const remote::file_handle &handle,
|
||||
std::string &item_path) -> packet::error_type {
|
||||
constexpr const auto *function_name = static_cast<const char *>(__FUNCTION__);
|
||||
|
||||
packet request;
|
||||
request.encode(path);
|
||||
request.encode(offset);
|
||||
request.encode(handle);
|
||||
|
||||
packet response;
|
||||
std::uint32_t service_flags = 0u;
|
||||
std::uint32_t service_flags{};
|
||||
auto ret =
|
||||
packet_client_.send(__FUNCTION__, request, response, service_flags);
|
||||
packet_client_.send(function_name, request, response, service_flags);
|
||||
if (ret == 0) {
|
||||
DECODE_OR_IGNORE(&response, item_path);
|
||||
}
|
||||
@@ -429,90 +471,106 @@ auto remote_client::fuse_readdir(const char *path,
|
||||
auto remote_client::fuse_release(const char *path,
|
||||
const remote::file_handle &handle)
|
||||
-> packet::error_type {
|
||||
constexpr const auto *function_name = static_cast<const char *>(__FUNCTION__);
|
||||
|
||||
packet request;
|
||||
request.encode(path);
|
||||
request.encode(handle);
|
||||
|
||||
std::uint32_t service_flags = 0u;
|
||||
return packet_client_.send(__FUNCTION__, request, service_flags);
|
||||
std::uint32_t service_flags{};
|
||||
return packet_client_.send(function_name, request, service_flags);
|
||||
}
|
||||
|
||||
auto remote_client::fuse_releasedir(const char *path,
|
||||
const remote::file_handle &handle)
|
||||
-> packet::error_type {
|
||||
constexpr const auto *function_name = static_cast<const char *>(__FUNCTION__);
|
||||
|
||||
packet request;
|
||||
request.encode(path);
|
||||
request.encode(handle);
|
||||
|
||||
std::uint32_t service_flags = 0u;
|
||||
return packet_client_.send(__FUNCTION__, request, service_flags);
|
||||
std::uint32_t service_flags{};
|
||||
return packet_client_.send(function_name, request, service_flags);
|
||||
}
|
||||
|
||||
/*packet::error_type remote_client::fuse_removexattr(const char *path, const
|
||||
char *name) override { packet request; request.encode(path);
|
||||
request.Encode(name);
|
||||
|
||||
std::uint32_t service_flags = 0u;
|
||||
return packetClient_.send(__FUNCTION__, request, service_flags);
|
||||
std::uint32_t service_flags {};
|
||||
return packetClient_.send(function_name, request, service_flags);
|
||||
}*/
|
||||
|
||||
auto remote_client::fuse_rmdir(const char *path) -> packet::error_type {
|
||||
constexpr const auto *function_name = static_cast<const char *>(__FUNCTION__);
|
||||
|
||||
packet request;
|
||||
request.encode(path);
|
||||
|
||||
std::uint32_t service_flags = 0u;
|
||||
return packet_client_.send(__FUNCTION__, request, service_flags);
|
||||
std::uint32_t service_flags{};
|
||||
return packet_client_.send(function_name, request, service_flags);
|
||||
}
|
||||
|
||||
auto remote_client::fuse_setattr_x(const char *path, remote::setattr_x &attr)
|
||||
-> packet::error_type {
|
||||
constexpr const auto *function_name = static_cast<const char *>(__FUNCTION__);
|
||||
|
||||
packet request;
|
||||
request.encode(path);
|
||||
request.encode(attr);
|
||||
|
||||
std::uint32_t service_flags = 0u;
|
||||
return packet_client_.send(__FUNCTION__, request, service_flags);
|
||||
std::uint32_t service_flags{};
|
||||
return packet_client_.send(function_name, request, service_flags);
|
||||
}
|
||||
|
||||
auto remote_client::fuse_setbkuptime(const char *path,
|
||||
const remote::file_time &bkuptime)
|
||||
-> packet::error_type {
|
||||
constexpr const auto *function_name = static_cast<const char *>(__FUNCTION__);
|
||||
|
||||
packet request;
|
||||
request.encode(path);
|
||||
request.encode(bkuptime);
|
||||
|
||||
std::uint32_t service_flags = 0u;
|
||||
return packet_client_.send(__FUNCTION__, request, service_flags);
|
||||
std::uint32_t service_flags{};
|
||||
return packet_client_.send(function_name, request, service_flags);
|
||||
}
|
||||
|
||||
auto remote_client::fuse_setchgtime(const char *path,
|
||||
const remote::file_time &chgtime)
|
||||
-> packet::error_type {
|
||||
constexpr const auto *function_name = static_cast<const char *>(__FUNCTION__);
|
||||
|
||||
packet request;
|
||||
request.encode(path);
|
||||
request.encode(chgtime);
|
||||
|
||||
std::uint32_t service_flags = 0u;
|
||||
return packet_client_.send(__FUNCTION__, request, service_flags);
|
||||
std::uint32_t service_flags{};
|
||||
return packet_client_.send(function_name, request, service_flags);
|
||||
}
|
||||
|
||||
auto remote_client::fuse_setcrtime(const char *path,
|
||||
const remote::file_time &crtime)
|
||||
-> packet::error_type {
|
||||
constexpr const auto *function_name = static_cast<const char *>(__FUNCTION__);
|
||||
|
||||
packet request;
|
||||
request.encode(path);
|
||||
request.encode(crtime);
|
||||
|
||||
std::uint32_t service_flags = 0u;
|
||||
return packet_client_.send(__FUNCTION__, request, service_flags);
|
||||
std::uint32_t service_flags{};
|
||||
return packet_client_.send(function_name, request, service_flags);
|
||||
}
|
||||
|
||||
auto remote_client::fuse_setvolname(const char *volname) -> packet::error_type {
|
||||
constexpr const auto *function_name = static_cast<const char *>(__FUNCTION__);
|
||||
|
||||
packet request;
|
||||
request.encode(volname);
|
||||
|
||||
std::uint32_t service_flags = 0u;
|
||||
return packet_client_.send(__FUNCTION__, request, service_flags);
|
||||
std::uint32_t service_flags{};
|
||||
return packet_client_.send(function_name, request, service_flags);
|
||||
}
|
||||
|
||||
/*packet::error_type remote_client::fuse_setxattr(const char *path, const char
|
||||
@@ -523,8 +581,8 @@ request; request.encode(path); request.encode(name); request.encode(size);
|
||||
request.encode(value, static_cast<std::size_t>(size));
|
||||
request.encode(flags);
|
||||
|
||||
std::uint32_t service_flags = 0u;
|
||||
ret = packetClient_.send(__FUNCTION__, request, service_flags);
|
||||
std::uint32_t service_flags {};
|
||||
ret = packetClient_.send(function_name, request, service_flags);
|
||||
}
|
||||
|
||||
return ret;
|
||||
@@ -538,8 +596,8 @@ packet request; request.encode(path); request.Encode(name);
|
||||
request.Encode(size); request.encode(value, static_cast<std::size_t>(size));
|
||||
request.encode(flags); request.encode(position);
|
||||
|
||||
std::uint32_t service_flags = 0u;
|
||||
ret = packetClient_.send(__FUNCTION__, request, service_flags);
|
||||
std::uint32_t service_flags {};
|
||||
ret = packetClient_.send(function_name, request, service_flags);
|
||||
}
|
||||
|
||||
return ret;
|
||||
@@ -547,14 +605,16 @@ request.encode(flags); request.encode(position);
|
||||
|
||||
auto remote_client::fuse_statfs(const char *path, std::uint64_t frsize,
|
||||
remote::statfs &st) -> packet::error_type {
|
||||
constexpr const auto *function_name = static_cast<const char *>(__FUNCTION__);
|
||||
|
||||
packet request;
|
||||
request.encode(path);
|
||||
request.encode(frsize);
|
||||
|
||||
packet response;
|
||||
std::uint32_t service_flags = 0u;
|
||||
std::uint32_t service_flags{};
|
||||
auto ret =
|
||||
packet_client_.send(__FUNCTION__, request, response, service_flags);
|
||||
packet_client_.send(function_name, request, response, service_flags);
|
||||
if (ret == 0) {
|
||||
ret = response.decode(st);
|
||||
}
|
||||
@@ -564,14 +624,16 @@ auto remote_client::fuse_statfs(const char *path, std::uint64_t frsize,
|
||||
|
||||
auto remote_client::fuse_statfs_x(const char *path, std::uint64_t bsize,
|
||||
remote::statfs_x &st) -> packet::error_type {
|
||||
constexpr const auto *function_name = static_cast<const char *>(__FUNCTION__);
|
||||
|
||||
packet request;
|
||||
request.encode(path);
|
||||
request.encode(bsize);
|
||||
|
||||
packet response;
|
||||
std::uint32_t service_flags = 0u;
|
||||
std::uint32_t service_flags{};
|
||||
auto ret =
|
||||
packet_client_.send(__FUNCTION__, request, response, service_flags);
|
||||
packet_client_.send(function_name, request, response, service_flags);
|
||||
if (ret == 0) {
|
||||
ret = response.decode(st);
|
||||
}
|
||||
@@ -582,45 +644,53 @@ auto remote_client::fuse_statfs_x(const char *path, std::uint64_t bsize,
|
||||
auto remote_client::fuse_truncate(const char *path,
|
||||
const remote::file_offset &size)
|
||||
-> packet::error_type {
|
||||
constexpr const auto *function_name = static_cast<const char *>(__FUNCTION__);
|
||||
|
||||
packet request;
|
||||
request.encode(path);
|
||||
request.encode(size);
|
||||
|
||||
std::uint32_t service_flags = 0u;
|
||||
return packet_client_.send(__FUNCTION__, request, service_flags);
|
||||
std::uint32_t service_flags{};
|
||||
return packet_client_.send(function_name, request, service_flags);
|
||||
}
|
||||
|
||||
auto remote_client::fuse_unlink(const char *path) -> packet::error_type {
|
||||
constexpr const auto *function_name = static_cast<const char *>(__FUNCTION__);
|
||||
|
||||
packet request;
|
||||
request.encode(path);
|
||||
|
||||
std::uint32_t service_flags = 0u;
|
||||
return packet_client_.send(__FUNCTION__, request, service_flags);
|
||||
std::uint32_t service_flags{};
|
||||
return packet_client_.send(function_name, request, service_flags);
|
||||
}
|
||||
|
||||
auto remote_client::fuse_utimens(const char *path, const remote::file_time *tv,
|
||||
std::uint64_t op0, std::uint64_t op1)
|
||||
-> packet::error_type {
|
||||
constexpr const auto *function_name = static_cast<const char *>(__FUNCTION__);
|
||||
|
||||
packet request;
|
||||
request.encode(path);
|
||||
request.encode(&tv[0], sizeof(remote::file_time) * 2);
|
||||
request.encode(op0);
|
||||
request.encode(op1);
|
||||
|
||||
std::uint32_t service_flags = 0u;
|
||||
return packet_client_.send(__FUNCTION__, request, service_flags);
|
||||
std::uint32_t service_flags{};
|
||||
return packet_client_.send(function_name, request, service_flags);
|
||||
}
|
||||
|
||||
auto remote_client::json_create_directory_snapshot(const std::string &path,
|
||||
json &json_data)
|
||||
-> packet::error_type {
|
||||
constexpr const auto *function_name = static_cast<const char *>(__FUNCTION__);
|
||||
|
||||
packet request;
|
||||
request.encode(path);
|
||||
|
||||
packet response;
|
||||
std::uint32_t service_flags = 0u;
|
||||
std::uint32_t service_flags{};
|
||||
auto ret =
|
||||
packet_client_.send(__FUNCTION__, request, response, service_flags);
|
||||
packet_client_.send(function_name, request, response, service_flags);
|
||||
if (ret == 0) {
|
||||
ret = packet::decode_json(response, json_data);
|
||||
}
|
||||
@@ -631,15 +701,17 @@ auto remote_client::json_create_directory_snapshot(const std::string &path,
|
||||
auto remote_client::json_read_directory_snapshot(
|
||||
const std::string &path, const remote::file_handle &handle,
|
||||
std::uint32_t page, json &json_data) -> packet::error_type {
|
||||
constexpr const auto *function_name = static_cast<const char *>(__FUNCTION__);
|
||||
|
||||
packet request;
|
||||
request.encode(path);
|
||||
request.encode(handle);
|
||||
request.encode(page);
|
||||
|
||||
packet response;
|
||||
std::uint32_t service_flags = 0u;
|
||||
std::uint32_t service_flags{};
|
||||
auto ret =
|
||||
packet_client_.send(__FUNCTION__, request, response, service_flags);
|
||||
packet_client_.send(function_name, request, response, service_flags);
|
||||
if (ret == 0) {
|
||||
ret = packet::decode_json(response, json_data);
|
||||
}
|
||||
@@ -650,12 +722,14 @@ auto remote_client::json_read_directory_snapshot(
|
||||
auto remote_client::json_release_directory_snapshot(
|
||||
const std::string &path, const remote::file_handle &handle)
|
||||
-> packet::error_type {
|
||||
constexpr const auto *function_name = static_cast<const char *>(__FUNCTION__);
|
||||
|
||||
packet request;
|
||||
request.encode(path);
|
||||
request.encode(handle);
|
||||
|
||||
std::uint32_t service_flags = 0u;
|
||||
return packet_client_.send(__FUNCTION__, request, service_flags);
|
||||
std::uint32_t service_flags{};
|
||||
return packet_client_.send(function_name, request, service_flags);
|
||||
}
|
||||
|
||||
void remote_client::set_fuse_uid_gid(const remote::user_id &uid,
|
||||
|
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
Copyright <2018-2023> <scott.e.graves@protonmail.com>
|
||||
Copyright <2018-2024> <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
|
||||
@@ -54,7 +54,7 @@ api_error remote_fuse_drive::chflags_impl(std::string api_path,
|
||||
|
||||
#if FUSE_USE_VERSION >= 30
|
||||
auto remote_fuse_drive::chmod_impl(std::string api_path, mode_t mode,
|
||||
struct fuse_file_info * /*fi*/)
|
||||
struct fuse_file_info * /*f_info*/)
|
||||
-> api_error {
|
||||
#else
|
||||
auto remote_fuse_drive::chmod_impl(std::string api_path, mode_t mode)
|
||||
@@ -66,7 +66,7 @@ auto remote_fuse_drive::chmod_impl(std::string api_path, mode_t mode)
|
||||
|
||||
#if FUSE_USE_VERSION >= 30
|
||||
auto remote_fuse_drive::chown_impl(std::string api_path, uid_t uid, gid_t gid,
|
||||
struct fuse_file_info * /*fi*/)
|
||||
struct fuse_file_info * /*f_info*/)
|
||||
-> api_error {
|
||||
#else
|
||||
auto remote_fuse_drive::chown_impl(std::string api_path, uid_t uid, gid_t gid)
|
||||
@@ -77,14 +77,17 @@ auto remote_fuse_drive::chown_impl(std::string api_path, uid_t uid, gid_t gid)
|
||||
}
|
||||
|
||||
auto remote_fuse_drive::create_impl(std::string api_path, mode_t mode,
|
||||
struct fuse_file_info *fi) -> api_error {
|
||||
struct fuse_file_info *f_info)
|
||||
-> api_error {
|
||||
return utils::to_api_error(remote_instance_->fuse_create(
|
||||
api_path.c_str(), static_cast<remote::file_mode>(mode),
|
||||
remote::create_open_flags(static_cast<std::uint32_t>(fi->flags)),
|
||||
fi->fh));
|
||||
remote::create_open_flags(static_cast<std::uint32_t>(f_info->flags)),
|
||||
f_info->fh));
|
||||
}
|
||||
|
||||
void remote_fuse_drive::destroy_impl(void * /*ptr*/) {
|
||||
void remote_fuse_drive::destroy_impl(void *ptr) {
|
||||
constexpr const auto *function_name = static_cast<const char *>(__FUNCTION__);
|
||||
|
||||
event_system::instance().raise<drive_unmount_pending>(get_mount_location());
|
||||
|
||||
if (server_) {
|
||||
@@ -95,7 +98,7 @@ void remote_fuse_drive::destroy_impl(void * /*ptr*/) {
|
||||
if (remote_instance_) {
|
||||
const auto res = remote_instance_->fuse_destroy();
|
||||
if (res != 0) {
|
||||
utils::error::raise_error(__FUNCTION__,
|
||||
utils::error::raise_error(function_name,
|
||||
"remote fuse_destroy() failed|err|" +
|
||||
std::to_string(res));
|
||||
}
|
||||
@@ -103,21 +106,25 @@ void remote_fuse_drive::destroy_impl(void * /*ptr*/) {
|
||||
}
|
||||
|
||||
if (not lock_data_.set_mount_state(false, "", -1)) {
|
||||
utils::error::raise_error(__FUNCTION__, "failed to set mount state");
|
||||
utils::error::raise_error(function_name, "failed to set mount state");
|
||||
}
|
||||
|
||||
event_system::instance().raise<drive_unmounted>(get_mount_location());
|
||||
|
||||
fuse_base::destroy_impl(ptr);
|
||||
}
|
||||
|
||||
auto remote_fuse_drive::fgetattr_impl(std::string api_path, struct stat *st,
|
||||
struct fuse_file_info *fi) -> api_error {
|
||||
remote::stat r{};
|
||||
auto remote_fuse_drive::fgetattr_impl(std::string api_path,
|
||||
struct stat *unix_st,
|
||||
struct fuse_file_info *f_info)
|
||||
-> api_error {
|
||||
remote::stat r_stat{};
|
||||
auto directory = false;
|
||||
|
||||
const auto res =
|
||||
remote_instance_->fuse_fgetattr(api_path.c_str(), r, directory, fi->fh);
|
||||
const auto res = remote_instance_->fuse_fgetattr(api_path.c_str(), r_stat,
|
||||
directory, f_info->fh);
|
||||
if (res == 0) {
|
||||
populate_stat(r, directory, *st);
|
||||
populate_stat(r_stat, directory, *unix_st);
|
||||
}
|
||||
|
||||
return utils::to_api_error(res);
|
||||
@@ -126,7 +133,7 @@ auto remote_fuse_drive::fgetattr_impl(std::string api_path, struct stat *st,
|
||||
#ifdef __APPLE__
|
||||
api_error remote_fuse_drive::fsetattr_x_impl(std::string api_path,
|
||||
struct setattr_x *attr,
|
||||
struct fuse_file_info *fi) {
|
||||
struct fuse_file_info *f_info) {
|
||||
remote::setattr_x attributes{};
|
||||
attributes.valid = attr->valid;
|
||||
attributes.mode = attr->mode;
|
||||
@@ -144,41 +151,42 @@ api_error remote_fuse_drive::fsetattr_x_impl(std::string api_path,
|
||||
attributes.bkuptime =
|
||||
((attr->bkuptime.tv_sec * NANOS_PER_SECOND) + attr->bkuptime.tv_nsec);
|
||||
attributes.flags = attr->flags;
|
||||
return utils::to_api_error(
|
||||
remote_instance_->fuse_fsetattr_x(api_path.c_str(), attributes, fi->fh));
|
||||
return utils::to_api_error(remote_instance_->fuse_fsetattr_x(
|
||||
api_path.c_str(), attributes, f_info->fh));
|
||||
}
|
||||
#endif
|
||||
|
||||
auto remote_fuse_drive::fsync_impl(std::string api_path, int datasync,
|
||||
struct fuse_file_info *fi) -> api_error {
|
||||
struct fuse_file_info *f_info) -> api_error {
|
||||
|
||||
return utils::to_api_error(
|
||||
remote_instance_->fuse_fsync(api_path.c_str(), datasync, fi->fh));
|
||||
remote_instance_->fuse_fsync(api_path.c_str(), datasync, f_info->fh));
|
||||
}
|
||||
|
||||
#if FUSE_USE_VERSION < 30
|
||||
auto remote_fuse_drive::ftruncate_impl(std::string api_path, off_t size,
|
||||
struct fuse_file_info *fi) -> api_error {
|
||||
struct fuse_file_info *f_info)
|
||||
-> api_error {
|
||||
return utils::to_api_error(
|
||||
remote_instance_->fuse_ftruncate(api_path.c_str(), size, fi->fh));
|
||||
remote_instance_->fuse_ftruncate(api_path.c_str(), size, f_info->fh));
|
||||
}
|
||||
#endif
|
||||
|
||||
#if FUSE_USE_VERSION >= 30
|
||||
auto remote_fuse_drive::getattr_impl(std::string api_path, struct stat *st,
|
||||
struct fuse_file_info * /*fi*/)
|
||||
auto remote_fuse_drive::getattr_impl(std::string api_path, struct stat *unix_st,
|
||||
struct fuse_file_info * /*f_info*/)
|
||||
-> api_error {
|
||||
#else
|
||||
auto remote_fuse_drive::getattr_impl(std::string api_path, struct stat *st)
|
||||
auto remote_fuse_drive::getattr_impl(std::string api_path, struct stat *unix_st)
|
||||
-> api_error {
|
||||
#endif
|
||||
bool directory = false;
|
||||
remote::stat r{};
|
||||
remote::stat r_stat{};
|
||||
|
||||
const auto res =
|
||||
remote_instance_->fuse_getattr(api_path.c_str(), r, directory);
|
||||
remote_instance_->fuse_getattr(api_path.c_str(), r_stat, directory);
|
||||
if (res == 0) {
|
||||
populate_stat(r, directory, *st);
|
||||
populate_stat(r_stat, directory, *unix_st);
|
||||
}
|
||||
|
||||
return utils::to_api_error(res);
|
||||
@@ -214,7 +222,14 @@ auto remote_fuse_drive::init_impl(struct fuse_conn_info *conn,
|
||||
#else
|
||||
auto remote_fuse_drive::init_impl(struct fuse_conn_info *conn) -> void * {
|
||||
#endif
|
||||
utils::file::change_to_process_directory();
|
||||
constexpr const auto *function_name = static_cast<const char *>(__FUNCTION__);
|
||||
|
||||
#if FUSE_USE_VERSION >= 30
|
||||
auto *ret = fuse_base::init_impl(conn, cfg);
|
||||
#else
|
||||
auto *ret = fuse_base::init_impl(conn);
|
||||
#endif
|
||||
|
||||
was_mounted_ = true;
|
||||
|
||||
if (console_enabled_) {
|
||||
@@ -225,14 +240,14 @@ auto remote_fuse_drive::init_impl(struct fuse_conn_info *conn) -> void * {
|
||||
event_system::instance().start();
|
||||
|
||||
if (not lock_data_.set_mount_state(true, get_mount_location(), getpid())) {
|
||||
utils::error::raise_error(__FUNCTION__, "failed to set mount state");
|
||||
utils::error::raise_error(function_name, "failed to set mount state");
|
||||
}
|
||||
|
||||
remote_instance_ = factory_();
|
||||
remote_instance_->set_fuse_uid_gid(getuid(), getgid());
|
||||
|
||||
if (remote_instance_->fuse_init() != 0) {
|
||||
utils::error::raise_error(__FUNCTION__,
|
||||
utils::error::raise_error(function_name,
|
||||
"failed to connect to remote server");
|
||||
event_system::instance().raise<unmount_requested>();
|
||||
} else {
|
||||
@@ -241,11 +256,7 @@ auto remote_fuse_drive::init_impl(struct fuse_conn_info *conn) -> void * {
|
||||
event_system::instance().raise<drive_mounted>(get_mount_location());
|
||||
}
|
||||
|
||||
#if FUSE_USE_VERSION >= 30
|
||||
return fuse_base::init_impl(conn, cfg);
|
||||
#else
|
||||
return fuse_base::init_impl(conn);
|
||||
#endif
|
||||
return ret;
|
||||
}
|
||||
|
||||
auto remote_fuse_drive::mkdir_impl(std::string api_path, mode_t mode)
|
||||
@@ -264,76 +275,88 @@ void remote_fuse_drive::notify_fuse_main_exit(int &ret) {
|
||||
}
|
||||
|
||||
auto remote_fuse_drive::open_impl(std::string api_path,
|
||||
struct fuse_file_info *fi) -> api_error {
|
||||
struct fuse_file_info *f_info) -> api_error {
|
||||
return utils::to_api_error(remote_instance_->fuse_open(
|
||||
api_path.c_str(), remote::create_open_flags(fi->flags), fi->fh));
|
||||
api_path.c_str(),
|
||||
remote::create_open_flags(static_cast<std::uint32_t>(f_info->flags)),
|
||||
f_info->fh));
|
||||
}
|
||||
|
||||
auto remote_fuse_drive::opendir_impl(std::string api_path,
|
||||
struct fuse_file_info *fi) -> api_error {
|
||||
struct fuse_file_info *f_info)
|
||||
-> api_error {
|
||||
|
||||
return utils::to_api_error(
|
||||
remote_instance_->fuse_opendir(api_path.c_str(), fi->fh));
|
||||
remote_instance_->fuse_opendir(api_path.c_str(), f_info->fh));
|
||||
}
|
||||
|
||||
void remote_fuse_drive::populate_stat(const remote::stat &r, bool directory,
|
||||
struct stat &st) {
|
||||
memset(&st, 0, sizeof(struct stat));
|
||||
void remote_fuse_drive::populate_stat(const remote::stat &r_stat,
|
||||
bool directory, struct stat &unix_st) {
|
||||
memset(&unix_st, 0, sizeof(struct stat));
|
||||
|
||||
#ifdef __APPLE__
|
||||
st.st_blksize = 0;
|
||||
unix_st.st_blksize = 0;
|
||||
|
||||
st.st_atimespec.tv_nsec = r.st_atimespec % NANOS_PER_SECOND;
|
||||
st.st_atimespec.tv_sec = r.st_atimespec / NANOS_PER_SECOND;
|
||||
unix_st.st_atimespec.tv_nsec = r_stat.st_atimespec % NANOS_PER_SECOND;
|
||||
unix_st.st_atimespec.tv_sec = r_stat.st_atimespec / NANOS_PER_SECOND;
|
||||
|
||||
st.st_birthtimespec.tv_nsec = r.st_birthtimespec % NANOS_PER_SECOND;
|
||||
st.st_birthtimespec.tv_sec = r.st_birthtimespec / NANOS_PER_SECOND;
|
||||
unix_st.st_birthtimespec.tv_nsec = r_stat.st_birthtimespec % NANOS_PER_SECOND;
|
||||
unix_st.st_birthtimespec.tv_sec = r_stat.st_birthtimespec / NANOS_PER_SECOND;
|
||||
|
||||
st.st_ctimespec.tv_nsec = r.st_ctimespec % NANOS_PER_SECOND;
|
||||
st.st_ctimespec.tv_sec = r.st_ctimespec / NANOS_PER_SECOND;
|
||||
unix_st.st_ctimespec.tv_nsec = r_stat.st_ctimespec % NANOS_PER_SECOND;
|
||||
unix_st.st_ctimespec.tv_sec = r_stat.st_ctimespec / NANOS_PER_SECOND;
|
||||
|
||||
st.st_mtimespec.tv_nsec = r.st_mtimespec % NANOS_PER_SECOND;
|
||||
st.st_mtimespec.tv_sec = r.st_mtimespec / NANOS_PER_SECOND;
|
||||
unix_st.st_mtimespec.tv_nsec = r_stat.st_mtimespec % NANOS_PER_SECOND;
|
||||
unix_st.st_mtimespec.tv_sec = r_stat.st_mtimespec / NANOS_PER_SECOND;
|
||||
|
||||
st.st_flags = r.st_flags;
|
||||
unix_st.st_flags = r_stat.st_flags;
|
||||
#else
|
||||
st.st_blksize = 4096;
|
||||
unix_st.st_blksize = 4096;
|
||||
|
||||
st.st_atim.tv_nsec = r.st_atimespec % NANOS_PER_SECOND;
|
||||
st.st_atim.tv_sec = r.st_atimespec / NANOS_PER_SECOND;
|
||||
unix_st.st_atim.tv_nsec =
|
||||
static_cast<suseconds_t>(r_stat.st_atimespec % NANOS_PER_SECOND);
|
||||
unix_st.st_atim.tv_sec =
|
||||
static_cast<suseconds_t>(r_stat.st_atimespec / NANOS_PER_SECOND);
|
||||
|
||||
st.st_ctim.tv_nsec = r.st_ctimespec % NANOS_PER_SECOND;
|
||||
st.st_ctim.tv_sec = r.st_ctimespec / NANOS_PER_SECOND;
|
||||
unix_st.st_ctim.tv_nsec =
|
||||
static_cast<suseconds_t>(r_stat.st_ctimespec % NANOS_PER_SECOND);
|
||||
unix_st.st_ctim.tv_sec =
|
||||
static_cast<suseconds_t>(r_stat.st_ctimespec / NANOS_PER_SECOND);
|
||||
|
||||
st.st_mtim.tv_nsec = r.st_mtimespec % NANOS_PER_SECOND;
|
||||
st.st_mtim.tv_sec = r.st_mtimespec / NANOS_PER_SECOND;
|
||||
unix_st.st_mtim.tv_nsec =
|
||||
static_cast<suseconds_t>(r_stat.st_mtimespec % NANOS_PER_SECOND);
|
||||
unix_st.st_mtim.tv_sec =
|
||||
static_cast<suseconds_t>(r_stat.st_mtimespec / NANOS_PER_SECOND);
|
||||
#endif
|
||||
if (not directory) {
|
||||
const auto block_size_stat = static_cast<std::uint64_t>(512u);
|
||||
const auto block_size = static_cast<std::uint64_t>(4096u);
|
||||
const auto size = utils::divide_with_ceiling(
|
||||
static_cast<std::uint64_t>(st.st_size), block_size) *
|
||||
block_size;
|
||||
st.st_blocks = std::max(block_size / block_size_stat,
|
||||
utils::divide_with_ceiling(size, block_size_stat));
|
||||
const auto block_size_stat = static_cast<std::uint64_t>(512U);
|
||||
const auto block_size = static_cast<std::uint64_t>(4096U);
|
||||
const auto size =
|
||||
utils::divide_with_ceiling(static_cast<std::uint64_t>(unix_st.st_size),
|
||||
block_size) *
|
||||
block_size;
|
||||
unix_st.st_blocks = static_cast<blkcnt_t>(
|
||||
std::max(block_size / block_size_stat,
|
||||
utils::divide_with_ceiling(size, block_size_stat)));
|
||||
}
|
||||
|
||||
st.st_gid = r.st_gid;
|
||||
st.st_mode = (directory ? S_IFDIR : S_IFREG) | r.st_mode;
|
||||
unix_st.st_gid = r_stat.st_gid;
|
||||
unix_st.st_mode = (directory ? S_IFDIR : S_IFREG) | r_stat.st_mode;
|
||||
|
||||
st.st_nlink = r.st_nlink;
|
||||
st.st_size = r.st_size;
|
||||
st.st_uid = r.st_uid;
|
||||
unix_st.st_nlink = r_stat.st_nlink;
|
||||
unix_st.st_size = static_cast<off_t>(r_stat.st_size);
|
||||
unix_st.st_uid = r_stat.st_uid;
|
||||
}
|
||||
|
||||
auto remote_fuse_drive::read_impl(std::string api_path, char *buffer,
|
||||
size_t read_size, off_t read_offset,
|
||||
struct fuse_file_info *fi,
|
||||
struct fuse_file_info *f_info,
|
||||
std::size_t &bytes_read) -> api_error {
|
||||
auto res = remote_instance_->fuse_read(api_path.c_str(), buffer, read_size,
|
||||
read_offset, fi->fh);
|
||||
auto res = remote_instance_->fuse_read(
|
||||
api_path.c_str(), buffer, read_size,
|
||||
static_cast<remote::file_offset>(read_offset), f_info->fh);
|
||||
if (res >= 0) {
|
||||
bytes_read = res;
|
||||
bytes_read = static_cast<size_t>(res);
|
||||
return api_error::success;
|
||||
}
|
||||
|
||||
@@ -343,19 +366,22 @@ auto remote_fuse_drive::read_impl(std::string api_path, char *buffer,
|
||||
#if FUSE_USE_VERSION >= 30
|
||||
auto remote_fuse_drive::readdir_impl(std::string api_path, void *buf,
|
||||
fuse_fill_dir_t fuse_fill_dir,
|
||||
off_t offset, struct fuse_file_info *fi,
|
||||
off_t offset,
|
||||
struct fuse_file_info *f_info,
|
||||
fuse_readdir_flags /*flags*/)
|
||||
-> api_error {
|
||||
#else
|
||||
auto remote_fuse_drive::readdir_impl(std::string api_path, void *buf,
|
||||
fuse_fill_dir_t fuse_fill_dir,
|
||||
off_t offset, struct fuse_file_info *fi)
|
||||
off_t offset,
|
||||
struct fuse_file_info *f_info)
|
||||
-> api_error {
|
||||
#endif
|
||||
std::string item_path;
|
||||
int res = 0;
|
||||
while ((res = remote_instance_->fuse_readdir(api_path.c_str(), offset, fi->fh,
|
||||
item_path)) == 0) {
|
||||
while ((res = remote_instance_->fuse_readdir(
|
||||
api_path.c_str(), static_cast<remote::file_offset>(offset),
|
||||
f_info->fh, item_path)) == 0) {
|
||||
if ((item_path != ".") && (item_path != "..")) {
|
||||
item_path = utils::path::strip_to_file_name(item_path);
|
||||
}
|
||||
@@ -378,16 +404,17 @@ auto remote_fuse_drive::readdir_impl(std::string api_path, void *buf,
|
||||
}
|
||||
|
||||
auto remote_fuse_drive::release_impl(std::string api_path,
|
||||
struct fuse_file_info *fi) -> api_error {
|
||||
struct fuse_file_info *f_info)
|
||||
-> api_error {
|
||||
return utils::to_api_error(
|
||||
remote_instance_->fuse_release(api_path.c_str(), fi->fh));
|
||||
remote_instance_->fuse_release(api_path.c_str(), f_info->fh));
|
||||
}
|
||||
|
||||
auto remote_fuse_drive::releasedir_impl(std::string api_path,
|
||||
struct fuse_file_info *fi)
|
||||
struct fuse_file_info *f_info)
|
||||
-> api_error {
|
||||
return utils::to_api_error(
|
||||
remote_instance_->fuse_releasedir(api_path.c_str(), fi->fh));
|
||||
remote_instance_->fuse_releasedir(api_path.c_str(), f_info->fh));
|
||||
}
|
||||
|
||||
#if FUSE_USE_VERSION >= 30
|
||||
@@ -471,8 +498,8 @@ api_error remote_fuse_drive::statfs_x_impl(std::string api_path,
|
||||
stbuf->f_ffree = r.f_ffree;
|
||||
stbuf->f_files = r.f_files;
|
||||
stbuf->f_owner = getuid();
|
||||
strncpy(&stbuf->f_mntonname[0u], get_mount_location().c_str(), MNAMELEN);
|
||||
strncpy(&stbuf->f_mntfromname[0u], &r.f_mntfromname[0], MNAMELEN);
|
||||
strncpy(&stbuf->f_mntonname[0U], get_mount_location().c_str(), MNAMELEN);
|
||||
strncpy(&stbuf->f_mntfromname[0U], &r.f_mntfromname[0U], MNAMELEN);
|
||||
}
|
||||
} else {
|
||||
res = -errno;
|
||||
@@ -485,15 +512,16 @@ auto remote_fuse_drive::statfs_impl(std::string api_path, struct statvfs *stbuf)
|
||||
-> api_error {
|
||||
auto res = statvfs(config_.get_data_directory().c_str(), stbuf);
|
||||
if (res == 0) {
|
||||
remote::statfs r{};
|
||||
if ((res = remote_instance_->fuse_statfs(api_path.c_str(), stbuf->f_frsize,
|
||||
r)) == 0) {
|
||||
stbuf->f_blocks = r.f_blocks;
|
||||
stbuf->f_bavail = r.f_bavail;
|
||||
stbuf->f_bfree = r.f_bfree;
|
||||
stbuf->f_ffree = r.f_ffree;
|
||||
stbuf->f_favail = r.f_favail;
|
||||
stbuf->f_files = r.f_files;
|
||||
remote::statfs r_stat{};
|
||||
res = remote_instance_->fuse_statfs(api_path.c_str(), stbuf->f_frsize,
|
||||
r_stat);
|
||||
if (res == 0) {
|
||||
stbuf->f_blocks = r_stat.f_blocks;
|
||||
stbuf->f_bavail = r_stat.f_bavail;
|
||||
stbuf->f_bfree = r_stat.f_bfree;
|
||||
stbuf->f_ffree = r_stat.f_ffree;
|
||||
stbuf->f_favail = r_stat.f_favail;
|
||||
stbuf->f_files = r_stat.f_files;
|
||||
}
|
||||
} else {
|
||||
res = -errno;
|
||||
@@ -505,14 +533,14 @@ auto remote_fuse_drive::statfs_impl(std::string api_path, struct statvfs *stbuf)
|
||||
|
||||
#if FUSE_USE_VERSION >= 30
|
||||
auto remote_fuse_drive::truncate_impl(std::string api_path, off_t size,
|
||||
struct fuse_file_info * /*fi*/)
|
||||
struct fuse_file_info * /*f_info*/)
|
||||
-> api_error {
|
||||
#else
|
||||
auto remote_fuse_drive::truncate_impl(std::string api_path, off_t size)
|
||||
-> api_error {
|
||||
#endif
|
||||
return utils::to_api_error(
|
||||
remote_instance_->fuse_truncate(api_path.c_str(), size));
|
||||
return utils::to_api_error(remote_instance_->fuse_truncate(
|
||||
api_path.c_str(), static_cast<remote::file_offset>(size)));
|
||||
}
|
||||
|
||||
auto remote_fuse_drive::unlink_impl(std::string api_path) -> api_error {
|
||||
@@ -522,31 +550,35 @@ auto remote_fuse_drive::unlink_impl(std::string api_path) -> api_error {
|
||||
#if FUSE_USE_VERSION >= 30
|
||||
auto remote_fuse_drive::utimens_impl(std::string api_path,
|
||||
const struct timespec tv[2],
|
||||
struct fuse_file_info * /*fi*/)
|
||||
struct fuse_file_info * /*f_info*/)
|
||||
-> api_error {
|
||||
#else
|
||||
auto remote_fuse_drive::utimens_impl(std::string api_path,
|
||||
const struct timespec tv[2]) -> api_error {
|
||||
#endif
|
||||
remote::file_time rtv[2u] = {0};
|
||||
if (tv) {
|
||||
rtv[0u] = tv[0u].tv_nsec + (tv[0u].tv_sec * NANOS_PER_SECOND);
|
||||
rtv[1u] = tv[1u].tv_nsec + (tv[1u].tv_sec * NANOS_PER_SECOND);
|
||||
remote::file_time rtv[2U] = {0};
|
||||
if (tv != nullptr) {
|
||||
rtv[0U] = static_cast<remote::file_time>(
|
||||
tv[0U].tv_nsec + (tv[0U].tv_sec * NANOS_PER_SECOND));
|
||||
rtv[1U] = static_cast<remote::file_time>(
|
||||
tv[1U].tv_nsec + (tv[1U].tv_sec * NANOS_PER_SECOND));
|
||||
}
|
||||
|
||||
return utils::to_api_error(remote_instance_->fuse_utimens(
|
||||
api_path.c_str(), rtv, tv ? tv[0u].tv_nsec : 0u,
|
||||
tv ? tv[1u].tv_nsec : 0u));
|
||||
api_path.c_str(), &rtv[0U],
|
||||
static_cast<std::uint64_t>(tv == nullptr ? 0 : tv[0U].tv_nsec),
|
||||
static_cast<std::uint64_t>(tv == nullptr ? 0 : tv[1U].tv_nsec)));
|
||||
}
|
||||
|
||||
auto remote_fuse_drive::write_impl(std::string api_path, const char *buffer,
|
||||
size_t write_size, off_t write_offset,
|
||||
struct fuse_file_info *fi,
|
||||
struct fuse_file_info *f_info,
|
||||
std::size_t &bytes_written) -> api_error {
|
||||
const auto res = remote_instance_->fuse_write(
|
||||
api_path.c_str(), buffer, write_size, write_offset, fi->fh);
|
||||
api_path.c_str(), buffer, write_size,
|
||||
static_cast<remote::file_offset>(write_offset), f_info->fh);
|
||||
if (res >= 0) {
|
||||
bytes_written = res;
|
||||
bytes_written = static_cast<std::size_t>(res);
|
||||
return api_error::success;
|
||||
}
|
||||
|
||||
|
File diff suppressed because it is too large
Load Diff
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
Copyright <2018-2023> <scott.e.graves@protonmail.com>
|
||||
Copyright <2018-2024> <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
|
||||
|
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
Copyright <2018-2023> <scott.e.graves@protonmail.com>
|
||||
Copyright <2018-2024> <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
|
||||
@@ -54,14 +54,16 @@ remote_client::remote_client(const app_config &config)
|
||||
|
||||
auto remote_client::winfsp_can_delete(PVOID file_desc, PWSTR file_name)
|
||||
-> packet::error_type {
|
||||
constexpr const auto *function_name = static_cast<const char *>(__FUNCTION__);
|
||||
|
||||
packet request;
|
||||
request.encode(file_desc);
|
||||
request.encode(file_name);
|
||||
|
||||
std::uint32_t service_flags = 0u;
|
||||
const auto ret = packet_client_.send(__FUNCTION__, request, service_flags);
|
||||
std::uint32_t service_flags{};
|
||||
const auto ret = packet_client_.send(function_name, request, service_flags);
|
||||
RAISE_REMOTE_WINFSP_CLIENT_EVENT(
|
||||
__FUNCTION__,
|
||||
function_name,
|
||||
utils::path::create_api_path(utils::string::to_utf8(file_name)), ret);
|
||||
return ret;
|
||||
}
|
||||
@@ -69,58 +71,66 @@ auto remote_client::winfsp_can_delete(PVOID file_desc, PWSTR file_name)
|
||||
auto remote_client::json_create_directory_snapshot(const std::string &path,
|
||||
json &json_data)
|
||||
-> packet::error_type {
|
||||
constexpr const auto *function_name = static_cast<const char *>(__FUNCTION__);
|
||||
|
||||
packet request;
|
||||
request.encode(path);
|
||||
|
||||
packet response;
|
||||
std::uint32_t service_flags = 0u;
|
||||
std::uint32_t service_flags{};
|
||||
auto ret =
|
||||
packet_client_.send(__FUNCTION__, request, response, service_flags);
|
||||
packet_client_.send(function_name, request, response, service_flags);
|
||||
if (ret == 0) {
|
||||
ret = packet::decode_json(response, json_data);
|
||||
}
|
||||
|
||||
RAISE_REMOTE_WINFSP_CLIENT_EVENT(__FUNCTION__, path, ret);
|
||||
RAISE_REMOTE_WINFSP_CLIENT_EVENT(function_name, path, ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
auto remote_client::json_read_directory_snapshot(
|
||||
const std::string &path, const remote::file_handle &handle,
|
||||
std::uint32_t page, json &json_data) -> packet::error_type {
|
||||
constexpr const auto *function_name = static_cast<const char *>(__FUNCTION__);
|
||||
|
||||
packet request;
|
||||
request.encode(path);
|
||||
request.encode(handle);
|
||||
request.encode(page);
|
||||
|
||||
packet response;
|
||||
std::uint32_t service_flags = 0u;
|
||||
std::uint32_t service_flags{};
|
||||
auto ret =
|
||||
packet_client_.send(__FUNCTION__, request, response, service_flags);
|
||||
packet_client_.send(function_name, request, response, service_flags);
|
||||
if (ret == 0) {
|
||||
ret = packet::decode_json(response, json_data);
|
||||
}
|
||||
|
||||
RAISE_REMOTE_WINFSP_CLIENT_EVENT(__FUNCTION__, path, ret);
|
||||
RAISE_REMOTE_WINFSP_CLIENT_EVENT(function_name, path, ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
auto remote_client::json_release_directory_snapshot(
|
||||
const std::string &path, const remote::file_handle &handle)
|
||||
-> packet::error_type {
|
||||
constexpr const auto *function_name = static_cast<const char *>(__FUNCTION__);
|
||||
|
||||
packet request;
|
||||
request.encode(path);
|
||||
request.encode(handle);
|
||||
|
||||
std::uint32_t service_flags = 0u;
|
||||
const auto ret = packet_client_.send(__FUNCTION__, request, service_flags);
|
||||
std::uint32_t service_flags{};
|
||||
const auto ret = packet_client_.send(function_name, request, service_flags);
|
||||
|
||||
RAISE_REMOTE_WINFSP_CLIENT_EVENT(__FUNCTION__, path, ret);
|
||||
RAISE_REMOTE_WINFSP_CLIENT_EVENT(function_name, path, ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
auto remote_client::winfsp_cleanup(PVOID file_desc, PWSTR file_name,
|
||||
UINT32 flags, BOOLEAN &was_closed)
|
||||
-> packet::error_type {
|
||||
constexpr const auto *function_name = static_cast<const char *>(__FUNCTION__);
|
||||
|
||||
auto handle = to_handle(file_desc);
|
||||
const auto file_path = get_open_file_path(handle);
|
||||
was_closed = 0;
|
||||
@@ -131,18 +141,20 @@ auto remote_client::winfsp_cleanup(PVOID file_desc, PWSTR file_name,
|
||||
request.encode(flags);
|
||||
|
||||
packet response;
|
||||
std::uint32_t service_flags = 0u;
|
||||
std::uint32_t service_flags{};
|
||||
auto ret =
|
||||
packet_client_.send(__FUNCTION__, request, response, service_flags);
|
||||
packet_client_.send(function_name, request, response, service_flags);
|
||||
DECODE_OR_IGNORE(&response, was_closed);
|
||||
if (was_closed) {
|
||||
if (was_closed != 0U) {
|
||||
remove_all(file_path);
|
||||
}
|
||||
RAISE_REMOTE_WINFSP_CLIENT_EVENT(__FUNCTION__, file_path, ret);
|
||||
RAISE_REMOTE_WINFSP_CLIENT_EVENT(function_name, file_path, ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
auto remote_client::winfsp_close(PVOID file_desc) -> packet::error_type {
|
||||
constexpr const auto *function_name = static_cast<const char *>(__FUNCTION__);
|
||||
|
||||
auto handle = to_handle(file_desc);
|
||||
if (has_open_info(handle, STATUS_INVALID_HANDLE) == STATUS_SUCCESS) {
|
||||
const auto file_path = get_open_file_path(handle);
|
||||
@@ -150,11 +162,11 @@ auto remote_client::winfsp_close(PVOID file_desc) -> packet::error_type {
|
||||
packet request;
|
||||
request.encode(file_desc);
|
||||
|
||||
std::uint32_t service_flags = 0u;
|
||||
const auto ret = packet_client_.send(__FUNCTION__, request, service_flags);
|
||||
std::uint32_t service_flags{};
|
||||
const auto ret = packet_client_.send(function_name, request, service_flags);
|
||||
if ((ret == STATUS_SUCCESS) || (ret == STATUS_INVALID_HANDLE)) {
|
||||
remove_open_info(handle);
|
||||
RAISE_REMOTE_WINFSP_CLIENT_EVENT(__FUNCTION__, file_path, ret);
|
||||
RAISE_REMOTE_WINFSP_CLIENT_EVENT(function_name, file_path, ret);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -167,6 +179,8 @@ auto remote_client::winfsp_create(PWSTR file_name, UINT32 create_options,
|
||||
remote::file_info *file_info,
|
||||
std::string &normalized_name, BOOLEAN &exists)
|
||||
-> packet::error_type {
|
||||
constexpr const auto *function_name = static_cast<const char *>(__FUNCTION__);
|
||||
|
||||
packet request;
|
||||
request.encode(file_name);
|
||||
request.encode(create_options);
|
||||
@@ -175,11 +189,11 @@ auto remote_client::winfsp_create(PWSTR file_name, UINT32 create_options,
|
||||
request.encode(allocation_size);
|
||||
|
||||
packet response;
|
||||
std::uint32_t service_flags = 0u;
|
||||
std::uint32_t service_flags{};
|
||||
auto ret =
|
||||
packet_client_.send(__FUNCTION__, request, response, service_flags);
|
||||
packet_client_.send(function_name, request, response, service_flags);
|
||||
if (ret == STATUS_SUCCESS) {
|
||||
HANDLE handle;
|
||||
HANDLE handle{};
|
||||
DECODE_OR_IGNORE(&response, handle);
|
||||
DECODE_OR_IGNORE(&response, *file_info);
|
||||
DECODE_OR_IGNORE(&response, normalized_name);
|
||||
@@ -198,23 +212,25 @@ auto remote_client::winfsp_create(PWSTR file_name, UINT32 create_options,
|
||||
}
|
||||
|
||||
RAISE_REMOTE_WINFSP_CLIENT_EVENT(
|
||||
__FUNCTION__, get_open_file_path(to_handle(*file_desc)), ret);
|
||||
function_name, get_open_file_path(to_handle(*file_desc)), ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
auto remote_client::winfsp_flush(PVOID file_desc, remote::file_info *file_info)
|
||||
-> packet::error_type {
|
||||
constexpr const auto *function_name = static_cast<const char *>(__FUNCTION__);
|
||||
|
||||
packet request;
|
||||
request.encode(file_desc);
|
||||
|
||||
packet response;
|
||||
std::uint32_t service_flags = 0u;
|
||||
std::uint32_t service_flags{};
|
||||
auto ret =
|
||||
packet_client_.send(__FUNCTION__, request, response, service_flags);
|
||||
packet_client_.send(function_name, request, response, service_flags);
|
||||
DECODE_OR_IGNORE(&response, *file_info);
|
||||
|
||||
RAISE_REMOTE_WINFSP_CLIENT_EVENT(
|
||||
__FUNCTION__, get_open_file_path(to_handle(file_desc)), ret);
|
||||
function_name, get_open_file_path(to_handle(file_desc)), ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
@@ -232,17 +248,19 @@ auto remote_client::winfsp_get_dir_buffer([[maybe_unused]] PVOID file_desc,
|
||||
auto remote_client::winfsp_get_file_info(PVOID file_desc,
|
||||
remote::file_info *file_info)
|
||||
-> packet::error_type {
|
||||
constexpr const auto *function_name = static_cast<const char *>(__FUNCTION__);
|
||||
|
||||
packet request;
|
||||
request.encode(file_desc);
|
||||
|
||||
packet response;
|
||||
std::uint32_t service_flags = 0u;
|
||||
std::uint32_t service_flags{};
|
||||
auto ret =
|
||||
packet_client_.send(__FUNCTION__, request, response, service_flags);
|
||||
packet_client_.send(function_name, request, response, service_flags);
|
||||
DECODE_OR_IGNORE(&response, *file_info);
|
||||
|
||||
RAISE_REMOTE_WINFSP_CLIENT_EVENT(
|
||||
__FUNCTION__, get_open_file_path(to_handle(file_desc)), ret);
|
||||
function_name, get_open_file_path(to_handle(file_desc)), ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
@@ -251,16 +269,18 @@ auto remote_client::winfsp_get_security_by_name(PWSTR file_name,
|
||||
std::uint64_t *descriptor_size,
|
||||
std::wstring &string_descriptor)
|
||||
-> packet::error_type {
|
||||
constexpr const auto *function_name = static_cast<const char *>(__FUNCTION__);
|
||||
|
||||
packet request;
|
||||
request.encode(file_name);
|
||||
request.encode(
|
||||
static_cast<std::uint64_t>(descriptor_size ? *descriptor_size : 0));
|
||||
request.encode(static_cast<std::uint64_t>(
|
||||
descriptor_size == nullptr ? 0 : *descriptor_size));
|
||||
request.encode(static_cast<std::uint8_t>(attributes != nullptr));
|
||||
|
||||
packet response;
|
||||
std::uint32_t service_flags = 0u;
|
||||
std::uint32_t service_flags{};
|
||||
auto ret =
|
||||
packet_client_.send(__FUNCTION__, request, response, service_flags);
|
||||
packet_client_.send(function_name, request, response, service_flags);
|
||||
|
||||
string_descriptor.clear();
|
||||
DECODE_OR_IGNORE(&response, string_descriptor);
|
||||
@@ -268,11 +288,11 @@ auto remote_client::winfsp_get_security_by_name(PWSTR file_name,
|
||||
string_descriptor = L"O:BAG:BAD:P(A;;FA;;;SY)(A;;FA;;;BA)(A;;FA;;;WD)";
|
||||
}
|
||||
|
||||
if (attributes) {
|
||||
if (attributes != nullptr) {
|
||||
DECODE_OR_IGNORE(&response, *attributes);
|
||||
}
|
||||
|
||||
RAISE_REMOTE_WINFSP_CLIENT_EVENT(__FUNCTION__,
|
||||
RAISE_REMOTE_WINFSP_CLIENT_EVENT(function_name,
|
||||
utils::string::to_utf8(file_name), ret);
|
||||
return ret;
|
||||
}
|
||||
@@ -281,11 +301,13 @@ auto remote_client::winfsp_get_volume_info(UINT64 &total_size,
|
||||
UINT64 &free_size,
|
||||
std::string &volume_label)
|
||||
-> packet::error_type {
|
||||
constexpr const auto *function_name = static_cast<const char *>(__FUNCTION__);
|
||||
|
||||
packet request;
|
||||
packet response;
|
||||
std::uint32_t service_flags = 0u;
|
||||
std::uint32_t service_flags{};
|
||||
auto ret =
|
||||
packet_client_.send(__FUNCTION__, request, response, service_flags);
|
||||
packet_client_.send(function_name, request, response, service_flags);
|
||||
DECODE_OR_IGNORE(&response, total_size);
|
||||
DECODE_OR_IGNORE(&response, free_size);
|
||||
DECODE_OR_IGNORE(&response, volume_label);
|
||||
@@ -295,16 +317,18 @@ auto remote_client::winfsp_get_volume_info(UINT64 &total_size,
|
||||
|
||||
auto remote_client::winfsp_mounted(const std::wstring &location)
|
||||
-> packet::error_type {
|
||||
constexpr const auto *function_name = static_cast<const char *>(__FUNCTION__);
|
||||
|
||||
packet request;
|
||||
request.encode(get_repertory_version());
|
||||
request.encode(location);
|
||||
|
||||
std::uint32_t service_flags = 0u;
|
||||
const auto ret = packet_client_.send(__FUNCTION__, request, service_flags);
|
||||
std::uint32_t service_flags{};
|
||||
const auto ret = packet_client_.send(function_name, request, service_flags);
|
||||
const auto mount_location = utils::string::to_utf8(location);
|
||||
event_system::instance().raise<drive_mounted>(mount_location);
|
||||
|
||||
RAISE_REMOTE_WINFSP_CLIENT_EVENT(__FUNCTION__, mount_location, ret);
|
||||
RAISE_REMOTE_WINFSP_CLIENT_EVENT(function_name, mount_location, ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
@@ -313,17 +337,19 @@ auto remote_client::winfsp_open(PWSTR file_name, UINT32 create_options,
|
||||
remote::file_info *file_info,
|
||||
std::string &normalized_name)
|
||||
-> packet::error_type {
|
||||
constexpr const auto *function_name = static_cast<const char *>(__FUNCTION__);
|
||||
|
||||
packet request;
|
||||
request.encode(file_name);
|
||||
request.encode(create_options);
|
||||
request.encode(granted_access);
|
||||
|
||||
packet response;
|
||||
std::uint32_t service_flags = 0u;
|
||||
std::uint32_t service_flags{};
|
||||
auto ret =
|
||||
packet_client_.send(__FUNCTION__, request, response, service_flags);
|
||||
packet_client_.send(function_name, request, response, service_flags);
|
||||
if (ret == STATUS_SUCCESS) {
|
||||
HANDLE handle;
|
||||
HANDLE handle{};
|
||||
DECODE_OR_IGNORE(&response, handle);
|
||||
DECODE_OR_IGNORE(&response, *file_info);
|
||||
DECODE_OR_IGNORE(&response, normalized_name);
|
||||
@@ -337,7 +363,7 @@ auto remote_client::winfsp_open(PWSTR file_name, UINT32 create_options,
|
||||
}
|
||||
|
||||
RAISE_REMOTE_WINFSP_CLIENT_EVENT(
|
||||
__FUNCTION__, get_open_file_path(to_handle(*file_desc)), ret);
|
||||
function_name, get_open_file_path(to_handle(*file_desc)), ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
@@ -346,6 +372,8 @@ auto remote_client::winfsp_overwrite(PVOID file_desc, UINT32 attributes,
|
||||
UINT64 allocation_size,
|
||||
remote::file_info *file_info)
|
||||
-> packet::error_type {
|
||||
constexpr const auto *function_name = static_cast<const char *>(__FUNCTION__);
|
||||
|
||||
packet request;
|
||||
request.encode(file_desc);
|
||||
request.encode(attributes);
|
||||
@@ -353,28 +381,30 @@ auto remote_client::winfsp_overwrite(PVOID file_desc, UINT32 attributes,
|
||||
request.encode(allocation_size);
|
||||
|
||||
packet response;
|
||||
std::uint32_t service_flags = 0u;
|
||||
std::uint32_t service_flags{};
|
||||
auto ret =
|
||||
packet_client_.send(__FUNCTION__, request, response, service_flags);
|
||||
packet_client_.send(function_name, request, response, service_flags);
|
||||
DECODE_OR_IGNORE(&response, *file_info);
|
||||
|
||||
RAISE_REMOTE_WINFSP_CLIENT_EVENT(
|
||||
__FUNCTION__, get_open_file_path(to_handle(file_desc)), ret);
|
||||
function_name, get_open_file_path(to_handle(file_desc)), ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
auto remote_client::winfsp_read(PVOID file_desc, PVOID buffer, UINT64 offset,
|
||||
UINT32 length, PUINT32 bytes_transferred)
|
||||
-> packet::error_type {
|
||||
constexpr const auto *function_name = static_cast<const char *>(__FUNCTION__);
|
||||
|
||||
packet request;
|
||||
request.encode(file_desc);
|
||||
request.encode(offset);
|
||||
request.encode(length);
|
||||
|
||||
packet response;
|
||||
std::uint32_t service_flags = 0u;
|
||||
std::uint32_t service_flags{};
|
||||
auto ret =
|
||||
packet_client_.send(__FUNCTION__, request, response, service_flags);
|
||||
packet_client_.send(function_name, request, response, service_flags);
|
||||
DECODE_OR_IGNORE(&response, *bytes_transferred);
|
||||
if (ret == STATUS_SUCCESS) {
|
||||
ret = response.decode(buffer, *bytes_transferred);
|
||||
@@ -388,7 +418,7 @@ auto remote_client::winfsp_read(PVOID file_desc, PVOID buffer, UINT64 offset,
|
||||
|
||||
if (ret != STATUS_SUCCESS) {
|
||||
RAISE_REMOTE_WINFSP_CLIENT_EVENT(
|
||||
__FUNCTION__, get_open_file_path(to_handle(file_desc)), ret);
|
||||
function_name, get_open_file_path(to_handle(file_desc)), ret);
|
||||
}
|
||||
|
||||
return ret;
|
||||
@@ -397,21 +427,23 @@ auto remote_client::winfsp_read(PVOID file_desc, PVOID buffer, UINT64 offset,
|
||||
auto remote_client::winfsp_read_directory(PVOID file_desc, PWSTR pattern,
|
||||
PWSTR marker, json &item_list)
|
||||
-> packet::error_type {
|
||||
constexpr const auto *function_name = static_cast<const char *>(__FUNCTION__);
|
||||
|
||||
packet request;
|
||||
request.encode(file_desc);
|
||||
request.encode(pattern);
|
||||
request.encode(marker);
|
||||
|
||||
packet response;
|
||||
std::uint32_t service_flags = 0u;
|
||||
std::uint32_t service_flags{};
|
||||
auto ret =
|
||||
packet_client_.send(__FUNCTION__, request, response, service_flags);
|
||||
packet_client_.send(function_name, request, response, service_flags);
|
||||
if (ret == STATUS_SUCCESS) {
|
||||
ret = packet::decode_json(response, item_list);
|
||||
}
|
||||
|
||||
RAISE_REMOTE_WINFSP_CLIENT_EVENT(
|
||||
__FUNCTION__, get_open_file_path(to_handle(file_desc)), ret);
|
||||
function_name, get_open_file_path(to_handle(file_desc)), ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
@@ -419,16 +451,18 @@ auto remote_client::winfsp_rename(PVOID file_desc, PWSTR file_name,
|
||||
PWSTR new_file_name,
|
||||
BOOLEAN replace_if_exists)
|
||||
-> packet::error_type {
|
||||
constexpr const auto *function_name = static_cast<const char *>(__FUNCTION__);
|
||||
|
||||
packet request;
|
||||
request.encode(file_desc);
|
||||
request.encode(file_name);
|
||||
request.encode(new_file_name);
|
||||
request.encode(replace_if_exists);
|
||||
|
||||
std::uint32_t service_flags = 0u;
|
||||
const auto ret = packet_client_.send(__FUNCTION__, request, service_flags);
|
||||
std::uint32_t service_flags{};
|
||||
const auto ret = packet_client_.send(function_name, request, service_flags);
|
||||
RAISE_REMOTE_WINFSP_CLIENT_EVENT(
|
||||
__FUNCTION__,
|
||||
function_name,
|
||||
utils::path::create_api_path(utils::string::to_utf8(file_name)) + "|" +
|
||||
utils::path::create_api_path(utils::string::to_utf8(new_file_name)),
|
||||
ret);
|
||||
@@ -439,6 +473,8 @@ auto remote_client::winfsp_set_basic_info(
|
||||
PVOID file_desc, UINT32 attributes, UINT64 creation_time,
|
||||
UINT64 last_access_time, UINT64 last_write_time, UINT64 change_time,
|
||||
remote::file_info *file_info) -> packet::error_type {
|
||||
constexpr const auto *function_name = static_cast<const char *>(__FUNCTION__);
|
||||
|
||||
packet request;
|
||||
request.encode(file_desc);
|
||||
request.encode(attributes);
|
||||
@@ -448,13 +484,13 @@ auto remote_client::winfsp_set_basic_info(
|
||||
request.encode(change_time);
|
||||
|
||||
packet response;
|
||||
std::uint32_t service_flags = 0u;
|
||||
std::uint32_t service_flags{};
|
||||
auto ret =
|
||||
packet_client_.send(__FUNCTION__, request, response, service_flags);
|
||||
packet_client_.send(function_name, request, response, service_flags);
|
||||
DECODE_OR_IGNORE(&response, *file_info);
|
||||
|
||||
RAISE_REMOTE_WINFSP_CLIENT_EVENT(
|
||||
__FUNCTION__, get_open_file_path(to_handle(file_desc)), ret);
|
||||
function_name, get_open_file_path(to_handle(file_desc)), ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
@@ -462,34 +498,38 @@ auto remote_client::winfsp_set_file_size(PVOID file_desc, UINT64 new_size,
|
||||
BOOLEAN set_allocation_size,
|
||||
remote::file_info *file_info)
|
||||
-> packet::error_type {
|
||||
constexpr const auto *function_name = static_cast<const char *>(__FUNCTION__);
|
||||
|
||||
packet request;
|
||||
request.encode(file_desc);
|
||||
request.encode(new_size);
|
||||
request.encode(set_allocation_size);
|
||||
|
||||
packet response;
|
||||
std::uint32_t service_flags = 0u;
|
||||
std::uint32_t service_flags{};
|
||||
auto ret =
|
||||
packet_client_.send(__FUNCTION__, request, response, service_flags);
|
||||
packet_client_.send(function_name, request, response, service_flags);
|
||||
DECODE_OR_IGNORE(&response, *file_info);
|
||||
|
||||
RAISE_REMOTE_WINFSP_CLIENT_EVENT(
|
||||
__FUNCTION__, get_open_file_path(to_handle(file_desc)), ret);
|
||||
function_name, get_open_file_path(to_handle(file_desc)), ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
auto remote_client::winfsp_unmounted(const std::wstring &location)
|
||||
-> packet::error_type {
|
||||
constexpr const auto *function_name = static_cast<const char *>(__FUNCTION__);
|
||||
|
||||
const auto mount_location = utils::string::to_utf8(location);
|
||||
event_system::instance().raise<drive_unmount_pending>(mount_location);
|
||||
packet request;
|
||||
request.encode(location);
|
||||
|
||||
std::uint32_t service_flags = 0u;
|
||||
const auto ret = packet_client_.send(__FUNCTION__, request, service_flags);
|
||||
std::uint32_t service_flags{};
|
||||
const auto ret = packet_client_.send(function_name, request, service_flags);
|
||||
event_system::instance().raise<drive_unmounted>(mount_location);
|
||||
|
||||
RAISE_REMOTE_WINFSP_CLIENT_EVENT(__FUNCTION__, mount_location, ret);
|
||||
RAISE_REMOTE_WINFSP_CLIENT_EVENT(function_name, mount_location, ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
@@ -499,32 +539,34 @@ auto remote_client::winfsp_write(PVOID file_desc, PVOID buffer, UINT64 offset,
|
||||
PUINT32 bytes_transferred,
|
||||
remote::file_info *file_info)
|
||||
-> packet::error_type {
|
||||
constexpr const auto *function_name = static_cast<const char *>(__FUNCTION__);
|
||||
|
||||
packet request;
|
||||
request.encode(file_desc);
|
||||
request.encode(length);
|
||||
request.encode(offset);
|
||||
request.encode(write_to_end);
|
||||
request.encode(constrained_io);
|
||||
if (length) {
|
||||
if (length != 0U) {
|
||||
request.encode(buffer, length);
|
||||
}
|
||||
|
||||
packet response;
|
||||
std::uint32_t service_flags = 0u;
|
||||
std::uint32_t service_flags{};
|
||||
auto ret =
|
||||
packet_client_.send(__FUNCTION__, request, response, service_flags);
|
||||
packet_client_.send(function_name, request, response, service_flags);
|
||||
DECODE_OR_IGNORE(&response, *bytes_transferred);
|
||||
DECODE_OR_IGNORE(&response, *file_info);
|
||||
|
||||
if (ret != STATUS_SUCCESS) {
|
||||
RAISE_REMOTE_WINFSP_CLIENT_EVENT(
|
||||
__FUNCTION__, get_open_file_path(to_handle(file_desc)), ret);
|
||||
function_name, get_open_file_path(to_handle(file_desc)), ret);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
#ifndef _WIN32
|
||||
native_handle remote_client::to_handle(PVOID file_desc) {
|
||||
auto remote_client::to_handle(PVOID file_desc) -> native_handle {
|
||||
return static_cast<native_handle>(reinterpret_cast<std::uint64_t>(file_desc));
|
||||
}
|
||||
#endif
|
||||
|
File diff suppressed because it is too large
Load Diff
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
Copyright <2018-2023> <scott.e.graves@protonmail.com>
|
||||
Copyright <2018-2024> <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
|
||||
@@ -21,8 +21,6 @@
|
||||
*/
|
||||
#ifdef _WIN32
|
||||
|
||||
#include <utility>
|
||||
|
||||
#include "drives/winfsp/remotewinfsp/remote_winfsp_drive.hpp"
|
||||
|
||||
#include "app_config.hpp"
|
||||
@@ -49,6 +47,8 @@ remote_winfsp_drive::winfsp_service::winfsp_service(
|
||||
host_(drive) {}
|
||||
|
||||
auto remote_winfsp_drive::winfsp_service::OnStart(ULONG, PWSTR *) -> NTSTATUS {
|
||||
constexpr const auto *function_name = static_cast<const char *>(__FUNCTION__);
|
||||
|
||||
const auto mount_location = utils::string::to_lower(
|
||||
utils::path::absolute((drive_args_.size() > 1u) ? drive_args_[1u] : ""));
|
||||
const auto drive_letter =
|
||||
@@ -75,7 +75,7 @@ auto remote_winfsp_drive::winfsp_service::OnStart(ULONG, PWSTR *) -> NTSTATUS {
|
||||
event_system::instance().raise<drive_mount_failed>(mount_location,
|
||||
std::to_string(ret));
|
||||
if (not lock_.set_mount_state(false, "", -1)) {
|
||||
utils::error::raise_error(__FUNCTION__, "failed to set mount state");
|
||||
utils::error::raise_error(function_name, "failed to set mount state");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -83,9 +83,11 @@ auto remote_winfsp_drive::winfsp_service::OnStart(ULONG, PWSTR *) -> NTSTATUS {
|
||||
}
|
||||
|
||||
auto remote_winfsp_drive::winfsp_service::OnStop() -> NTSTATUS {
|
||||
constexpr const auto *function_name = static_cast<const char *>(__FUNCTION__);
|
||||
|
||||
host_.Unmount();
|
||||
if (not lock_.set_mount_state(false, "", -1)) {
|
||||
utils::error::raise_error(__FUNCTION__, "failed to set mount state");
|
||||
utils::error::raise_error(function_name, "failed to set mount state");
|
||||
}
|
||||
|
||||
return STATUS_SUCCESS;
|
||||
@@ -134,7 +136,8 @@ auto remote_winfsp_drive::Create(PWSTR file_name, UINT32 create_options,
|
||||
set_file_info(ofi->FileInfo, fi);
|
||||
const auto file_path = utils::string::from_utf8(normalized_name);
|
||||
wcsncpy(ofi->NormalizedName, &file_path[0], wcslen(&file_path[0]));
|
||||
ofi->NormalizedNameSize = (UINT16)(wcslen(&file_path[0]) * sizeof(WCHAR));
|
||||
ofi->NormalizedNameSize =
|
||||
static_cast<UINT16>(wcslen(&file_path[0]) * sizeof(WCHAR));
|
||||
}
|
||||
|
||||
return ret;
|
||||
@@ -258,6 +261,8 @@ auto remote_winfsp_drive::mount(const std::vector<std::string> &drive_args)
|
||||
}
|
||||
|
||||
auto remote_winfsp_drive::Mounted(PVOID host) -> NTSTATUS {
|
||||
constexpr const auto *function_name = static_cast<const char *>(__FUNCTION__);
|
||||
|
||||
auto *file_system_host = reinterpret_cast<FileSystemHost *>(host);
|
||||
remote_instance_ = factory_();
|
||||
server_ = std::make_unique<server>(config_);
|
||||
@@ -265,7 +270,7 @@ auto remote_winfsp_drive::Mounted(PVOID host) -> NTSTATUS {
|
||||
mount_location_ = utils::string::to_utf8(file_system_host->MountPoint());
|
||||
if (not lock_.set_mount_state(true, mount_location_,
|
||||
::GetCurrentProcessId())) {
|
||||
utils::error::raise_error(__FUNCTION__, "failed to set mount state");
|
||||
utils::error::raise_error(function_name, "failed to set mount state");
|
||||
}
|
||||
|
||||
return remote_instance_->winfsp_mounted(file_system_host->MountPoint());
|
||||
@@ -284,7 +289,8 @@ auto remote_winfsp_drive::Open(PWSTR file_name, UINT32 create_options,
|
||||
set_file_info(ofi->FileInfo, fi);
|
||||
const auto file_path = utils::string::from_utf8(normalize_name);
|
||||
wcsncpy(ofi->NormalizedName, &file_path[0], wcslen(&file_path[0]));
|
||||
ofi->NormalizedNameSize = (UINT16)(wcslen(&file_path[0]) * sizeof(WCHAR));
|
||||
ofi->NormalizedNameSize =
|
||||
static_cast<UINT16>(wcslen(&file_path[0]) * sizeof(WCHAR));
|
||||
}
|
||||
|
||||
return ret;
|
||||
@@ -445,11 +451,13 @@ auto remote_winfsp_drive::SetFileSize(PVOID /*file_node*/, PVOID file_desc,
|
||||
}
|
||||
|
||||
VOID remote_winfsp_drive::Unmounted(PVOID host) {
|
||||
constexpr const auto *function_name = static_cast<const char *>(__FUNCTION__);
|
||||
|
||||
server_->stop();
|
||||
server_.reset();
|
||||
auto *file_system_host = reinterpret_cast<FileSystemHost *>(host);
|
||||
if (not lock_.set_mount_state(false, "", -1)) {
|
||||
utils::error::raise_error(__FUNCTION__, "failed to set mount state");
|
||||
utils::error::raise_error(function_name, "failed to set mount state");
|
||||
}
|
||||
remote_instance_->winfsp_unmounted(file_system_host->MountPoint());
|
||||
remote_instance_.reset();
|
||||
|
File diff suppressed because it is too large
Load Diff
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
Copyright <2018-2023> <scott.e.graves@protonmail.com>
|
||||
Copyright <2018-2024> <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
|
||||
@@ -69,6 +69,8 @@ logging_consumer::~logging_consumer() {
|
||||
}
|
||||
|
||||
void logging_consumer::check_log_roll(std::size_t count) {
|
||||
constexpr const auto *function_name = static_cast<const char *>(__FUNCTION__);
|
||||
|
||||
std::uint64_t file_size{};
|
||||
const auto success = utils::file::get_file_size(log_path_, file_size);
|
||||
if (success && (file_size + count) >= MAX_LOG_FILE_SIZE) {
|
||||
@@ -85,7 +87,7 @@ void logging_consumer::check_log_roll(std::size_t count) {
|
||||
log_directory_,
|
||||
{"repertory." + std::to_string(i + std::uint8_t(1)) + ".log"});
|
||||
if (not utils::file::move_file(temp_log_path, next_file_path)) {
|
||||
utils::error::raise_error(__FUNCTION__,
|
||||
utils::error::raise_error(function_name,
|
||||
utils::get_last_error_code(),
|
||||
temp_log_path + "|dest|" + next_file_path,
|
||||
"failed to move file");
|
||||
@@ -97,7 +99,7 @@ void logging_consumer::check_log_roll(std::size_t count) {
|
||||
auto backup_log_path =
|
||||
utils::path::combine(log_directory_, {"repertory.1.log"});
|
||||
if (not utils::file::move_file(log_path_, backup_log_path)) {
|
||||
utils::error::raise_error(__FUNCTION__, utils::get_last_error_code(),
|
||||
utils::error::raise_error(function_name, utils::get_last_error_code(),
|
||||
log_path_ + "|dest|" + backup_log_path,
|
||||
"failed to move file");
|
||||
}
|
||||
|
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
Copyright <2018-2023> <scott.e.graves@protonmail.com>
|
||||
Copyright <2018-2024> <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
|
||||
|
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
Copyright <2018-2023> <scott.e.graves@protonmail.com>
|
||||
Copyright <2018-2024> <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
|
||||
|
File diff suppressed because it is too large
Load Diff
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
Copyright <2018-2023> <scott.e.graves@protonmail.com>
|
||||
Copyright <2018-2024> <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
|
||||
@@ -64,13 +64,12 @@ file_manager::open_file::open_file(
|
||||
}
|
||||
|
||||
if (not fsi.directory) {
|
||||
set_api_error(native_file::create_or_open(
|
||||
fsi.source_path, not provider_.is_direct_only(), nf_));
|
||||
set_api_error(native_file::create_or_open(fsi.source_path,
|
||||
provider_.is_direct_only(), nf_));
|
||||
if (get_api_error() == api_error::success) {
|
||||
if (read_state.has_value()) {
|
||||
modified_ = true;
|
||||
mgr_.store_resume(*this);
|
||||
read_state_ = read_state.value();
|
||||
set_modified();
|
||||
} else if (fsi_.size > 0U) {
|
||||
read_state_.resize(static_cast<std::size_t>(utils::divide_with_ceiling(
|
||||
fsi_.size, chunk_size)),
|
||||
@@ -238,7 +237,7 @@ auto file_manager::open_file::is_complete() const -> bool {
|
||||
}
|
||||
|
||||
auto file_manager::open_file::native_operation(
|
||||
const i_open_file::native_operation_callback &callback) -> api_error {
|
||||
i_open_file::native_operation_callback callback) -> api_error {
|
||||
unique_recur_mutex_lock file_lock(file_mtx_);
|
||||
if (stop_requested_) {
|
||||
return api_error::download_stopped;
|
||||
@@ -250,7 +249,9 @@ auto file_manager::open_file::native_operation(
|
||||
|
||||
auto file_manager::open_file::native_operation(
|
||||
std::uint64_t new_file_size,
|
||||
const i_open_file::native_operation_callback &callback) -> api_error {
|
||||
i_open_file::native_operation_callback callback) -> api_error {
|
||||
constexpr const auto *function_name = static_cast<const char *>(__FUNCTION__);
|
||||
|
||||
if (fsi_.directory) {
|
||||
return api_error::invalid_operation;
|
||||
}
|
||||
@@ -284,7 +285,7 @@ auto file_manager::open_file::native_operation(
|
||||
|
||||
auto res = do_io([&]() -> api_error { return callback(nf_->get_handle()); });
|
||||
if (res != api_error::success) {
|
||||
utils::error::raise_api_path_error(__FUNCTION__, get_api_path(),
|
||||
utils::error::raise_api_path_error(function_name, get_api_path(),
|
||||
utils::get_last_error_code(),
|
||||
"failed to allocate file");
|
||||
return res;
|
||||
@@ -293,7 +294,7 @@ auto file_manager::open_file::native_operation(
|
||||
{
|
||||
std::uint64_t file_size{};
|
||||
if (not nf_->get_file_size(file_size)) {
|
||||
utils::error::raise_api_path_error(__FUNCTION__, get_api_path(),
|
||||
utils::error::raise_api_path_error(function_name, get_api_path(),
|
||||
utils::get_last_error_code(),
|
||||
"failed to get file size");
|
||||
return set_api_error(api_error::os_error);
|
||||
@@ -301,7 +302,7 @@ auto file_manager::open_file::native_operation(
|
||||
|
||||
if (file_size != new_file_size) {
|
||||
utils::error::raise_api_path_error(
|
||||
__FUNCTION__, get_api_path(), api_error::file_size_mismatch,
|
||||
function_name, get_api_path(), api_error::file_size_mismatch,
|
||||
"allocated file size mismatch|expected|" +
|
||||
std::to_string(new_file_size) + "|actual|" +
|
||||
std::to_string(file_size));
|
||||
@@ -323,11 +324,7 @@ auto file_manager::open_file::native_operation(
|
||||
}
|
||||
|
||||
if (original_file_size != new_file_size) {
|
||||
if (not modified_) {
|
||||
mgr_.store_resume(*this);
|
||||
}
|
||||
modified_ = true;
|
||||
mgr_.remove_upload(get_api_path());
|
||||
set_modified();
|
||||
|
||||
fsi_.size = new_file_size;
|
||||
const auto now = std::to_string(utils::get_file_time_now());
|
||||
@@ -339,7 +336,7 @@ auto file_manager::open_file::native_operation(
|
||||
{META_WRITTEN, now},
|
||||
});
|
||||
if (res != api_error::success) {
|
||||
utils::error::raise_api_path_error(__FUNCTION__, get_api_path(), res,
|
||||
utils::error::raise_api_path_error(function_name, get_api_path(), res,
|
||||
"failed to set file meta");
|
||||
return set_api_error(res);
|
||||
}
|
||||
@@ -409,6 +406,10 @@ void file_manager::open_file::remove(std::uint64_t handle) {
|
||||
mgr_.queue_upload(*this);
|
||||
modified_ = false;
|
||||
}
|
||||
|
||||
if (removed_ && (get_open_file_count() == 0U)) {
|
||||
removed_ = false;
|
||||
}
|
||||
}
|
||||
|
||||
auto file_manager::open_file::resize(std::uint64_t new_file_size) -> api_error {
|
||||
@@ -424,6 +425,8 @@ auto file_manager::open_file::resize(std::uint64_t new_file_size) -> api_error {
|
||||
}
|
||||
|
||||
auto file_manager::open_file::close() -> bool {
|
||||
constexpr const auto *function_name = static_cast<const char *>(__FUNCTION__);
|
||||
|
||||
if (not fsi_.directory && not stop_requested_) {
|
||||
stop_requested_ = true;
|
||||
|
||||
@@ -463,7 +466,7 @@ auto file_manager::open_file::close() -> bool {
|
||||
mgr_.remove_resume(get_api_path(), get_source_path());
|
||||
if (not utils::file::retry_delete_file(fsi_.source_path)) {
|
||||
utils::error::raise_api_path_error(
|
||||
__FUNCTION__, get_api_path(), fsi_.source_path,
|
||||
function_name, get_api_path(), fsi_.source_path,
|
||||
utils::get_last_error_code(), "failed to delete file");
|
||||
}
|
||||
|
||||
@@ -473,7 +476,7 @@ auto file_manager::open_file::close() -> bool {
|
||||
const auto res = provider_.set_item_meta(fsi_.api_path, META_SOURCE,
|
||||
fsi_.source_path);
|
||||
if (res != api_error::success) {
|
||||
utils::error::raise_api_path_error(__FUNCTION__, get_api_path(),
|
||||
utils::error::raise_api_path_error(function_name, get_api_path(),
|
||||
fsi_.source_path, res,
|
||||
"failed to set file meta");
|
||||
}
|
||||
@@ -486,6 +489,18 @@ auto file_manager::open_file::close() -> bool {
|
||||
return false;
|
||||
}
|
||||
|
||||
void file_manager::open_file::set_modified() {
|
||||
if (not modified_) {
|
||||
modified_ = true;
|
||||
mgr_.store_resume(*this);
|
||||
}
|
||||
|
||||
if (not removed_) {
|
||||
removed_ = true;
|
||||
mgr_.remove_upload(get_api_path());
|
||||
}
|
||||
}
|
||||
|
||||
void file_manager::open_file::update_background_reader(std::size_t read_chunk) {
|
||||
recur_mutex_lock reader_lock(file_mtx_);
|
||||
read_chunk_index_ = read_chunk;
|
||||
@@ -524,6 +539,8 @@ void file_manager::open_file::update_background_reader(std::size_t read_chunk) {
|
||||
auto file_manager::open_file::write(std::uint64_t write_offset,
|
||||
const data_buffer &data,
|
||||
std::size_t &bytes_written) -> api_error {
|
||||
constexpr const auto *function_name = static_cast<const char *>(__FUNCTION__);
|
||||
|
||||
bytes_written = 0U;
|
||||
|
||||
if (fsi_.directory || provider_.is_direct_only()) {
|
||||
@@ -581,17 +598,12 @@ auto file_manager::open_file::write(std::uint64_t write_offset,
|
||||
{META_WRITTEN, now},
|
||||
});
|
||||
if (res != api_error::success) {
|
||||
utils::error::raise_api_path_error(__FUNCTION__, get_api_path(), res,
|
||||
utils::error::raise_api_path_error(function_name, get_api_path(), res,
|
||||
"failed to set file meta");
|
||||
return set_api_error(res);
|
||||
}
|
||||
|
||||
if (not modified_) {
|
||||
mgr_.store_resume(*this);
|
||||
}
|
||||
modified_ = true;
|
||||
mgr_.remove_upload(get_api_path());
|
||||
|
||||
set_modified();
|
||||
return api_error::success;
|
||||
}
|
||||
} // namespace repertory
|
||||
|
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
Copyright <2018-2023> <scott.e.graves@protonmail.com>
|
||||
Copyright <2018-2024> <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
|
||||
|
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
Copyright <2018-2023> <scott.e.graves@protonmail.com>
|
||||
Copyright <2018-2024> <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
|
||||
@@ -22,9 +22,9 @@
|
||||
#include "file_manager/file_manager.hpp"
|
||||
|
||||
namespace repertory {
|
||||
void file_manager::open_file_base::download::notify(const api_error &e) {
|
||||
void file_manager::open_file_base::download::notify(const api_error &err) {
|
||||
complete_ = true;
|
||||
error_ = e;
|
||||
error_ = err;
|
||||
unique_mutex_lock lock(mtx_);
|
||||
notify_.notify_all();
|
||||
}
|
||||
|
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
Copyright <2018-2023> <scott.e.graves@protonmail.com>
|
||||
Copyright <2018-2024> <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
|
||||
@@ -36,6 +36,6 @@ auto file_manager::open_file_base::io_item::get_result() -> api_error {
|
||||
}
|
||||
|
||||
notify_.wait(lock);
|
||||
return result_.value();
|
||||
return result_.value_or(api_error::error);
|
||||
}
|
||||
} // namespace repertory
|
||||
|
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
Copyright <2018-2023> <scott.e.graves@protonmail.com>
|
||||
Copyright <2018-2024> <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
|
||||
@@ -85,12 +85,14 @@ file_manager::ring_buffer_open_file::ring_buffer_open_file(
|
||||
}
|
||||
|
||||
file_manager::ring_buffer_open_file::~ring_buffer_open_file() {
|
||||
constexpr const auto *function_name = static_cast<const char *>(__FUNCTION__);
|
||||
|
||||
close();
|
||||
|
||||
nf_->close();
|
||||
if (not utils::file::retry_delete_file(fsi_.source_path)) {
|
||||
utils::error::raise_api_path_error(
|
||||
__FUNCTION__, fsi_.api_path, fsi_.source_path,
|
||||
function_name, fsi_.api_path, fsi_.source_path,
|
||||
utils::get_last_error_code(), "failed to delete file");
|
||||
}
|
||||
}
|
||||
@@ -195,7 +197,7 @@ auto file_manager::ring_buffer_open_file::is_download_complete() const -> bool {
|
||||
}
|
||||
|
||||
auto file_manager::ring_buffer_open_file::native_operation(
|
||||
const i_open_file::native_operation_callback &callback) -> api_error {
|
||||
i_open_file::native_operation_callback callback) -> api_error {
|
||||
return do_io([&]() -> api_error { return callback(nf_->get_handle()); });
|
||||
}
|
||||
|
||||
@@ -258,7 +260,8 @@ auto file_manager::ring_buffer_open_file::read(std::size_t read_size,
|
||||
}
|
||||
|
||||
reset_timeout();
|
||||
if ((res = download_chunk(chunk)) == api_error::success) {
|
||||
res = download_chunk(chunk);
|
||||
if (res == api_error::success) {
|
||||
const auto to_read = std::min(
|
||||
static_cast<std::size_t>(chunk_size_ - read_offset), read_size);
|
||||
res = do_io([this, &buffer, &chunk, &data, read_offset,
|
||||
@@ -270,8 +273,10 @@ auto file_manager::ring_buffer_open_file::read(std::size_t read_size,
|
||||
? api_error::success
|
||||
: api_error::os_error;
|
||||
if (ret == api_error::success) {
|
||||
data.insert(data.end(), buffer.begin() + read_offset,
|
||||
buffer.begin() + read_offset + to_read);
|
||||
data.insert(data.end(),
|
||||
buffer.begin() + static_cast<std::int64_t>(read_offset),
|
||||
buffer.begin() +
|
||||
static_cast<std::int64_t>(read_offset + to_read));
|
||||
reset_timeout();
|
||||
}
|
||||
|
||||
|
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
Copyright <2018-2023> <scott.e.graves@protonmail.com>
|
||||
Copyright <2018-2024> <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
|
||||
@@ -27,10 +27,11 @@
|
||||
#include "utils/unix/unix_utils.hpp"
|
||||
|
||||
namespace repertory {
|
||||
using std::bind;
|
||||
|
||||
file_manager::upload::upload(filesystem_item fsi, i_provider &provider)
|
||||
: fsi_(fsi), provider_(provider) {
|
||||
thread_ =
|
||||
std::make_unique<std::thread>(std::bind(&upload::upload_thread, this));
|
||||
: fsi_(std::move(fsi)), provider_(provider) {
|
||||
thread_ = std::make_unique<std::thread>([this] { upload_thread(); });
|
||||
}
|
||||
|
||||
file_manager::upload::~upload() {
|
||||
@@ -48,11 +49,13 @@ void file_manager::upload::cancel() {
|
||||
void file_manager::upload::stop() { stop_requested_ = true; }
|
||||
|
||||
void file_manager::upload::upload_thread() {
|
||||
constexpr const auto *function_name = static_cast<const char *>(__FUNCTION__);
|
||||
|
||||
error_ =
|
||||
provider_.upload_file(fsi_.api_path, fsi_.source_path, stop_requested_);
|
||||
if (not utils::file::reset_modified_time(fsi_.source_path)) {
|
||||
utils::error::raise_api_path_error(
|
||||
__FUNCTION__, fsi_.api_path, fsi_.source_path,
|
||||
function_name, fsi_.api_path, fsi_.source_path,
|
||||
utils::get_last_error_code(), "failed to reset modified time");
|
||||
}
|
||||
|
||||
|
21
src/main.cpp
21
src/main.cpp
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
Copyright <2018-2023> <scott.e.graves@protonmail.com>
|
||||
Copyright <2018-2024> <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
|
||||
@@ -39,7 +39,12 @@ std::size_t PROVIDER_INDEX{0U};
|
||||
auto main(int argc, char **argv) -> int {
|
||||
repertory_init();
|
||||
|
||||
std::vector<const char *> args(argv, argv + argc);
|
||||
std::vector<const char *> args;
|
||||
{
|
||||
auto args_span = std::span(argv, static_cast<std::size_t>(argc));
|
||||
std::copy(args_span.begin(), args_span.end(), std::back_inserter(args));
|
||||
}
|
||||
|
||||
#ifdef REPERTORY_TESTING
|
||||
#ifdef _WIN32
|
||||
if (utils::cli::has_option(args, "--provider_index")) {
|
||||
@@ -81,9 +86,9 @@ auto main(int argc, char **argv) -> int {
|
||||
std::string unique_id;
|
||||
if ((res == exit_code::success) && (prov == provider_type::remote)) {
|
||||
std::string data;
|
||||
if ((res = utils::cli::parse_string_option(
|
||||
args, utils::cli::options::remote_mount_option, data)) ==
|
||||
exit_code::success) {
|
||||
res = utils::cli::parse_string_option(
|
||||
args, utils::cli::options::remote_mount_option, data);
|
||||
if (res == exit_code::success) {
|
||||
const auto parts = utils::string::split(data, ':');
|
||||
if (parts.size() != 2) {
|
||||
std::cerr << "Invalid syntax for host/port '-rm "
|
||||
@@ -111,9 +116,9 @@ auto main(int argc, char **argv) -> int {
|
||||
#ifdef REPERTORY_ENABLE_S3
|
||||
if ((res == exit_code::success) && (prov == provider_type::s3)) {
|
||||
std::string data;
|
||||
if ((res = utils::cli::parse_string_option(args,
|
||||
utils::cli::options::name_option,
|
||||
data)) == exit_code::success) {
|
||||
res = utils::cli::parse_string_option(
|
||||
args, utils::cli::options::name_option, data);
|
||||
if (res == exit_code::success) {
|
||||
unique_id = utils::string::trim(data);
|
||||
if (unique_id.empty()) {
|
||||
std::cerr << "Name of S3 instance not provided" << std::endl;
|
||||
|
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
Copyright <2018-2023> <scott.e.graves@protonmail.com>
|
||||
Copyright <2018-2024> <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
|
||||
@@ -101,6 +101,8 @@ auto lock_data::get_state_directory() -> std::string {
|
||||
}
|
||||
|
||||
auto lock_data::grab_lock(std::uint8_t retry_count) -> lock_result {
|
||||
constexpr const auto *function_name = static_cast<const char *>(__FUNCTION__);
|
||||
|
||||
if (lock_fd_ == -1) {
|
||||
return lock_result::failure;
|
||||
}
|
||||
@@ -109,7 +111,7 @@ auto lock_data::grab_lock(std::uint8_t retry_count) -> lock_result {
|
||||
switch (lock_status_) {
|
||||
case 0:
|
||||
if (not set_mount_state(false, "", -1)) {
|
||||
utils::error::raise_error(__FUNCTION__, "failed to set mount state");
|
||||
utils::error::raise_error(function_name, "failed to set mount state");
|
||||
}
|
||||
return lock_result::success;
|
||||
case EWOULDBLOCK:
|
||||
@@ -121,16 +123,18 @@ auto lock_data::grab_lock(std::uint8_t retry_count) -> lock_result {
|
||||
|
||||
auto lock_data::set_mount_state(bool active, const std::string &mount_location,
|
||||
int pid) -> bool {
|
||||
constexpr const auto *function_name = static_cast<const char *>(__FUNCTION__);
|
||||
|
||||
auto ret = false;
|
||||
auto fd =
|
||||
auto handle =
|
||||
open(get_lock_data_file().c_str(), O_CREAT | O_RDWR, S_IWUSR | S_IRUSR);
|
||||
if (fd != -1) {
|
||||
if (wait_for_lock(fd) == 0) {
|
||||
if (handle != -1) {
|
||||
if (wait_for_lock(handle) == 0) {
|
||||
const auto mount_id =
|
||||
app_config::get_provider_display_name(pt_) + unique_id_;
|
||||
json mount_state;
|
||||
if (not utils::file::read_json_file(get_lock_data_file(), mount_state)) {
|
||||
utils::error::raise_error(__FUNCTION__,
|
||||
utils::error::raise_error(function_name,
|
||||
"failed to read mount state file|sp|" +
|
||||
get_lock_file());
|
||||
}
|
||||
@@ -157,22 +161,25 @@ auto lock_data::set_mount_state(bool active, const std::string &mount_location,
|
||||
ret = true;
|
||||
}
|
||||
|
||||
flock(fd, LOCK_UN);
|
||||
flock(handle, LOCK_UN);
|
||||
}
|
||||
|
||||
close(fd);
|
||||
close(handle);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
auto lock_data::wait_for_lock(int fd, std::uint8_t retry_count) -> int {
|
||||
static constexpr const std::uint32_t max_sleep = 100U;
|
||||
|
||||
auto lock_status = EWOULDBLOCK;
|
||||
std::int16_t remain = retry_count * 100u;
|
||||
auto remain = static_cast<std::uint32_t>(retry_count * max_sleep);
|
||||
while ((remain > 0) && (lock_status == EWOULDBLOCK)) {
|
||||
if ((lock_status = flock(fd, LOCK_EX | LOCK_NB)) == -1) {
|
||||
if ((lock_status = errno) == EWOULDBLOCK) {
|
||||
const auto sleep_ms = utils::random_between(
|
||||
std::int16_t(1), std::min(remain, std::int16_t(100)));
|
||||
lock_status = flock(fd, LOCK_EX | LOCK_NB);
|
||||
if (lock_status == -1) {
|
||||
lock_status = errno;
|
||||
if (lock_status == EWOULDBLOCK) {
|
||||
auto sleep_ms = utils::random_between(1U, std::min(remain, max_sleep));
|
||||
std::this_thread::sleep_for(std::chrono::milliseconds(sleep_ms));
|
||||
remain -= sleep_ms;
|
||||
}
|
||||
|
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
Copyright <2018-2023> <scott.e.graves@protonmail.com>
|
||||
Copyright <2018-2024> <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
|
||||
@@ -73,6 +73,8 @@ auto lock_data::get_mount_state(json &mount_state) -> bool {
|
||||
}
|
||||
|
||||
auto lock_data::grab_lock(std::uint8_t retry_count) -> lock_result {
|
||||
constexpr const auto *function_name = static_cast<const char *>(__FUNCTION__);
|
||||
|
||||
auto ret = lock_result::success;
|
||||
if (mutex_handle_ == INVALID_HANDLE_VALUE) {
|
||||
ret = lock_result::failure;
|
||||
@@ -97,7 +99,7 @@ auto lock_data::grab_lock(std::uint8_t retry_count) -> lock_result {
|
||||
|
||||
if (should_reset) {
|
||||
if (not set_mount_state(false, "", -1)) {
|
||||
utils::error::raise_error(__FUNCTION__, "failed to set mount state");
|
||||
utils::error::raise_error(function_name, "failed to set mount state");
|
||||
}
|
||||
}
|
||||
} break;
|
||||
|
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
Copyright <2018-2023> <scott.e.graves@protonmail.com>
|
||||
Copyright <2018-2024> <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
|
||||
@@ -22,13 +22,15 @@
|
||||
#include "providers/base_provider.hpp"
|
||||
|
||||
#include "app_config.hpp"
|
||||
#include "database/db_common.hpp"
|
||||
#include "database/db_insert.hpp"
|
||||
#include "database/db_select.hpp"
|
||||
#include "events/event_system.hpp"
|
||||
#include "events/events.hpp"
|
||||
#include "file_manager/i_file_manager.hpp"
|
||||
#include "utils/file_utils.hpp"
|
||||
#include "utils/path_utils.hpp"
|
||||
#include "utils/polling.hpp"
|
||||
#include "utils/rocksdb_utils.hpp"
|
||||
|
||||
namespace repertory {
|
||||
auto base_provider::create_api_file(std::string path, std::string key,
|
||||
@@ -66,13 +68,15 @@ auto base_provider::create_api_file(std::string path, std::uint64_t size,
|
||||
auto base_provider::create_directory_clone_source_meta(
|
||||
const std::string &source_api_path, const std::string &api_path)
|
||||
-> api_error {
|
||||
constexpr const auto *function_name = static_cast<const char *>(__FUNCTION__);
|
||||
|
||||
bool exists{};
|
||||
auto res = is_file(source_api_path, exists);
|
||||
if (res != api_error::success) {
|
||||
return res;
|
||||
}
|
||||
if (exists) {
|
||||
utils::error::raise_api_path_error(__FUNCTION__, api_path,
|
||||
utils::error::raise_api_path_error(function_name, api_path,
|
||||
api_error::item_exists,
|
||||
"failed to create directory");
|
||||
return api_error::item_exists;
|
||||
@@ -83,7 +87,7 @@ auto base_provider::create_directory_clone_source_meta(
|
||||
return res;
|
||||
}
|
||||
if (exists) {
|
||||
utils::error::raise_api_path_error(__FUNCTION__, api_path,
|
||||
utils::error::raise_api_path_error(function_name, api_path,
|
||||
api_error::directory_exists,
|
||||
"failed to create directory");
|
||||
return api_error::directory_exists;
|
||||
@@ -94,7 +98,7 @@ auto base_provider::create_directory_clone_source_meta(
|
||||
return res;
|
||||
}
|
||||
if (exists) {
|
||||
utils::error::raise_api_path_error(__FUNCTION__, api_path,
|
||||
utils::error::raise_api_path_error(function_name, api_path,
|
||||
api_error::item_exists,
|
||||
"failed to create directory");
|
||||
return api_error::item_exists;
|
||||
@@ -106,7 +110,7 @@ auto base_provider::create_directory_clone_source_meta(
|
||||
if (res == api_error::item_not_found) {
|
||||
res = api_error::directory_not_found;
|
||||
}
|
||||
utils::error::raise_api_path_error(__FUNCTION__, api_path, res,
|
||||
utils::error::raise_api_path_error(function_name, api_path, res,
|
||||
"failed to create directory");
|
||||
return res;
|
||||
}
|
||||
@@ -116,13 +120,15 @@ auto base_provider::create_directory_clone_source_meta(
|
||||
|
||||
auto base_provider::create_directory(const std::string &api_path,
|
||||
api_meta_map &meta) -> api_error {
|
||||
constexpr const auto *function_name = static_cast<const char *>(__FUNCTION__);
|
||||
|
||||
bool exists{};
|
||||
auto res = is_directory(api_path, exists);
|
||||
if (res != api_error::success) {
|
||||
return res;
|
||||
}
|
||||
if (exists) {
|
||||
utils::error::raise_api_path_error(__FUNCTION__, api_path,
|
||||
utils::error::raise_api_path_error(function_name, api_path,
|
||||
api_error::directory_exists,
|
||||
"failed to create directory");
|
||||
return api_error::directory_exists;
|
||||
@@ -130,12 +136,12 @@ auto base_provider::create_directory(const std::string &api_path,
|
||||
|
||||
res = is_file(api_path, exists);
|
||||
if (res != api_error::success) {
|
||||
utils::error::raise_api_path_error(__FUNCTION__, api_path, res,
|
||||
utils::error::raise_api_path_error(function_name, api_path, res,
|
||||
"failed to create directory");
|
||||
return res;
|
||||
}
|
||||
if (exists) {
|
||||
utils::error::raise_api_path_error(__FUNCTION__, api_path,
|
||||
utils::error::raise_api_path_error(function_name, api_path,
|
||||
api_error::item_exists,
|
||||
"failed to create directory");
|
||||
return api_error::item_exists;
|
||||
@@ -144,12 +150,12 @@ auto base_provider::create_directory(const std::string &api_path,
|
||||
try {
|
||||
res = create_directory_impl(api_path, meta);
|
||||
if (res != api_error::success) {
|
||||
utils::error::raise_api_path_error(__FUNCTION__, api_path, res,
|
||||
utils::error::raise_api_path_error(function_name, api_path, res,
|
||||
"failed to create directory");
|
||||
return res;
|
||||
}
|
||||
} catch (const std::exception &e) {
|
||||
utils::error::raise_api_path_error(__FUNCTION__, api_path, e,
|
||||
utils::error::raise_api_path_error(function_name, api_path, e,
|
||||
"failed to create directory");
|
||||
return api_error::error;
|
||||
}
|
||||
@@ -160,13 +166,15 @@ auto base_provider::create_directory(const std::string &api_path,
|
||||
|
||||
auto base_provider::create_file(const std::string &api_path, api_meta_map &meta)
|
||||
-> api_error {
|
||||
constexpr const auto *function_name = static_cast<const char *>(__FUNCTION__);
|
||||
|
||||
bool exists{};
|
||||
auto res = is_directory(api_path, exists);
|
||||
if (res != api_error::success && res != api_error::item_not_found) {
|
||||
return res;
|
||||
}
|
||||
if (exists) {
|
||||
utils::error::raise_api_path_error(__FUNCTION__, api_path,
|
||||
utils::error::raise_api_path_error(function_name, api_path,
|
||||
api_error::directory_exists,
|
||||
"failed to create file");
|
||||
return api_error::directory_exists;
|
||||
@@ -177,7 +185,7 @@ auto base_provider::create_file(const std::string &api_path, api_meta_map &meta)
|
||||
return res;
|
||||
}
|
||||
if (exists) {
|
||||
utils::error::raise_api_path_error(__FUNCTION__, api_path,
|
||||
utils::error::raise_api_path_error(function_name, api_path,
|
||||
api_error::item_exists,
|
||||
"failed to create file");
|
||||
return api_error::item_exists;
|
||||
@@ -186,7 +194,7 @@ auto base_provider::create_file(const std::string &api_path, api_meta_map &meta)
|
||||
try {
|
||||
res = create_file_extra(api_path, meta);
|
||||
if (res != api_error::success) {
|
||||
utils::error::raise_api_path_error(__FUNCTION__, api_path, res,
|
||||
utils::error::raise_api_path_error(function_name, api_path, res,
|
||||
"failed to create file");
|
||||
return res;
|
||||
}
|
||||
@@ -194,7 +202,7 @@ auto base_provider::create_file(const std::string &api_path, api_meta_map &meta)
|
||||
meta[META_DIRECTORY] = utils::string::from_bool(false);
|
||||
res = set_item_meta(api_path, meta);
|
||||
if (res != api_error::success) {
|
||||
utils::error::raise_api_path_error(__FUNCTION__, api_path, res,
|
||||
utils::error::raise_api_path_error(function_name, api_path, res,
|
||||
"failed to create file");
|
||||
return res;
|
||||
}
|
||||
@@ -202,12 +210,12 @@ auto base_provider::create_file(const std::string &api_path, api_meta_map &meta)
|
||||
stop_type stop_requested{false};
|
||||
res = upload_file(api_path, meta[META_SOURCE], stop_requested);
|
||||
if (res != api_error::success) {
|
||||
get_db()->Delete(rocksdb::WriteOptions(), api_path);
|
||||
db3_->remove_api_path(api_path);
|
||||
}
|
||||
|
||||
return res;
|
||||
} catch (const std::exception &e) {
|
||||
utils::error::raise_api_path_error(__FUNCTION__, api_path, e,
|
||||
utils::error::raise_api_path_error(function_name, api_path, e,
|
||||
"failed to create file");
|
||||
}
|
||||
|
||||
@@ -217,38 +225,23 @@ auto base_provider::create_file(const std::string &api_path, api_meta_map &meta)
|
||||
auto base_provider::get_api_path_from_source(const std::string &source_path,
|
||||
std::string &api_path) const
|
||||
-> api_error {
|
||||
constexpr const auto *function_name = static_cast<const char *>(__FUNCTION__);
|
||||
|
||||
if (source_path.empty()) {
|
||||
utils::error::raise_api_path_error(__FUNCTION__, api_path,
|
||||
utils::error::raise_api_path_error(function_name, api_path,
|
||||
api_error::item_not_found,
|
||||
"failed to source path from api path");
|
||||
return api_error::item_not_found;
|
||||
}
|
||||
|
||||
auto iterator = std::unique_ptr<rocksdb::Iterator>(
|
||||
db_->NewIterator(rocksdb::ReadOptions()));
|
||||
for (iterator->SeekToFirst(); iterator->Valid(); iterator->Next()) {
|
||||
std::string current_source_path{};
|
||||
if (get_item_meta(iterator->key().ToString(), META_SOURCE,
|
||||
current_source_path) != api_error::success) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (current_source_path.empty()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (current_source_path == source_path) {
|
||||
api_path = iterator->key().ToString();
|
||||
return api_error::success;
|
||||
}
|
||||
}
|
||||
|
||||
return api_error::item_not_found;
|
||||
return db3_->get_api_path(source_path, api_path);
|
||||
}
|
||||
|
||||
auto base_provider::get_directory_items(const std::string &api_path,
|
||||
directory_item_list &list) const
|
||||
-> api_error {
|
||||
constexpr const auto *function_name = static_cast<const char *>(__FUNCTION__);
|
||||
|
||||
bool exists{};
|
||||
auto res = is_directory(api_path, exists);
|
||||
if (res != api_error::success) {
|
||||
@@ -264,7 +257,7 @@ auto base_provider::get_directory_items(const std::string &api_path,
|
||||
return res;
|
||||
}
|
||||
} catch (const std::exception &e) {
|
||||
utils::error::raise_api_path_error(__FUNCTION__, api_path, e,
|
||||
utils::error::raise_api_path_error(function_name, api_path, e,
|
||||
"failed to get directory items");
|
||||
return api_error::error;
|
||||
}
|
||||
@@ -392,81 +385,32 @@ auto base_provider::get_filesystem_item_from_source_path(
|
||||
|
||||
auto base_provider::get_item_meta(const std::string &api_path,
|
||||
api_meta_map &meta) const -> api_error {
|
||||
std::string meta_value{};
|
||||
db_->Get(rocksdb::ReadOptions(), api_path, &meta_value);
|
||||
if (meta_value.empty()) {
|
||||
return api_error::item_not_found;
|
||||
}
|
||||
|
||||
try {
|
||||
meta = json::parse(meta_value).get<api_meta_map>();
|
||||
|
||||
return api_error::success;
|
||||
} catch (const std::exception &e) {
|
||||
utils::error::raise_api_path_error(__FUNCTION__, api_path, e,
|
||||
"failed to get item meta");
|
||||
}
|
||||
|
||||
return api_error::error;
|
||||
return db3_->get_item_meta(api_path, meta);
|
||||
}
|
||||
|
||||
auto base_provider::get_item_meta(const std::string &api_path,
|
||||
const std::string &key,
|
||||
std::string &value) const -> api_error {
|
||||
std::string meta_value{};
|
||||
db_->Get(rocksdb::ReadOptions(), api_path, &meta_value);
|
||||
if (meta_value.empty()) {
|
||||
return api_error::item_not_found;
|
||||
}
|
||||
|
||||
try {
|
||||
value = json::parse(meta_value)[key];
|
||||
return api_error::success;
|
||||
} catch (const std::exception &e) {
|
||||
utils::error::raise_api_path_error(__FUNCTION__, api_path, e,
|
||||
"failed to get item meta");
|
||||
}
|
||||
|
||||
return api_error::error;
|
||||
return db3_->get_item_meta(api_path, key, value);
|
||||
}
|
||||
|
||||
auto base_provider::get_pinned_files() const -> std::vector<std::string> {
|
||||
std::vector<std::string> ret{};
|
||||
|
||||
auto iterator = std::unique_ptr<rocksdb::Iterator>(
|
||||
db_->NewIterator(rocksdb::ReadOptions()));
|
||||
for (iterator->SeekToFirst(); iterator->Valid(); iterator->Next()) {
|
||||
std::string pinned{};
|
||||
if (get_item_meta(iterator->key().ToString(), META_PINNED, pinned) !=
|
||||
api_error::success) {
|
||||
continue;
|
||||
}
|
||||
if (pinned.empty() || not utils::string::to_bool(pinned)) {
|
||||
continue;
|
||||
}
|
||||
ret.emplace_back(iterator->key().ToString());
|
||||
}
|
||||
|
||||
return ret;
|
||||
return db3_->get_pinned_files();
|
||||
}
|
||||
|
||||
auto base_provider::get_total_item_count() const -> std::uint64_t {
|
||||
std::uint64_t ret{};
|
||||
auto iterator = std::unique_ptr<rocksdb::Iterator>(
|
||||
db_->NewIterator(rocksdb::ReadOptions()));
|
||||
for (iterator->SeekToFirst(); iterator->Valid(); iterator->Next()) {
|
||||
ret++;
|
||||
}
|
||||
return ret;
|
||||
return db3_->get_total_item_count();
|
||||
}
|
||||
|
||||
auto base_provider::get_used_drive_space() const -> std::uint64_t {
|
||||
constexpr const auto *function_name = static_cast<const char *>(__FUNCTION__);
|
||||
|
||||
try {
|
||||
auto used_space = get_used_drive_space_impl();
|
||||
get_file_mgr()->update_used_space(used_space);
|
||||
return used_space;
|
||||
} catch (const std::exception &ex) {
|
||||
utils::error::raise_error(__FUNCTION__, ex,
|
||||
utils::error::raise_error(function_name, ex,
|
||||
"failed to get used drive space");
|
||||
}
|
||||
|
||||
@@ -485,6 +429,8 @@ auto base_provider::is_file_writeable(const std::string &api_path) const
|
||||
}
|
||||
|
||||
void base_provider::remove_deleted_files() {
|
||||
constexpr const auto *function_name = static_cast<const char *>(__FUNCTION__);
|
||||
|
||||
struct removed_item {
|
||||
std::string api_path{};
|
||||
bool directory{};
|
||||
@@ -494,36 +440,33 @@ void base_provider::remove_deleted_files() {
|
||||
api_file_list list{};
|
||||
auto res = get_file_list(list);
|
||||
if (res != api_error::success) {
|
||||
utils::error::raise_error(__FUNCTION__, res, "failed to get file list");
|
||||
utils::error::raise_error(function_name, res, "failed to get file list");
|
||||
return;
|
||||
}
|
||||
|
||||
std::vector<removed_item> removed_list{};
|
||||
auto iterator = std::unique_ptr<rocksdb::Iterator>(
|
||||
db_->NewIterator(rocksdb::ReadOptions()));
|
||||
for (iterator->SeekToFirst(); iterator->Valid(); iterator->Next()) {
|
||||
|
||||
for (const auto &api_path : db3_->get_api_path_list()) {
|
||||
api_meta_map meta{};
|
||||
if (get_item_meta(iterator->key().ToString(), meta) == api_error::success) {
|
||||
if (get_item_meta(api_path, meta) == api_error::success) {
|
||||
if (utils::string::to_bool(meta[META_DIRECTORY])) {
|
||||
bool exists{};
|
||||
if (is_directory(iterator->key().ToString(), exists) !=
|
||||
api_error::success) {
|
||||
if (is_directory(api_path, exists) != api_error::success) {
|
||||
continue;
|
||||
}
|
||||
if (not exists) {
|
||||
removed_list.emplace_back(
|
||||
removed_item{iterator->key().ToString(), true, ""});
|
||||
removed_list.emplace_back(removed_item{api_path, true, ""});
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
bool exists{};
|
||||
if (is_file(iterator->key().ToString(), exists) != api_error::success) {
|
||||
if (is_file(api_path, exists) != api_error::success) {
|
||||
continue;
|
||||
}
|
||||
if (not exists) {
|
||||
removed_list.emplace_back(
|
||||
removed_item{iterator->key().ToString(), false, meta[META_SOURCE]});
|
||||
removed_item{api_path, false, meta[META_SOURCE]});
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -553,14 +496,14 @@ void base_provider::remove_deleted_files() {
|
||||
}
|
||||
} else {
|
||||
utils::error::raise_error(
|
||||
__FUNCTION__, std::to_string(utils::get_last_error_code()),
|
||||
function_name, std::to_string(utils::get_last_error_code()),
|
||||
"failed to create orphaned director|sp|" + orphaned_directory);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
if (fm_->evict_file(item.api_path)) {
|
||||
db_->Delete(rocksdb::WriteOptions(), item.api_path);
|
||||
db3_->remove_api_path(item.api_path);
|
||||
event_system::instance().raise<file_removed_externally>(
|
||||
item.api_path, item.source_path);
|
||||
}
|
||||
@@ -569,7 +512,7 @@ void base_provider::remove_deleted_files() {
|
||||
|
||||
for (const auto &item : removed_list) {
|
||||
if (item.directory) {
|
||||
db_->Delete(rocksdb::WriteOptions(), item.api_path);
|
||||
db3_->remove_api_path(item.api_path);
|
||||
event_system::instance().raise<directory_removed_externally>(
|
||||
item.api_path, item.source_path);
|
||||
}
|
||||
@@ -588,20 +531,10 @@ auto base_provider::remove_file(const std::string &api_path) -> api_error {
|
||||
return error;
|
||||
};
|
||||
|
||||
const auto *const function_name = __FUNCTION__;
|
||||
|
||||
const auto remove_file_meta = [this, &api_path, &function_name,
|
||||
¬ify_end]() -> api_error {
|
||||
const auto remove_file_meta = [this, &api_path, ¬ify_end]() -> api_error {
|
||||
api_meta_map meta{};
|
||||
auto res = get_item_meta(api_path, meta);
|
||||
|
||||
auto res2 = get_db()->Delete(rocksdb::WriteOptions(), api_path);
|
||||
if (not res2.ok()) {
|
||||
utils::error::raise_api_path_error(function_name, api_path, res2.code(),
|
||||
"failed to remove file");
|
||||
return notify_end(api_error::error);
|
||||
}
|
||||
|
||||
db3_->remove_api_path(api_path);
|
||||
return notify_end(res);
|
||||
};
|
||||
|
||||
@@ -658,109 +591,42 @@ auto base_provider::remove_directory(const std::string &api_path) -> api_error {
|
||||
return notify_end(res);
|
||||
}
|
||||
|
||||
auto status = get_db()->Delete(rocksdb::WriteOptions(), api_path);
|
||||
if (not status.ok()) {
|
||||
utils::error::raise_api_path_error(__FUNCTION__, api_path, status.code(),
|
||||
"failed to remove directory");
|
||||
return notify_end(api_error::error);
|
||||
}
|
||||
db3_->remove_api_path(api_path);
|
||||
|
||||
return notify_end(api_error::success);
|
||||
}
|
||||
|
||||
auto base_provider::remove_item_meta(const std::string &api_path,
|
||||
const std::string &key) -> api_error {
|
||||
api_meta_map meta{};
|
||||
auto res = get_item_meta(api_path, meta);
|
||||
if (res != api_error::success) {
|
||||
return res;
|
||||
}
|
||||
|
||||
meta.erase(key);
|
||||
|
||||
auto res2 = db_->Put(rocksdb::WriteOptions(), api_path, json(meta).dump());
|
||||
if (not res2.ok()) {
|
||||
utils::error::raise_api_path_error(__FUNCTION__, api_path, res2.code(),
|
||||
"failed to remove item meta");
|
||||
return api_error::error;
|
||||
}
|
||||
|
||||
return api_error::success;
|
||||
return db3_->remove_item_meta(api_path, key);
|
||||
}
|
||||
|
||||
auto base_provider::set_item_meta(const std::string &api_path,
|
||||
const std::string &key,
|
||||
const std::string &value) -> api_error {
|
||||
json meta_json{};
|
||||
std::string meta_value{};
|
||||
db_->Get(rocksdb::ReadOptions(), api_path, &meta_value);
|
||||
if (not meta_value.empty()) {
|
||||
try {
|
||||
meta_json = json::parse(meta_value);
|
||||
} catch (const std::exception &e) {
|
||||
utils::error::raise_api_path_error(__FUNCTION__, api_path, e,
|
||||
"failed to set item meta");
|
||||
return api_error::error;
|
||||
}
|
||||
}
|
||||
|
||||
meta_json[key] = value;
|
||||
|
||||
const auto res =
|
||||
db_->Put(rocksdb::WriteOptions(), api_path, meta_json.dump());
|
||||
if (not res.ok()) {
|
||||
utils::error::raise_api_path_error(__FUNCTION__, api_path, res.code(),
|
||||
"failed to set item meta");
|
||||
return api_error::error;
|
||||
}
|
||||
|
||||
return api_error::success;
|
||||
return db3_->set_item_meta(api_path, key, value);
|
||||
}
|
||||
|
||||
auto base_provider::set_item_meta(const std::string &api_path,
|
||||
const api_meta_map &meta) -> api_error {
|
||||
json meta_json{};
|
||||
std::string meta_value{};
|
||||
db_->Get(rocksdb::ReadOptions(), api_path, &meta_value);
|
||||
if (not meta_value.empty()) {
|
||||
try {
|
||||
meta_json = json::parse(meta_value);
|
||||
} catch (const std::exception &e) {
|
||||
utils::error::raise_api_path_error(__FUNCTION__, api_path, e,
|
||||
"failed to set item meta");
|
||||
return api_error::error;
|
||||
}
|
||||
}
|
||||
|
||||
for (const auto &kv : meta) {
|
||||
meta_json[kv.first] = kv.second;
|
||||
}
|
||||
|
||||
const auto res =
|
||||
db_->Put(rocksdb::WriteOptions(), api_path, meta_json.dump());
|
||||
if (not res.ok()) {
|
||||
utils::error::raise_api_path_error(__FUNCTION__, api_path, res.code(),
|
||||
"failed to set item meta");
|
||||
return api_error::error;
|
||||
}
|
||||
|
||||
return api_error::success;
|
||||
return db3_->set_item_meta(api_path, meta);
|
||||
}
|
||||
|
||||
auto base_provider::start(api_item_added_callback api_item_added,
|
||||
i_file_manager *mgr) -> bool {
|
||||
utils::db::create_rocksdb(config_, DB_NAME, db_);
|
||||
|
||||
api_item_added_ = api_item_added;
|
||||
fm_ = mgr;
|
||||
|
||||
db3_ = std::make_unique<meta_db>(config_);
|
||||
|
||||
api_meta_map meta{};
|
||||
if (get_item_meta("/", meta) == api_error::item_not_found) {
|
||||
auto dir = create_api_file("/", "", 0U);
|
||||
api_item_added_(true, dir);
|
||||
}
|
||||
|
||||
auto online = false;
|
||||
auto unmount_requested = false;
|
||||
auto online{false};
|
||||
auto unmount_requested{false};
|
||||
{
|
||||
repertory::event_consumer consumer(
|
||||
"unmount_requested",
|
||||
@@ -789,12 +655,14 @@ auto base_provider::start(api_item_added_callback api_item_added,
|
||||
|
||||
void base_provider::stop() {
|
||||
polling::instance().remove_callback("check_deleted");
|
||||
db_.reset();
|
||||
db3_.reset();
|
||||
}
|
||||
|
||||
auto base_provider::upload_file(const std::string &api_path,
|
||||
const std::string &source_path,
|
||||
stop_type &stop_requested) -> api_error {
|
||||
constexpr const auto *function_name = static_cast<const char *>(__FUNCTION__);
|
||||
|
||||
event_system::instance().raise<provider_upload_begin>(api_path, source_path);
|
||||
|
||||
const auto notify_end = [&api_path,
|
||||
@@ -806,7 +674,7 @@ auto base_provider::upload_file(const std::string &api_path,
|
||||
try {
|
||||
return notify_end(upload_file_impl(api_path, source_path, stop_requested));
|
||||
} catch (const std::exception &e) {
|
||||
utils::error::raise_error(__FUNCTION__, e, "exception occurred");
|
||||
utils::error::raise_error(function_name, e, "exception occurred");
|
||||
}
|
||||
|
||||
return notify_end(api_error::error);
|
||||
|
File diff suppressed because it is too large
Load Diff
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
Copyright <2018-2023> <scott.e.graves@protonmail.com>
|
||||
Copyright <2018-2024> <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
|
||||
|
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
Copyright <2018-2023> <scott.e.graves@protonmail.com>
|
||||
Copyright <2018-2024> <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
|
||||
@@ -36,7 +36,6 @@
|
||||
#include "utils/file_utils.hpp"
|
||||
#include "utils/path_utils.hpp"
|
||||
#include "utils/polling.hpp"
|
||||
#include "utils/rocksdb_utils.hpp"
|
||||
#include "utils/string_utils.hpp"
|
||||
|
||||
namespace repertory {
|
||||
@@ -64,6 +63,8 @@ auto s3_provider::add_if_not_found(api_file &file,
|
||||
|
||||
auto s3_provider::create_directory_impl(const std::string &api_path,
|
||||
api_meta_map &meta) -> api_error {
|
||||
constexpr const auto *function_name = static_cast<const char *>(__FUNCTION__);
|
||||
|
||||
const auto cfg = get_config().get_s3_config();
|
||||
const auto is_encrypted = not cfg.encryption_token.empty();
|
||||
stop_type stop_requested{false};
|
||||
@@ -73,7 +74,7 @@ auto s3_provider::create_directory_impl(const std::string &api_path,
|
||||
auto res = get_item_meta(utils::path::get_parent_api_path(api_path),
|
||||
META_KEY, encrypted_file_path);
|
||||
if (res != api_error::success) {
|
||||
utils::error::raise_api_path_error(__FUNCTION__, api_path, res,
|
||||
utils::error::raise_api_path_error(function_name, api_path, res,
|
||||
"failed to create file");
|
||||
return res;
|
||||
}
|
||||
@@ -98,14 +99,14 @@ auto s3_provider::create_directory_impl(const std::string &api_path,
|
||||
|
||||
long response_code{};
|
||||
if (not get_comm().make_request(put_file, response_code, stop_requested)) {
|
||||
utils::error::raise_api_path_error(__FUNCTION__, api_path,
|
||||
utils::error::raise_api_path_error(function_name, api_path,
|
||||
api_error::comm_error,
|
||||
"failed to create directory");
|
||||
return api_error::comm_error;
|
||||
}
|
||||
|
||||
if (response_code != http_error_codes::ok) {
|
||||
utils::error::raise_api_path_error(__FUNCTION__, api_path, response_code,
|
||||
utils::error::raise_api_path_error(function_name, api_path, response_code,
|
||||
"failed to create directory");
|
||||
return api_error::comm_error;
|
||||
}
|
||||
@@ -115,12 +116,14 @@ auto s3_provider::create_directory_impl(const std::string &api_path,
|
||||
|
||||
auto s3_provider::create_file_extra(const std::string &api_path,
|
||||
api_meta_map &meta) -> api_error {
|
||||
constexpr const auto *function_name = static_cast<const char *>(__FUNCTION__);
|
||||
|
||||
if (not get_config().get_s3_config().encryption_token.empty()) {
|
||||
std::string encrypted_file_path;
|
||||
auto res = get_item_meta(utils::path::get_parent_api_path(api_path),
|
||||
META_KEY, encrypted_file_path);
|
||||
if (res != api_error::success) {
|
||||
utils::error::raise_api_path_error(__FUNCTION__, api_path, res,
|
||||
utils::error::raise_api_path_error(function_name, api_path, res,
|
||||
"failed to create file");
|
||||
return res;
|
||||
}
|
||||
@@ -198,6 +201,8 @@ auto s3_provider::decrypt_object_name(std::string &object_name) const
|
||||
|
||||
auto s3_provider::get_directory_item_count(const std::string &api_path) const
|
||||
-> std::uint64_t {
|
||||
constexpr const auto *function_name = static_cast<const char *>(__FUNCTION__);
|
||||
|
||||
try {
|
||||
const auto cfg = get_config().get_s3_config();
|
||||
const auto is_encrypted = not cfg.encryption_token.empty();
|
||||
@@ -248,7 +253,7 @@ auto s3_provider::get_directory_item_count(const std::string &api_path) const
|
||||
|
||||
return ret;
|
||||
} catch (const std::exception &e) {
|
||||
utils::error::raise_error(__FUNCTION__, e, "exception occurred");
|
||||
utils::error::raise_error(function_name, e, "exception occurred");
|
||||
}
|
||||
|
||||
return 0U;
|
||||
@@ -372,6 +377,8 @@ auto s3_provider::get_directory_items_impl(const std::string &api_path,
|
||||
|
||||
auto s3_provider::get_file(const std::string &api_path, api_file &file) const
|
||||
-> api_error {
|
||||
constexpr const auto *function_name = static_cast<const char *>(__FUNCTION__);
|
||||
|
||||
try {
|
||||
bool is_encrypted{};
|
||||
std::string object_name;
|
||||
@@ -395,7 +402,7 @@ auto s3_provider::get_file(const std::string &api_path, api_file &file) const
|
||||
file.modified_date = utils::aws::format_time(result.last_modified);
|
||||
return add_if_not_found(file, object_name);
|
||||
} catch (const std::exception &e) {
|
||||
utils::error::raise_error(__FUNCTION__, e, "exception occurred");
|
||||
utils::error::raise_error(function_name, e, "exception occurred");
|
||||
}
|
||||
|
||||
return api_error::error;
|
||||
@@ -465,6 +472,8 @@ auto s3_provider::get_object_info(bool directory, const std::string &api_path,
|
||||
bool &is_encrypted, std::string &object_name,
|
||||
head_object_result &result) const
|
||||
-> api_error {
|
||||
constexpr const auto *function_name = static_cast<const char *>(__FUNCTION__);
|
||||
|
||||
try {
|
||||
const auto cfg = get_config().get_s3_config();
|
||||
is_encrypted = not cfg.encryption_token.empty();
|
||||
@@ -503,7 +512,7 @@ auto s3_provider::get_object_info(bool directory, const std::string &api_path,
|
||||
|
||||
return api_error::success;
|
||||
} catch (const std::exception &e) {
|
||||
utils::error::raise_error(__FUNCTION__, e, "exception occurred");
|
||||
utils::error::raise_error(function_name, e, "exception occurred");
|
||||
}
|
||||
|
||||
return api_error::error;
|
||||
@@ -572,6 +581,8 @@ auto s3_provider::get_used_drive_space_impl() const -> std::uint64_t {
|
||||
|
||||
auto s3_provider::is_directory(const std::string &api_path, bool &exists) const
|
||||
-> api_error {
|
||||
constexpr const auto *function_name = static_cast<const char *>(__FUNCTION__);
|
||||
|
||||
exists = false;
|
||||
if (api_path == "/") {
|
||||
exists = true;
|
||||
@@ -590,7 +601,7 @@ auto s3_provider::is_directory(const std::string &api_path, bool &exists) const
|
||||
exists = res != api_error::item_not_found;
|
||||
return api_error::success;
|
||||
} catch (const std::exception &e) {
|
||||
utils::error::raise_error(__FUNCTION__, e, "exception occurred");
|
||||
utils::error::raise_error(function_name, e, "exception occurred");
|
||||
}
|
||||
|
||||
return api_error::error;
|
||||
@@ -598,6 +609,8 @@ auto s3_provider::is_directory(const std::string &api_path, bool &exists) const
|
||||
|
||||
auto s3_provider::is_file(const std::string &api_path, bool &exists) const
|
||||
-> api_error {
|
||||
constexpr const auto *function_name = static_cast<const char *>(__FUNCTION__);
|
||||
|
||||
exists = false;
|
||||
if (api_path == "/") {
|
||||
return api_error::success;
|
||||
@@ -615,7 +628,7 @@ auto s3_provider::is_file(const std::string &api_path, bool &exists) const
|
||||
exists = res != api_error::item_not_found;
|
||||
return api_error::success;
|
||||
} catch (const std::exception &e) {
|
||||
utils::error::raise_error(__FUNCTION__, e, "exception occurred");
|
||||
utils::error::raise_error(function_name, e, "exception occurred");
|
||||
}
|
||||
|
||||
return api_error::error;
|
||||
@@ -629,6 +642,8 @@ auto s3_provider::is_online() const -> bool {
|
||||
auto s3_provider::read_file_bytes(const std::string &api_path, std::size_t size,
|
||||
std::uint64_t offset, data_buffer &data,
|
||||
stop_type &stop_requested) -> api_error {
|
||||
constexpr const auto *function_name = static_cast<const char *>(__FUNCTION__);
|
||||
|
||||
try {
|
||||
const auto cfg = get_config().get_s3_config();
|
||||
const auto is_encrypted = not cfg.encryption_token.empty();
|
||||
@@ -669,13 +684,13 @@ auto s3_provider::read_file_bytes(const std::string &api_path, std::size_t size,
|
||||
const auto notify_retry = [&]() {
|
||||
if (response_code == 0) {
|
||||
utils::error::raise_api_path_error(
|
||||
__FUNCTION__, api_path, api_error::comm_error,
|
||||
function_name, api_path, api_error::comm_error,
|
||||
"read file bytes failed|offset|" + std::to_string(read_offset) +
|
||||
"|size|" + std::to_string(read_size) + "|retry|" +
|
||||
std::to_string(i + 1U));
|
||||
} else {
|
||||
utils::error::raise_api_path_error(
|
||||
__FUNCTION__, api_path, response_code,
|
||||
function_name, api_path, response_code,
|
||||
"read file bytes failed|offset|" + std::to_string(read_offset) +
|
||||
"|size|" + std::to_string(read_size) + "|retry|" +
|
||||
std::to_string(i + 1U));
|
||||
@@ -721,7 +736,7 @@ auto s3_provider::read_file_bytes(const std::string &api_path, std::size_t size,
|
||||
|
||||
return read_bytes(size, offset, data);
|
||||
} catch (const std::exception &e) {
|
||||
utils::error::raise_error(__FUNCTION__, e, "exception occurred");
|
||||
utils::error::raise_error(function_name, e, "exception occurred");
|
||||
}
|
||||
|
||||
return api_error::error;
|
||||
@@ -729,6 +744,8 @@ auto s3_provider::read_file_bytes(const std::string &api_path, std::size_t size,
|
||||
|
||||
auto s3_provider::remove_directory_impl(const std::string &api_path)
|
||||
-> api_error {
|
||||
constexpr const auto *function_name = static_cast<const char *>(__FUNCTION__);
|
||||
|
||||
const auto cfg = get_config().get_s3_config();
|
||||
const auto is_encrypted = not cfg.encryption_token.empty();
|
||||
|
||||
@@ -751,7 +768,7 @@ auto s3_provider::remove_directory_impl(const std::string &api_path)
|
||||
long response_code{};
|
||||
stop_type stop_requested{};
|
||||
if (not get_comm().make_request(del, response_code, stop_requested)) {
|
||||
utils::error::raise_api_path_error(__FUNCTION__, api_path,
|
||||
utils::error::raise_api_path_error(function_name, api_path,
|
||||
api_error::comm_error,
|
||||
"failed to remove directory");
|
||||
return api_error::comm_error;
|
||||
@@ -760,7 +777,7 @@ auto s3_provider::remove_directory_impl(const std::string &api_path)
|
||||
if ((response_code < http_error_codes::ok ||
|
||||
response_code >= http_error_codes::multiple_choices) &&
|
||||
response_code != http_error_codes::not_found) {
|
||||
utils::error::raise_api_path_error(__FUNCTION__, api_path, response_code,
|
||||
utils::error::raise_api_path_error(function_name, api_path, response_code,
|
||||
"failed to remove directory");
|
||||
return api_error::comm_error;
|
||||
}
|
||||
@@ -769,6 +786,8 @@ auto s3_provider::remove_directory_impl(const std::string &api_path)
|
||||
}
|
||||
|
||||
auto s3_provider::remove_file_impl(const std::string &api_path) -> api_error {
|
||||
constexpr const auto *function_name = static_cast<const char *>(__FUNCTION__);
|
||||
|
||||
const auto cfg = get_config().get_s3_config();
|
||||
const auto is_encrypted = not cfg.encryption_token.empty();
|
||||
|
||||
@@ -791,15 +810,16 @@ auto s3_provider::remove_file_impl(const std::string &api_path) -> api_error {
|
||||
long response_code{};
|
||||
stop_type stop_requested{};
|
||||
if (not get_comm().make_request(del, response_code, stop_requested)) {
|
||||
utils::error::raise_api_path_error(
|
||||
__FUNCTION__, api_path, api_error::comm_error, "failed to remove file");
|
||||
utils::error::raise_api_path_error(function_name, api_path,
|
||||
api_error::comm_error,
|
||||
"failed to remove file");
|
||||
return api_error::comm_error;
|
||||
}
|
||||
|
||||
if ((response_code < http_error_codes::ok ||
|
||||
response_code >= http_error_codes::multiple_choices) &&
|
||||
response_code != http_error_codes::not_found) {
|
||||
utils::error::raise_api_path_error(__FUNCTION__, api_path, response_code,
|
||||
utils::error::raise_api_path_error(function_name, api_path, response_code,
|
||||
"failed to remove file");
|
||||
return api_error::comm_error;
|
||||
}
|
||||
|
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
Copyright <2018-2023> <scott.e.graves@protonmail.com>
|
||||
Copyright <2018-2024> <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
|
||||
@@ -31,7 +31,6 @@
|
||||
#include "utils/file_utils.hpp"
|
||||
#include "utils/path_utils.hpp"
|
||||
#include "utils/polling.hpp"
|
||||
#include "utils/rocksdb_utils.hpp"
|
||||
#include "utils/string_utils.hpp"
|
||||
#include "utils/utils.hpp"
|
||||
|
||||
@@ -42,6 +41,8 @@ sia_provider::sia_provider(app_config &config, i_http_comm &comm)
|
||||
auto sia_provider::create_directory_impl(const std::string &api_path,
|
||||
api_meta_map & /* meta */)
|
||||
-> api_error {
|
||||
constexpr const auto *function_name = static_cast<const char *>(__FUNCTION__);
|
||||
|
||||
curl::requests::http_put_file put_file{};
|
||||
put_file.allow_timeout = true;
|
||||
put_file.path = "/api/worker/objects" + api_path + "/";
|
||||
@@ -49,14 +50,14 @@ auto sia_provider::create_directory_impl(const std::string &api_path,
|
||||
long response_code{};
|
||||
stop_type stop_requested{};
|
||||
if (not get_comm().make_request(put_file, response_code, stop_requested)) {
|
||||
utils::error::raise_api_path_error(__FUNCTION__, api_path,
|
||||
utils::error::raise_api_path_error(function_name, api_path,
|
||||
api_error::comm_error,
|
||||
"failed to create directory");
|
||||
return api_error::comm_error;
|
||||
}
|
||||
|
||||
if (response_code != http_error_codes::ok) {
|
||||
utils::error::raise_api_path_error(__FUNCTION__, api_path, response_code,
|
||||
utils::error::raise_api_path_error(function_name, api_path, response_code,
|
||||
"failed to create directory");
|
||||
return api_error::comm_error;
|
||||
}
|
||||
@@ -66,6 +67,8 @@ auto sia_provider::create_directory_impl(const std::string &api_path,
|
||||
|
||||
auto sia_provider::get_directory_item_count(const std::string &api_path) const
|
||||
-> std::uint64_t {
|
||||
constexpr const auto *function_name = static_cast<const char *>(__FUNCTION__);
|
||||
|
||||
try {
|
||||
json object_list{};
|
||||
if (not get_object_list(api_path, object_list)) {
|
||||
@@ -84,7 +87,7 @@ auto sia_provider::get_directory_item_count(const std::string &api_path) const
|
||||
}
|
||||
++item_count;
|
||||
} catch (const std::exception &e) {
|
||||
utils::error::raise_api_path_error(__FUNCTION__, api_path, e,
|
||||
utils::error::raise_api_path_error(function_name, api_path, e,
|
||||
"failed to process entry|" +
|
||||
entry.dump());
|
||||
}
|
||||
@@ -93,7 +96,7 @@ auto sia_provider::get_directory_item_count(const std::string &api_path) const
|
||||
|
||||
return item_count;
|
||||
} catch (const std::exception &e) {
|
||||
utils::error::raise_api_path_error(__FUNCTION__, api_path, e,
|
||||
utils::error::raise_api_path_error(function_name, api_path, e,
|
||||
"failed to get directory item count");
|
||||
}
|
||||
|
||||
@@ -103,6 +106,8 @@ auto sia_provider::get_directory_item_count(const std::string &api_path) const
|
||||
auto sia_provider::get_directory_items_impl(const std::string &api_path,
|
||||
directory_item_list &list) const
|
||||
-> api_error {
|
||||
constexpr const auto *function_name = static_cast<const char *>(__FUNCTION__);
|
||||
|
||||
json object_list{};
|
||||
if (not get_object_list(api_path, object_list)) {
|
||||
return api_error::comm_error;
|
||||
@@ -129,7 +134,7 @@ auto sia_provider::get_directory_items_impl(const std::string &api_path,
|
||||
get_api_item_added()(directory, file);
|
||||
auto res = get_item_meta(entry_api_path, meta);
|
||||
if (res != api_error::success) {
|
||||
utils::error::raise_error(__FUNCTION__, res,
|
||||
utils::error::raise_error(function_name, res,
|
||||
"failed to get item meta");
|
||||
continue;
|
||||
}
|
||||
@@ -148,7 +153,7 @@ auto sia_provider::get_directory_items_impl(const std::string &api_path,
|
||||
dir_item.size = file.file_size;
|
||||
list.emplace_back(std::move(dir_item));
|
||||
} catch (const std::exception &e) {
|
||||
utils::error::raise_api_path_error(__FUNCTION__, api_path, e,
|
||||
utils::error::raise_api_path_error(function_name, api_path, e,
|
||||
"failed to process entry|" +
|
||||
entry.dump());
|
||||
}
|
||||
@@ -186,6 +191,8 @@ auto sia_provider::get_file(const std::string &api_path, api_file &file) const
|
||||
}
|
||||
|
||||
auto sia_provider::get_file_list(api_file_list &list) const -> api_error {
|
||||
constexpr const auto *function_name = static_cast<const char *>(__FUNCTION__);
|
||||
|
||||
using dir_func = std::function<api_error(std::string api_path)>;
|
||||
const dir_func get_files_in_dir = [&](std::string api_path) -> api_error {
|
||||
try {
|
||||
@@ -236,7 +243,7 @@ auto sia_provider::get_file_list(api_file_list &list) const -> api_error {
|
||||
|
||||
return api_error::success;
|
||||
} catch (const std::exception &e) {
|
||||
utils::error::raise_error(__FUNCTION__, e,
|
||||
utils::error::raise_error(function_name, e,
|
||||
"failed to process directory|" + api_path);
|
||||
}
|
||||
|
||||
@@ -248,6 +255,8 @@ auto sia_provider::get_file_list(api_file_list &list) const -> api_error {
|
||||
|
||||
auto sia_provider::get_object_info(const std::string &api_path,
|
||||
json &object_info) const -> api_error {
|
||||
constexpr const auto *function_name = static_cast<const char *>(__FUNCTION__);
|
||||
|
||||
try {
|
||||
curl::requests::http_get get{};
|
||||
get.allow_timeout = true;
|
||||
@@ -271,14 +280,14 @@ auto sia_provider::get_object_info(const std::string &api_path,
|
||||
}
|
||||
|
||||
if (response_code != http_error_codes::ok) {
|
||||
utils::error::raise_api_path_error(__FUNCTION__, api_path, response_code,
|
||||
utils::error::raise_api_path_error(function_name, api_path, response_code,
|
||||
"failed to get object info");
|
||||
return api_error::comm_error;
|
||||
}
|
||||
|
||||
return api_error::success;
|
||||
} catch (const std::exception &e) {
|
||||
utils::error::raise_api_path_error(__FUNCTION__, api_path, e,
|
||||
utils::error::raise_api_path_error(function_name, api_path, e,
|
||||
"failed to get object info");
|
||||
}
|
||||
|
||||
@@ -287,6 +296,8 @@ auto sia_provider::get_object_info(const std::string &api_path,
|
||||
|
||||
auto sia_provider::get_object_list(const std::string &api_path,
|
||||
nlohmann::json &object_list) const -> bool {
|
||||
constexpr const auto *function_name = static_cast<const char *>(__FUNCTION__);
|
||||
|
||||
curl::requests::http_get get{};
|
||||
get.allow_timeout = true;
|
||||
get.path = "/api/bus/objects" + api_path + "/";
|
||||
@@ -301,14 +312,14 @@ auto sia_provider::get_object_list(const std::string &api_path,
|
||||
long response_code{};
|
||||
stop_type stop_requested{};
|
||||
if (not get_comm().make_request(get, response_code, stop_requested)) {
|
||||
utils::error::raise_api_path_error(__FUNCTION__, api_path,
|
||||
utils::error::raise_api_path_error(function_name, api_path,
|
||||
api_error::comm_error,
|
||||
"failed to get object list");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (response_code != http_error_codes::ok) {
|
||||
utils::error::raise_api_path_error(__FUNCTION__, api_path, response_code,
|
||||
utils::error::raise_api_path_error(function_name, api_path, response_code,
|
||||
"failed to get object list");
|
||||
return false;
|
||||
}
|
||||
@@ -317,6 +328,8 @@ auto sia_provider::get_object_list(const std::string &api_path,
|
||||
}
|
||||
|
||||
auto sia_provider::get_total_drive_space() const -> std::uint64_t {
|
||||
constexpr const auto *function_name = static_cast<const char *>(__FUNCTION__);
|
||||
|
||||
try {
|
||||
curl::requests::http_get get{};
|
||||
get.allow_timeout = true;
|
||||
@@ -337,14 +350,14 @@ auto sia_provider::get_total_drive_space() const -> std::uint64_t {
|
||||
}
|
||||
|
||||
if (response_code != http_error_codes::ok) {
|
||||
utils::error::raise_error(__FUNCTION__, response_code,
|
||||
utils::error::raise_error(function_name, response_code,
|
||||
"failed to get total drive space");
|
||||
return 0U;
|
||||
}
|
||||
|
||||
return config_data["contracts"]["storage"].get<std::uint64_t>();
|
||||
} catch (const std::exception &e) {
|
||||
utils::error::raise_error(__FUNCTION__, e,
|
||||
utils::error::raise_error(function_name, e,
|
||||
"failed to get total drive space");
|
||||
}
|
||||
|
||||
@@ -352,6 +365,8 @@ auto sia_provider::get_total_drive_space() const -> std::uint64_t {
|
||||
}
|
||||
|
||||
auto sia_provider::get_used_drive_space_impl() const -> std::uint64_t {
|
||||
constexpr const auto *function_name = static_cast<const char *>(__FUNCTION__);
|
||||
|
||||
curl::requests::http_get get{};
|
||||
get.allow_timeout = true;
|
||||
get.path = "/api/bus/stats/objects";
|
||||
@@ -371,7 +386,7 @@ auto sia_provider::get_used_drive_space_impl() const -> std::uint64_t {
|
||||
}
|
||||
|
||||
if (response_code != http_error_codes::ok) {
|
||||
utils::error::raise_error(__FUNCTION__, response_code,
|
||||
utils::error::raise_error(function_name, response_code,
|
||||
"failed to get used drive space");
|
||||
return 0U;
|
||||
}
|
||||
@@ -381,6 +396,8 @@ auto sia_provider::get_used_drive_space_impl() const -> std::uint64_t {
|
||||
|
||||
auto sia_provider::is_directory(const std::string &api_path, bool &exists) const
|
||||
-> api_error {
|
||||
constexpr const auto *function_name = static_cast<const char *>(__FUNCTION__);
|
||||
|
||||
if (api_path == "/") {
|
||||
exists = true;
|
||||
return api_error::success;
|
||||
@@ -403,7 +420,7 @@ auto sia_provider::is_directory(const std::string &api_path, bool &exists) const
|
||||
}) != object_list.at("entries").end();
|
||||
return api_error::success;
|
||||
} catch (const std::exception &e) {
|
||||
utils::error::raise_api_path_error(__FUNCTION__, api_path, e,
|
||||
utils::error::raise_api_path_error(function_name, api_path, e,
|
||||
"failed to determine path is directory");
|
||||
}
|
||||
|
||||
@@ -412,6 +429,8 @@ auto sia_provider::is_directory(const std::string &api_path, bool &exists) const
|
||||
|
||||
auto sia_provider::is_file(const std::string &api_path, bool &exists) const
|
||||
-> api_error {
|
||||
constexpr const auto *function_name = static_cast<const char *>(__FUNCTION__);
|
||||
|
||||
exists = false;
|
||||
if (api_path == "/") {
|
||||
return api_error::success;
|
||||
@@ -431,7 +450,7 @@ auto sia_provider::is_file(const std::string &api_path, bool &exists) const
|
||||
exists = not file_data.contains("entries");
|
||||
return api_error::success;
|
||||
} catch (const std::exception &e) {
|
||||
utils::error::raise_api_path_error(__FUNCTION__, api_path, e,
|
||||
utils::error::raise_api_path_error(function_name, api_path, e,
|
||||
"failed to determine path is directory");
|
||||
}
|
||||
|
||||
@@ -439,6 +458,8 @@ auto sia_provider::is_file(const std::string &api_path, bool &exists) const
|
||||
}
|
||||
|
||||
auto sia_provider::is_online() const -> bool {
|
||||
constexpr const auto *function_name = static_cast<const char *>(__FUNCTION__);
|
||||
|
||||
try {
|
||||
curl::requests::http_get get{};
|
||||
get.allow_timeout = true;
|
||||
@@ -455,22 +476,22 @@ auto sia_provider::is_online() const -> bool {
|
||||
long response_code{};
|
||||
stop_type stop_requested{};
|
||||
if (not get_comm().make_request(get, response_code, stop_requested)) {
|
||||
utils::error::raise_error(__FUNCTION__, api_error::comm_error,
|
||||
utils::error::raise_error(function_name, api_error::comm_error,
|
||||
"failed to determine if provider is online");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (response_code != http_error_codes::ok) {
|
||||
utils::error::raise_error(__FUNCTION__, response_code,
|
||||
utils::error::raise_error(function_name, response_code,
|
||||
"failed to determine if provider is online");
|
||||
return false;
|
||||
}
|
||||
|
||||
event_system::instance().raise<debug_log>(__FUNCTION__, "",
|
||||
event_system::instance().raise<debug_log>(function_name, "",
|
||||
state_data.dump());
|
||||
return true;
|
||||
} catch (const std::exception &e) {
|
||||
utils::error::raise_error(__FUNCTION__, e,
|
||||
utils::error::raise_error(function_name, e,
|
||||
"failed to determine if provider is online");
|
||||
}
|
||||
|
||||
@@ -481,6 +502,8 @@ auto sia_provider::read_file_bytes(const std::string &api_path,
|
||||
std::size_t size, std::uint64_t offset,
|
||||
data_buffer &buffer,
|
||||
stop_type &stop_requested) -> api_error {
|
||||
constexpr const auto *function_name = static_cast<const char *>(__FUNCTION__);
|
||||
|
||||
curl::requests::http_get get{};
|
||||
get.path = "/api/worker/objects" + api_path;
|
||||
get.range = {{
|
||||
@@ -498,13 +521,13 @@ auto sia_provider::read_file_bytes(const std::string &api_path,
|
||||
const auto notify_retry = [&]() {
|
||||
if (response_code == 0) {
|
||||
utils::error::raise_api_path_error(
|
||||
__FUNCTION__, api_path, api_error::comm_error,
|
||||
function_name, api_path, api_error::comm_error,
|
||||
"read file bytes failed|offset|" + std::to_string(offset) +
|
||||
"|size|" + std::to_string(size) + "|retry|" +
|
||||
std::to_string(i + 1U));
|
||||
} else {
|
||||
utils::error::raise_api_path_error(
|
||||
__FUNCTION__, api_path, response_code,
|
||||
function_name, api_path, response_code,
|
||||
"read file bytes failed|offset|" + std::to_string(offset) +
|
||||
"|size|" + std::to_string(size) + "|retry|" +
|
||||
std::to_string(i + 1U));
|
||||
@@ -531,6 +554,8 @@ auto sia_provider::read_file_bytes(const std::string &api_path,
|
||||
|
||||
auto sia_provider::remove_directory_impl(const std::string &api_path)
|
||||
-> api_error {
|
||||
constexpr const auto *function_name = static_cast<const char *>(__FUNCTION__);
|
||||
|
||||
curl::requests::http_delete del{};
|
||||
del.allow_timeout = true;
|
||||
del.path = "/api/bus/objects" + api_path + "/";
|
||||
@@ -538,14 +563,14 @@ auto sia_provider::remove_directory_impl(const std::string &api_path)
|
||||
long response_code{};
|
||||
stop_type stop_requested{};
|
||||
if (not get_comm().make_request(del, response_code, stop_requested)) {
|
||||
utils::error::raise_api_path_error(__FUNCTION__, api_path,
|
||||
utils::error::raise_api_path_error(function_name, api_path,
|
||||
api_error::comm_error,
|
||||
"failed to remove directory");
|
||||
return api_error::comm_error;
|
||||
}
|
||||
|
||||
if (response_code != http_error_codes::ok) {
|
||||
utils::error::raise_api_path_error(__FUNCTION__, api_path, response_code,
|
||||
utils::error::raise_api_path_error(function_name, api_path, response_code,
|
||||
"failed to remove directory");
|
||||
return api_error::comm_error;
|
||||
}
|
||||
@@ -554,6 +579,8 @@ auto sia_provider::remove_directory_impl(const std::string &api_path)
|
||||
}
|
||||
|
||||
auto sia_provider::remove_file_impl(const std::string &api_path) -> api_error {
|
||||
constexpr const auto *function_name = static_cast<const char *>(__FUNCTION__);
|
||||
|
||||
curl::requests::http_delete del{};
|
||||
del.allow_timeout = true;
|
||||
del.path = "/api/bus/objects" + api_path;
|
||||
@@ -561,14 +588,15 @@ auto sia_provider::remove_file_impl(const std::string &api_path) -> api_error {
|
||||
long response_code{};
|
||||
stop_type stop_requested{};
|
||||
if (not get_comm().make_request(del, response_code, stop_requested)) {
|
||||
utils::error::raise_api_path_error(
|
||||
__FUNCTION__, api_path, api_error::comm_error, "failed to remove file");
|
||||
utils::error::raise_api_path_error(function_name, api_path,
|
||||
api_error::comm_error,
|
||||
"failed to remove file");
|
||||
return api_error::comm_error;
|
||||
}
|
||||
|
||||
if (response_code != http_error_codes::ok &&
|
||||
response_code != http_error_codes::not_found) {
|
||||
utils::error::raise_api_path_error(__FUNCTION__, api_path, response_code,
|
||||
utils::error::raise_api_path_error(function_name, api_path, response_code,
|
||||
"failed to remove file");
|
||||
return api_error::comm_error;
|
||||
}
|
||||
@@ -576,10 +604,36 @@ auto sia_provider::remove_file_impl(const std::string &api_path) -> api_error {
|
||||
return api_error::success;
|
||||
}
|
||||
|
||||
auto sia_provider::rename_file(const std::string & /*from_api_path*/,
|
||||
const std::string & /*to_api_path*/)
|
||||
-> api_error {
|
||||
return api_error::not_implemented;
|
||||
auto sia_provider::rename_file(const std::string &from_api_path,
|
||||
const std::string &to_api_path) -> api_error {
|
||||
constexpr const auto *function_name = static_cast<const char *>(__FUNCTION__);
|
||||
|
||||
curl::requests::http_post post{};
|
||||
post.path = "/api/bus/objects/rename";
|
||||
post.json = nlohmann::json({
|
||||
{"from", from_api_path},
|
||||
{"to", to_api_path},
|
||||
{"mode", "single"},
|
||||
});
|
||||
|
||||
long response_code{};
|
||||
stop_type stop_requested{};
|
||||
if (not get_comm().make_request(post, response_code, stop_requested)) {
|
||||
utils::error::raise_api_path_error(
|
||||
function_name, from_api_path + '|' + to_api_path, api_error::comm_error,
|
||||
"failed to rename file");
|
||||
return api_error::comm_error;
|
||||
}
|
||||
|
||||
if (response_code < http_error_codes::ok ||
|
||||
response_code >= http_error_codes::multiple_choices) {
|
||||
utils::error::raise_api_path_error(
|
||||
function_name, from_api_path + '|' + to_api_path, response_code,
|
||||
"failed to rename file file");
|
||||
return api_error::comm_error;
|
||||
}
|
||||
|
||||
return get_db().rename_item_meta(from_api_path, to_api_path);
|
||||
}
|
||||
|
||||
auto sia_provider::start(api_item_added_callback api_item_added,
|
||||
@@ -597,20 +651,22 @@ void sia_provider::stop() {
|
||||
auto sia_provider::upload_file_impl(const std::string &api_path,
|
||||
const std::string &source_path,
|
||||
stop_type &stop_requested) -> api_error {
|
||||
constexpr const auto *function_name = static_cast<const char *>(__FUNCTION__);
|
||||
|
||||
curl::requests::http_put_file put_file{};
|
||||
put_file.path = "/api/worker/objects" + api_path;
|
||||
put_file.source_path = source_path;
|
||||
|
||||
long response_code{};
|
||||
if (not get_comm().make_request(put_file, response_code, stop_requested)) {
|
||||
utils::error::raise_api_path_error(__FUNCTION__, api_path, source_path,
|
||||
utils::error::raise_api_path_error(function_name, api_path, source_path,
|
||||
api_error::comm_error,
|
||||
"failed to upload file");
|
||||
return api_error::comm_error;
|
||||
}
|
||||
|
||||
if (response_code != http_error_codes::ok) {
|
||||
utils::error::raise_api_path_error(__FUNCTION__, api_path, source_path,
|
||||
utils::error::raise_api_path_error(function_name, api_path, source_path,
|
||||
response_code, "failed to upload file");
|
||||
return api_error::comm_error;
|
||||
}
|
||||
|
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
Copyright <2018-2023> <scott.e.graves@protonmail.com>
|
||||
Copyright <2018-2024> <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
|
||||
|
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
Copyright <2018-2023> <scott.e.graves@protonmail.com>
|
||||
Copyright <2018-2024> <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
|
||||
@@ -89,13 +89,15 @@ void full_server::handle_get_pinned_files(const httplib::Request & /*req*/,
|
||||
|
||||
void full_server::handle_get_pinned_status(const httplib::Request &req,
|
||||
httplib::Response &res) {
|
||||
constexpr const auto *function_name = static_cast<const char *>(__FUNCTION__);
|
||||
|
||||
const auto api_path =
|
||||
utils::path::create_api_path(req.get_param_value("api_path"));
|
||||
|
||||
std::string pinned;
|
||||
const auto result = provider_.get_item_meta(api_path, META_PINNED, pinned);
|
||||
if (result != api_error::success) {
|
||||
utils::error::raise_api_path_error(__FUNCTION__, api_path, result,
|
||||
utils::error::raise_api_path_error(function_name, api_path, result,
|
||||
"failed to get pinned status");
|
||||
res.status = 500;
|
||||
return;
|
||||
@@ -111,13 +113,15 @@ void full_server::handle_get_pinned_status(const httplib::Request &req,
|
||||
|
||||
void full_server::handle_pin_file(const httplib::Request &req,
|
||||
httplib::Response &res) {
|
||||
constexpr const auto *function_name = static_cast<const char *>(__FUNCTION__);
|
||||
|
||||
const auto api_path =
|
||||
utils::path::create_api_path(req.get_param_value("api_path"));
|
||||
|
||||
bool exists{};
|
||||
auto result = provider_.is_file(api_path, exists);
|
||||
if (result != api_error::success) {
|
||||
utils::error::raise_api_path_error(__FUNCTION__, api_path, result,
|
||||
utils::error::raise_api_path_error(function_name, api_path, result,
|
||||
"failed to pin file");
|
||||
res.status = 500;
|
||||
return;
|
||||
@@ -138,13 +142,15 @@ void full_server::handle_pin_file(const httplib::Request &req,
|
||||
|
||||
void full_server::handle_unpin_file(const httplib::Request &req,
|
||||
httplib::Response &res) {
|
||||
constexpr const auto *function_name = static_cast<const char *>(__FUNCTION__);
|
||||
|
||||
const auto api_path =
|
||||
utils::path::create_api_path(req.get_param_value("api_path"));
|
||||
|
||||
bool exists{};
|
||||
auto result = provider_.is_file(api_path, exists);
|
||||
if (result != api_error::success) {
|
||||
utils::error::raise_api_path_error(__FUNCTION__, api_path, result,
|
||||
utils::error::raise_api_path_error(function_name, api_path, result,
|
||||
"failed to unpin file");
|
||||
res.status = 500;
|
||||
return;
|
||||
|
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
Copyright <2018-2023> <scott.e.graves@protonmail.com>
|
||||
Copyright <2018-2024> <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
|
||||
@@ -29,8 +29,10 @@ namespace repertory {
|
||||
server::server(app_config &config) : config_(config) {}
|
||||
|
||||
auto server::check_authorization(const httplib::Request &req) -> bool {
|
||||
constexpr const auto *function_name = static_cast<const char *>(__FUNCTION__);
|
||||
|
||||
if (config_.get_api_auth().empty() || config_.get_api_user().empty()) {
|
||||
utils::error::raise_error(__FUNCTION__,
|
||||
utils::error::raise_error(function_name,
|
||||
"authorization user or password is not set");
|
||||
return false;
|
||||
}
|
||||
@@ -118,7 +120,9 @@ void server::initialize(httplib::Server &inst) {
|
||||
}
|
||||
|
||||
void server::start() {
|
||||
mutex_lock l(start_stop_mutex_);
|
||||
constexpr const auto *function_name = static_cast<const char *>(__FUNCTION__);
|
||||
|
||||
mutex_lock lock(start_stop_mutex_);
|
||||
if (not started_) {
|
||||
event_system::instance().raise<service_started>("server");
|
||||
server_ = std::make_unique<httplib::Server>();
|
||||
@@ -132,11 +136,11 @@ void server::start() {
|
||||
std::rethrow_exception(ep);
|
||||
} catch (std::exception &e) {
|
||||
data["error"] = e.what() ? e.what() : "unknown error";
|
||||
utils::error::raise_error(__FUNCTION__, e,
|
||||
utils::error::raise_error(function_name, e,
|
||||
"failed request: " + req.path);
|
||||
} catch (...) {
|
||||
data["error"] = "unknown error";
|
||||
utils::error::raise_error(__FUNCTION__, "unknown error",
|
||||
utils::error::raise_error(function_name, "unknown error",
|
||||
"failed request: " + req.path);
|
||||
}
|
||||
|
||||
|
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
Copyright <2018-2023> <scott.e.graves@protonmail.com>
|
||||
Copyright <2018-2024> <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
|
||||
|
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
Copyright <2018-2023> <scott.e.graves@protonmail.com>
|
||||
Copyright <2018-2024> <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
|
||||
|
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
Copyright <2018-2023> <scott.e.graves@protonmail.com>
|
||||
Copyright <2018-2024> <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
|
||||
|
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
Copyright <2018-2023> <scott.e.graves@protonmail.com>
|
||||
Copyright <2018-2024> <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
|
||||
@@ -104,8 +104,7 @@ protected:
|
||||
return traits_type::eof();
|
||||
}
|
||||
|
||||
reader_.set_read_position(
|
||||
static_cast<std::uint64_t>(reinterpret_cast<std::uintptr_t>(gptr())));
|
||||
reader_.set_read_position(reinterpret_cast<std::uintptr_t>(gptr()));
|
||||
|
||||
char c{};
|
||||
const auto res = encrypting_reader::reader_function(&c, 1U, 1U, &reader_);
|
||||
@@ -121,8 +120,7 @@ protected:
|
||||
return traits_type::eof();
|
||||
}
|
||||
|
||||
reader_.set_read_position(
|
||||
static_cast<std::uint64_t>(reinterpret_cast<std::uintptr_t>(gptr())));
|
||||
reader_.set_read_position(reinterpret_cast<std::uintptr_t>(gptr()));
|
||||
|
||||
const auto res = encrypting_reader::reader_function(
|
||||
ptr, 1U, static_cast<std::size_t>(count), &reader_);
|
||||
@@ -172,8 +170,7 @@ encrypting_reader::encrypting_reader(
|
||||
: key_(utils::encryption::generate_key(token)),
|
||||
stop_requested_(stop_requested),
|
||||
error_return_(error_return) {
|
||||
const auto res = native_file::create_or_open(
|
||||
source_path, not relative_parent_path.has_value(), source_file_);
|
||||
const auto res = native_file::create_or_open(source_path, true, source_file_);
|
||||
if (res != api_error::success) {
|
||||
throw std::runtime_error("file open failed|src|" + source_path + '|' +
|
||||
api_error_to_string(res));
|
||||
@@ -202,15 +199,15 @@ encrypting_reader::encrypting_reader(
|
||||
std::to_string(utils::get_last_error_code()));
|
||||
}
|
||||
|
||||
const auto total_chunks = static_cast<std::size_t>(utils::divide_with_ceiling(
|
||||
file_size, static_cast<std::uint64_t>(data_chunk_size_)));
|
||||
const auto total_chunks = utils::divide_with_ceiling(
|
||||
file_size, static_cast<std::uint64_t>(data_chunk_size_));
|
||||
total_size_ =
|
||||
file_size + (total_chunks * encrypting_reader::get_header_size());
|
||||
last_data_chunk_ = total_chunks - 1U;
|
||||
last_data_chunk_size_ = static_cast<std::size_t>(
|
||||
(file_size <= data_chunk_size_) ? file_size
|
||||
: (file_size % data_chunk_size_) == 0U ? data_chunk_size_
|
||||
: file_size % data_chunk_size_);
|
||||
last_data_chunk_size_ = (file_size <= data_chunk_size_) ? file_size
|
||||
: (file_size % data_chunk_size_) == 0U
|
||||
? data_chunk_size_
|
||||
: file_size % data_chunk_size_;
|
||||
iv_list_.resize(total_chunks);
|
||||
for (auto &iv : iv_list_) {
|
||||
randombytes_buf(iv.data(), iv.size());
|
||||
@@ -225,8 +222,7 @@ encrypting_reader::encrypting_reader(const std::string &encrypted_file_path,
|
||||
: key_(utils::encryption::generate_key(token)),
|
||||
stop_requested_(stop_requested),
|
||||
error_return_(error_return) {
|
||||
const auto res =
|
||||
native_file::create_or_open(source_path, false, source_file_);
|
||||
const auto res = native_file::create_or_open(source_path, true, source_file_);
|
||||
if (res != api_error::success) {
|
||||
throw std::runtime_error("file open failed|src|" + source_path + '|' +
|
||||
api_error_to_string(res));
|
||||
@@ -242,15 +238,15 @@ encrypting_reader::encrypting_reader(const std::string &encrypted_file_path,
|
||||
std::to_string(utils::get_last_error_code()));
|
||||
}
|
||||
|
||||
const auto total_chunks = static_cast<std::size_t>(utils::divide_with_ceiling(
|
||||
file_size, static_cast<std::uint64_t>(data_chunk_size_)));
|
||||
const auto total_chunks = utils::divide_with_ceiling(
|
||||
file_size, static_cast<std::uint64_t>(data_chunk_size_));
|
||||
total_size_ =
|
||||
file_size + (total_chunks * encrypting_reader::get_header_size());
|
||||
last_data_chunk_ = total_chunks - 1U;
|
||||
last_data_chunk_size_ = static_cast<std::size_t>(
|
||||
(file_size <= data_chunk_size_) ? file_size
|
||||
: (file_size % data_chunk_size_) == 0U ? data_chunk_size_
|
||||
: file_size % data_chunk_size_);
|
||||
last_data_chunk_size_ = (file_size <= data_chunk_size_) ? file_size
|
||||
: (file_size % data_chunk_size_) == 0U
|
||||
? data_chunk_size_
|
||||
: file_size % data_chunk_size_;
|
||||
iv_list_.resize(total_chunks);
|
||||
for (auto &iv : iv_list_) {
|
||||
randombytes_buf(iv.data(), iv.size());
|
||||
@@ -267,8 +263,7 @@ encrypting_reader::encrypting_reader(
|
||||
: key_(utils::encryption::generate_key(token)),
|
||||
stop_requested_(stop_requested),
|
||||
error_return_(error_return) {
|
||||
const auto res =
|
||||
native_file::create_or_open(source_path, false, source_file_);
|
||||
const auto res = native_file::create_or_open(source_path, true, source_file_);
|
||||
if (res != api_error::success) {
|
||||
throw std::runtime_error("file open failed|src|" + source_path + '|' +
|
||||
api_error_to_string(res));
|
||||
@@ -284,15 +279,15 @@ encrypting_reader::encrypting_reader(
|
||||
std::to_string(utils::get_last_error_code()));
|
||||
}
|
||||
|
||||
const auto total_chunks = static_cast<std::size_t>(utils::divide_with_ceiling(
|
||||
file_size, static_cast<std::uint64_t>(data_chunk_size_)));
|
||||
const auto total_chunks = utils::divide_with_ceiling(
|
||||
file_size, static_cast<std::uint64_t>(data_chunk_size_));
|
||||
total_size_ =
|
||||
file_size + (total_chunks * encrypting_reader::get_header_size());
|
||||
last_data_chunk_ = total_chunks - 1U;
|
||||
last_data_chunk_size_ = static_cast<std::size_t>(
|
||||
(file_size <= data_chunk_size_) ? file_size
|
||||
: (file_size % data_chunk_size_) == 0U ? data_chunk_size_
|
||||
: file_size % data_chunk_size_);
|
||||
last_data_chunk_size_ = (file_size <= data_chunk_size_) ? file_size
|
||||
: (file_size % data_chunk_size_) == 0U
|
||||
? data_chunk_size_
|
||||
: file_size % data_chunk_size_;
|
||||
iv_list_ = std::move(iv_list);
|
||||
}
|
||||
|
||||
@@ -332,8 +327,8 @@ auto encrypting_reader::calculate_encrypted_size(const std::string &source_path)
|
||||
std::to_string(utils::get_last_error_code()));
|
||||
}
|
||||
|
||||
const auto total_chunks = static_cast<std::size_t>(utils::divide_with_ceiling(
|
||||
file_size, static_cast<std::uint64_t>(data_chunk_size_)));
|
||||
const auto total_chunks = utils::divide_with_ceiling(
|
||||
file_size, static_cast<std::uint64_t>(data_chunk_size_));
|
||||
return file_size + (total_chunks * encrypting_reader::get_header_size());
|
||||
}
|
||||
|
||||
@@ -345,20 +340,21 @@ auto encrypting_reader::create_iostream() const
|
||||
|
||||
auto encrypting_reader::reader_function(char *buffer, size_t size,
|
||||
size_t nitems) -> size_t {
|
||||
constexpr const auto *function_name = static_cast<const char *>(__FUNCTION__);
|
||||
|
||||
const auto read_size = static_cast<std::size_t>(std::min(
|
||||
static_cast<std::uint64_t>(size * nitems), total_size_ - read_offset_));
|
||||
|
||||
auto chunk = static_cast<std::size_t>(read_offset_ / encrypted_chunk_size_);
|
||||
auto chunk_offset =
|
||||
static_cast<std::size_t>(read_offset_ % encrypted_chunk_size_);
|
||||
std::size_t total_read = 0u;
|
||||
auto chunk = read_offset_ / encrypted_chunk_size_;
|
||||
auto chunk_offset = read_offset_ % encrypted_chunk_size_;
|
||||
std::size_t total_read{};
|
||||
|
||||
auto ret = false;
|
||||
if (read_offset_ < total_size_) {
|
||||
try {
|
||||
ret = true;
|
||||
auto remain = read_size;
|
||||
while (not stop_requested_ && ret && remain) {
|
||||
while (not stop_requested_ && ret && (remain != 0U)) {
|
||||
if (chunk_buffers_.find(chunk) == chunk_buffers_.end()) {
|
||||
auto &chunk_buffer = chunk_buffers_[chunk];
|
||||
data_buffer file_data(chunk == last_data_chunk_
|
||||
@@ -378,8 +374,9 @@ auto encrypting_reader::reader_function(char *buffer, size_t size,
|
||||
}
|
||||
|
||||
auto &chunk_buffer = chunk_buffers_[chunk];
|
||||
const auto to_read =
|
||||
std::min(chunk_buffer.size() - chunk_offset, remain);
|
||||
const auto to_read = std::min(
|
||||
static_cast<std::size_t>(chunk_buffer.size() - chunk_offset),
|
||||
remain);
|
||||
std::memcpy(buffer + total_read, &chunk_buffer[chunk_offset], to_read);
|
||||
total_read += to_read;
|
||||
remain -= to_read;
|
||||
@@ -388,7 +385,7 @@ auto encrypting_reader::reader_function(char *buffer, size_t size,
|
||||
read_offset_ += to_read;
|
||||
}
|
||||
} catch (const std::exception &e) {
|
||||
utils::error::raise_error(__FUNCTION__, e, "exception occurred");
|
||||
utils::error::raise_error(function_name, e, "exception occurred");
|
||||
ret = false;
|
||||
}
|
||||
}
|
||||
|
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
Copyright <2018-2023> <scott.e.graves@protonmail.com>
|
||||
Copyright <2018-2024> <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
|
||||
@@ -72,16 +72,16 @@ auto generate_key(const std::string &encryption_token) -> key_type {
|
||||
throw std::runtime_error("failed to initialize sha256|" +
|
||||
std::to_string(res));
|
||||
}
|
||||
|
||||
if ((res = crypto_hash_sha256_update(
|
||||
&state,
|
||||
reinterpret_cast<const unsigned char *>(encryption_token.c_str()),
|
||||
strnlen(encryption_token.c_str(), encryption_token.size()))) != 0) {
|
||||
res = crypto_hash_sha256_update(
|
||||
&state, reinterpret_cast<const unsigned char *>(encryption_token.c_str()),
|
||||
strnlen(encryption_token.c_str(), encryption_token.size()));
|
||||
if (res != 0) {
|
||||
throw std::runtime_error("failed to update sha256|" + std::to_string(res));
|
||||
}
|
||||
|
||||
key_type ret{};
|
||||
if ((res = crypto_hash_sha256_final(&state, ret.data())) != 0) {
|
||||
res = crypto_hash_sha256_final(&state, ret.data());
|
||||
if (res != 0) {
|
||||
throw std::runtime_error("failed to finalize sha256|" +
|
||||
std::to_string(res));
|
||||
}
|
||||
@@ -89,11 +89,9 @@ auto generate_key(const std::string &encryption_token) -> key_type {
|
||||
return ret;
|
||||
}
|
||||
|
||||
auto read_encrypted_range(
|
||||
const http_range &range, const key_type &key,
|
||||
const std::function<api_error(data_buffer &ct, std::uint64_t start_offset,
|
||||
std::uint64_t end_offset)> &reader,
|
||||
std::uint64_t total_size, data_buffer &data) -> api_error {
|
||||
auto read_encrypted_range(const http_range &range, const key_type &key,
|
||||
reader_func reader, std::uint64_t total_size,
|
||||
data_buffer &data) -> api_error {
|
||||
const auto encrypted_chunk_size =
|
||||
utils::encryption::encrypting_reader::get_encrypted_chunk_size();
|
||||
const auto data_chunk_size =
|
||||
@@ -108,31 +106,33 @@ auto read_encrypted_range(
|
||||
auto source_offset = static_cast<std::size_t>(range.begin % data_chunk_size);
|
||||
|
||||
for (std::size_t chunk = start_chunk; chunk <= end_chunk; chunk++) {
|
||||
data_buffer ct;
|
||||
data_buffer cypher;
|
||||
const auto start_offset = chunk * encrypted_chunk_size;
|
||||
const auto end_offset = std::min(
|
||||
start_offset + (total_size - (chunk * data_chunk_size)) + header_size -
|
||||
1U,
|
||||
static_cast<std::uint64_t>(start_offset + encrypted_chunk_size - 1U));
|
||||
|
||||
const auto result = reader(ct, start_offset, end_offset);
|
||||
const auto result = reader(cypher, start_offset, end_offset);
|
||||
if (result != api_error::success) {
|
||||
return result;
|
||||
}
|
||||
|
||||
data_buffer source_buffer;
|
||||
if (not utils::encryption::decrypt_data(key, ct, source_buffer)) {
|
||||
if (not utils::encryption::decrypt_data(key, cypher, source_buffer)) {
|
||||
return api_error::decryption_error;
|
||||
}
|
||||
ct.clear();
|
||||
cypher.clear();
|
||||
|
||||
const auto data_size = static_cast<std::size_t>(std::min(
|
||||
remain, static_cast<std::uint64_t>(data_chunk_size - source_offset)));
|
||||
std::copy(source_buffer.begin() + source_offset,
|
||||
source_buffer.begin() + source_offset + data_size,
|
||||
std::copy(std::next(source_buffer.begin(),
|
||||
static_cast<std::int64_t>(source_offset)),
|
||||
std::next(source_buffer.begin(),
|
||||
static_cast<std::int64_t>(source_offset + data_size)),
|
||||
std::back_inserter(data));
|
||||
remain -= data_size;
|
||||
source_offset = 0u;
|
||||
source_offset = 0U;
|
||||
}
|
||||
|
||||
return api_error::success;
|
||||
|
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
Copyright <2018-2023> <scott.e.graves@protonmail.com>
|
||||
Copyright <2018-2024> <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
|
||||
@@ -26,147 +26,141 @@
|
||||
#include "types/repertory.hpp"
|
||||
|
||||
namespace repertory::utils::error {
|
||||
void raise_error(std::string_view function, std::string_view msg) {
|
||||
void raise_error(std::string function, std::string_view msg) {
|
||||
event_system::instance().raise<repertory_exception>(
|
||||
static_cast<std::string>(function), static_cast<std::string>(msg));
|
||||
function, static_cast<std::string>(msg));
|
||||
}
|
||||
|
||||
void raise_error(std::string_view function, const api_error &e,
|
||||
void raise_error(std::string function, const api_error &err,
|
||||
std::string_view msg) {
|
||||
event_system::instance().raise<repertory_exception>(
|
||||
static_cast<std::string>(function),
|
||||
static_cast<std::string>(msg) + "|err|" + api_error_to_string(e));
|
||||
function,
|
||||
static_cast<std::string>(msg) + "|err|" + api_error_to_string(err));
|
||||
}
|
||||
|
||||
void raise_error(std::string_view function, const std::exception &e,
|
||||
void raise_error(std::string function, const std::exception &exception,
|
||||
std::string_view msg) {
|
||||
event_system::instance().raise<repertory_exception>(
|
||||
static_cast<std::string>(function),
|
||||
function,
|
||||
static_cast<std::string>(msg) + "|err|" +
|
||||
(e.what() ? e.what() : "unknown error"));
|
||||
(exception.what() == nullptr ? "unknown error" : exception.what()));
|
||||
}
|
||||
|
||||
void raise_error(std::string_view function, const json &e,
|
||||
std::string_view msg) {
|
||||
void raise_error(std::string function, const json &err, std::string_view msg) {
|
||||
event_system::instance().raise<repertory_exception>(
|
||||
static_cast<std::string>(function),
|
||||
static_cast<std::string>(msg) + "|err|" + e.dump(2));
|
||||
function, static_cast<std::string>(msg) + "|err|" + err.dump(2));
|
||||
}
|
||||
|
||||
void raise_error(std::string_view function, std::int64_t e,
|
||||
std::string_view msg) {
|
||||
void raise_error(std::string function, std::int64_t err, std::string_view msg) {
|
||||
event_system::instance().raise<repertory_exception>(
|
||||
static_cast<std::string>(function),
|
||||
static_cast<std::string>(msg) + "|err|" + std::to_string(e));
|
||||
function, static_cast<std::string>(msg) + "|err|" + std::to_string(err));
|
||||
}
|
||||
|
||||
void raise_error(std::string_view function, const api_error &e,
|
||||
void raise_error(std::string function, const api_error &err,
|
||||
std::string_view file_path, std::string_view msg) {
|
||||
event_system::instance().raise<repertory_exception>(
|
||||
static_cast<std::string>(function),
|
||||
function, static_cast<std::string>(msg) + "|sp|" +
|
||||
static_cast<std::string>(file_path) + "|err|" +
|
||||
api_error_to_string(err));
|
||||
}
|
||||
|
||||
void raise_error(std::string function, std::int64_t err,
|
||||
std::string_view file_path, std::string_view msg) {
|
||||
event_system::instance().raise<repertory_exception>(
|
||||
function, static_cast<std::string>(msg) + "|sp|" +
|
||||
static_cast<std::string>(file_path) + "|err|" +
|
||||
std::to_string(err));
|
||||
}
|
||||
|
||||
void raise_error(std::string function, const std::exception &exception,
|
||||
std::string_view file_path, std::string_view msg) {
|
||||
event_system::instance().raise<repertory_exception>(
|
||||
function,
|
||||
static_cast<std::string>(msg) + "|sp|" +
|
||||
static_cast<std::string>(file_path) + "|err|" +
|
||||
api_error_to_string(e));
|
||||
(exception.what() == nullptr ? "unknown error" : exception.what()));
|
||||
}
|
||||
|
||||
void raise_error(std::string_view function, std::int64_t e,
|
||||
std::string_view file_path, std::string_view msg) {
|
||||
void raise_api_path_error(std::string function, std::string_view api_path,
|
||||
const api_error &err, std::string_view msg) {
|
||||
event_system::instance().raise<repertory_exception>(
|
||||
static_cast<std::string>(function),
|
||||
static_cast<std::string>(msg) + "|sp|" +
|
||||
static_cast<std::string>(file_path) + "|err|" + std::to_string(e));
|
||||
function, static_cast<std::string>(msg) + "|ap|" +
|
||||
static_cast<std::string>(api_path) + "|err|" +
|
||||
api_error_to_string(err));
|
||||
}
|
||||
|
||||
void raise_error(std::string_view function, const std::exception &e,
|
||||
std::string_view file_path, std::string_view msg) {
|
||||
void raise_api_path_error(std::string function, std::string_view api_path,
|
||||
std::int64_t err, std::string_view msg) {
|
||||
event_system::instance().raise<repertory_exception>(
|
||||
static_cast<std::string>(function),
|
||||
static_cast<std::string>(msg) + "|sp|" +
|
||||
static_cast<std::string>(file_path) + "|err|" +
|
||||
(e.what() ? e.what() : "unknown error"));
|
||||
function, static_cast<std::string>(msg) + "|ap|" +
|
||||
static_cast<std::string>(api_path) + "|err|" +
|
||||
std::to_string(err));
|
||||
}
|
||||
|
||||
void raise_api_path_error(std::string_view function, std::string_view api_path,
|
||||
const api_error &e, std::string_view msg) {
|
||||
event_system::instance().raise<repertory_exception>(
|
||||
static_cast<std::string>(function),
|
||||
static_cast<std::string>(msg) + "|ap|" +
|
||||
static_cast<std::string>(api_path) + "|err|" +
|
||||
api_error_to_string(e));
|
||||
}
|
||||
|
||||
void raise_api_path_error(std::string_view function, std::string_view api_path,
|
||||
std::int64_t e, std::string_view msg) {
|
||||
event_system::instance().raise<repertory_exception>(
|
||||
static_cast<std::string>(function),
|
||||
static_cast<std::string>(msg) + "|ap|" +
|
||||
static_cast<std::string>(api_path) + "|err|" + std::to_string(e));
|
||||
}
|
||||
|
||||
void raise_api_path_error(std::string_view function, std::string_view api_path,
|
||||
const std::exception &e, std::string_view msg) {
|
||||
event_system::instance().raise<repertory_exception>(
|
||||
static_cast<std::string>(function),
|
||||
static_cast<std::string>(msg) + "|ap|" +
|
||||
static_cast<std::string>(api_path) + "|err|" +
|
||||
(e.what() ? e.what() : "unknown error"));
|
||||
}
|
||||
|
||||
void raise_api_path_error(std::string_view function, std::string_view api_path,
|
||||
std::string_view source_path, const api_error &e,
|
||||
void raise_api_path_error(std::string function, std::string_view api_path,
|
||||
const std::exception &exception,
|
||||
std::string_view msg) {
|
||||
event_system::instance().raise<repertory_exception>(
|
||||
static_cast<std::string>(function),
|
||||
function,
|
||||
static_cast<std::string>(msg) + "|ap|" +
|
||||
static_cast<std::string>(api_path) + "|err|" +
|
||||
(exception.what() == nullptr ? "unknown error" : exception.what()));
|
||||
}
|
||||
|
||||
void raise_api_path_error(std::string function, std::string_view api_path,
|
||||
std::string_view source_path, const api_error &err,
|
||||
std::string_view msg) {
|
||||
event_system::instance().raise<repertory_exception>(
|
||||
function, static_cast<std::string>(msg) + "|ap|" +
|
||||
static_cast<std::string>(api_path) + "|sp|" +
|
||||
static_cast<std::string>(source_path) + "|err|" +
|
||||
api_error_to_string(err));
|
||||
}
|
||||
|
||||
void raise_api_path_error(std::string function, std::string_view api_path,
|
||||
std::string_view source_path, std::int64_t err,
|
||||
std::string_view msg) {
|
||||
event_system::instance().raise<repertory_exception>(
|
||||
function, static_cast<std::string>(msg) + "|ap|" +
|
||||
static_cast<std::string>(api_path) + "|sp|" +
|
||||
static_cast<std::string>(source_path) + "|err|" +
|
||||
std::to_string(err));
|
||||
}
|
||||
|
||||
void raise_api_path_error(std::string function, std::string_view api_path,
|
||||
const json &err, std::string_view msg) {
|
||||
event_system::instance().raise<repertory_exception>(
|
||||
function, static_cast<std::string>(msg) + "|ap|" +
|
||||
static_cast<std::string>(api_path) + "|err|" + err.dump(2));
|
||||
}
|
||||
|
||||
void raise_api_path_error(std::string function, std::string_view api_path,
|
||||
std::string_view source_path,
|
||||
const std::exception &exception,
|
||||
std::string_view msg) {
|
||||
event_system::instance().raise<repertory_exception>(
|
||||
function,
|
||||
static_cast<std::string>(msg) + "|ap|" +
|
||||
static_cast<std::string>(api_path) + "|sp|" +
|
||||
static_cast<std::string>(source_path) + "|err|" +
|
||||
api_error_to_string(e));
|
||||
(exception.what() == nullptr ? "unknown error" : exception.what()));
|
||||
}
|
||||
|
||||
void raise_api_path_error(std::string_view function, std::string_view api_path,
|
||||
std::string_view source_path, std::int64_t e,
|
||||
std::string_view msg) {
|
||||
event_system::instance().raise<repertory_exception>(
|
||||
static_cast<std::string>(function),
|
||||
static_cast<std::string>(msg) + "|ap|" +
|
||||
static_cast<std::string>(api_path) + "|sp|" +
|
||||
static_cast<std::string>(source_path) + "|err|" + std::to_string(e));
|
||||
}
|
||||
|
||||
void raise_api_path_error(std::string_view function, std::string_view api_path,
|
||||
const json &e, std::string_view msg) {
|
||||
event_system::instance().raise<repertory_exception>(
|
||||
static_cast<std::string>(function),
|
||||
static_cast<std::string>(msg) + "|ap|" +
|
||||
static_cast<std::string>(api_path) + "|err|" + e.dump(2));
|
||||
}
|
||||
|
||||
void raise_api_path_error(std::string_view function, std::string_view api_path,
|
||||
std::string_view source_path, const std::exception &e,
|
||||
std::string_view msg) {
|
||||
event_system::instance().raise<repertory_exception>(
|
||||
static_cast<std::string>(function),
|
||||
static_cast<std::string>(msg) + "|ap|" +
|
||||
static_cast<std::string>(api_path) + "|sp|" +
|
||||
static_cast<std::string>(source_path) + "|err|" +
|
||||
(e.what() ? e.what() : "unknown error"));
|
||||
}
|
||||
|
||||
void raise_url_error(std::string_view function, std::string_view url,
|
||||
CURLcode e, std::string_view msg) {
|
||||
event_system::instance().raise<repertory_exception>(
|
||||
static_cast<std::string>(function),
|
||||
static_cast<std::string>(msg) + "|url|" + static_cast<std::string>(url) +
|
||||
"|err|" + curl_easy_strerror(e));
|
||||
}
|
||||
|
||||
void raise_url_error(std::string_view function, std::string_view url,
|
||||
std::string_view source_path, const std::exception &e,
|
||||
void raise_url_error(std::string function, std::string_view url, CURLcode err,
|
||||
std::string_view msg) {
|
||||
event_system::instance().raise<repertory_exception>(
|
||||
static_cast<std::string>(function),
|
||||
function, static_cast<std::string>(msg) + "|url|" +
|
||||
static_cast<std::string>(url) + "|err|" +
|
||||
curl_easy_strerror(err));
|
||||
}
|
||||
|
||||
void raise_url_error(std::string function, std::string_view url,
|
||||
std::string_view source_path,
|
||||
const std::exception &exception, std::string_view msg) {
|
||||
event_system::instance().raise<repertory_exception>(
|
||||
function,
|
||||
static_cast<std::string>(msg) + "|url|" + static_cast<std::string>(url) +
|
||||
"|sp|" + static_cast<std::string>(source_path) + "|err|" +
|
||||
(e.what() ? e.what() : "unknown error"));
|
||||
(exception.what() == nullptr ? "unknown error" : exception.what()));
|
||||
}
|
||||
} // namespace repertory::utils::error
|
||||
|
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
Copyright <2018-2023> <scott.e.graves@protonmail.com>
|
||||
Copyright <2018-2024> <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
|
||||
@@ -30,9 +30,9 @@
|
||||
namespace repertory::utils::file {
|
||||
auto calculate_used_space(std::string path, bool recursive) -> std::uint64_t {
|
||||
path = utils::path::absolute(path);
|
||||
std::uint64_t ret = 0u;
|
||||
std::uint64_t ret{};
|
||||
#ifdef _WIN32
|
||||
WIN32_FIND_DATA fd = {0};
|
||||
WIN32_FIND_DATA fd{};
|
||||
const auto search = utils::path::combine(path, {"*.*"});
|
||||
auto find = ::FindFirstFile(search.c_str(), &fd);
|
||||
if (find != INVALID_HANDLE_VALUE) {
|
||||
@@ -118,7 +118,7 @@ auto copy_directory_recursively(std::string from_path, std::string to_path)
|
||||
auto ret = create_full_directory_path(to_path);
|
||||
if (ret) {
|
||||
#ifdef _WIN32
|
||||
WIN32_FIND_DATA fd = {0};
|
||||
WIN32_FIND_DATA fd{};
|
||||
const auto search = utils::path::combine(from_path, {"*.*"});
|
||||
auto find = ::FindFirstFile(search.c_str(), &fd);
|
||||
if (find != INVALID_HANDLE_VALUE) {
|
||||
@@ -209,7 +209,7 @@ auto delete_directory_recursively(std::string path) -> bool {
|
||||
path = utils::path::absolute(path);
|
||||
#ifdef _WIN32
|
||||
|
||||
WIN32_FIND_DATA fd = {0};
|
||||
WIN32_FIND_DATA fd{};
|
||||
const auto search = utils::path::combine(path, {"*.*"});
|
||||
auto find = ::FindFirstFile(search.c_str(), &fd);
|
||||
if (find != INVALID_HANDLE_VALUE) {
|
||||
@@ -361,7 +361,7 @@ auto get_directory_files(std::string path, bool oldest_first, bool recursive)
|
||||
std::deque<std::string> ret;
|
||||
std::unordered_map<std::string, std::uint64_t> lookup;
|
||||
#ifdef _WIN32
|
||||
WIN32_FIND_DATA fd = {0};
|
||||
WIN32_FIND_DATA fd{};
|
||||
const auto search = utils::path::combine(path, {"*.*"});
|
||||
auto find = ::FindFirstFile(search.c_str(), &fd);
|
||||
if (find != INVALID_HANDLE_VALUE) {
|
||||
@@ -531,15 +531,17 @@ auto is_file(const std::string &path) -> bool {
|
||||
auto is_modified_date_older_than(const std::string &path,
|
||||
const std::chrono::hours &hours) -> bool {
|
||||
auto ret = false;
|
||||
std::uint64_t modified = 0;
|
||||
std::uint64_t modified{};
|
||||
if (get_modified_time(path, modified)) {
|
||||
const auto seconds =
|
||||
std::chrono::duration_cast<std::chrono::seconds>(hours);
|
||||
#ifdef _WIN32
|
||||
return (std::chrono::system_clock::from_time_t(modified) + seconds) <
|
||||
std::chrono::system_clock::now();
|
||||
return (std::chrono::system_clock::from_time_t(
|
||||
static_cast<time_t>(modified)) +
|
||||
seconds) < std::chrono::system_clock::now();
|
||||
#else
|
||||
return (modified + (seconds.count() * NANOS_PER_SECOND)) <
|
||||
return (modified +
|
||||
static_cast<std::uint64_t>(seconds.count() * NANOS_PER_SECOND)) <
|
||||
utils::get_time_now();
|
||||
#endif
|
||||
}
|
||||
@@ -579,6 +581,8 @@ auto read_file_lines(const std::string &path) -> std::vector<std::string> {
|
||||
}
|
||||
|
||||
auto read_json_file(const std::string &path, json &data) -> bool {
|
||||
constexpr const auto *function_name = static_cast<const char *>(__FUNCTION__);
|
||||
|
||||
if (not utils::file::is_file(path)) {
|
||||
return true;
|
||||
}
|
||||
@@ -603,7 +607,7 @@ auto read_json_file(const std::string &path, json &data) -> bool {
|
||||
}
|
||||
}
|
||||
} catch (const std::exception &e) {
|
||||
utils::error::raise_error(__FUNCTION__, e, path,
|
||||
utils::error::raise_error(function_name, e, path,
|
||||
"failed to read json file");
|
||||
}
|
||||
|
||||
|
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
Copyright <2018-2023> <scott.e.graves@protonmail.com>
|
||||
Copyright <2018-2024> <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
|
||||
@@ -35,20 +35,21 @@ native_file::~native_file() {
|
||||
}
|
||||
}
|
||||
|
||||
auto native_file::clone(const native_file_ptr &nf) -> native_file_ptr {
|
||||
auto native_file::clone(const native_file_ptr &ptr) -> native_file_ptr {
|
||||
std::string source_path;
|
||||
|
||||
#ifdef _WIN32
|
||||
source_path.resize(MAX_PATH + 1);
|
||||
::GetFinalPathNameByHandleA(nf->get_handle(), &source_path[0u], MAX_PATH + 1,
|
||||
::GetFinalPathNameByHandleA(ptr->get_handle(), source_path.data(),
|
||||
MAX_PATH + 1,
|
||||
FILE_NAME_NORMALIZED | VOLUME_NAME_DOS);
|
||||
#else
|
||||
source_path.resize(PATH_MAX + 1);
|
||||
#ifdef __APPLE__
|
||||
fcntl(nf->get_handle(), F_GETPATH, &source_path[0u]);
|
||||
fcntl(ptr->get_handle(), F_GETPATH, source_path.data());
|
||||
#else
|
||||
readlink(("/proc/self/fd/" + std::to_string(nf->get_handle())).c_str(),
|
||||
&source_path[0u], source_path.size());
|
||||
readlink(("/proc/self/fd/" + std::to_string(ptr->get_handle())).c_str(),
|
||||
source_path.data(), source_path.size());
|
||||
#endif
|
||||
#endif
|
||||
source_path = source_path.c_str();
|
||||
@@ -63,52 +64,60 @@ auto native_file::clone(const native_file_ptr &nf) -> native_file_ptr {
|
||||
return clone;
|
||||
}
|
||||
|
||||
auto native_file::create_or_open(const std::string &source_path,
|
||||
[[maybe_unused]] bool should_chmod,
|
||||
native_file_ptr &nf) -> api_error {
|
||||
auto native_file::create_or_open(const std::string &source_path, bool read_only,
|
||||
native_file_ptr &ptr) -> api_error {
|
||||
#ifdef _WIN32
|
||||
auto handle = ::CreateFileA(source_path.c_str(), GENERIC_READ | GENERIC_WRITE,
|
||||
FILE_SHARE_READ | FILE_SHARE_WRITE, nullptr,
|
||||
OPEN_ALWAYS, FILE_FLAG_RANDOM_ACCESS, nullptr);
|
||||
auto handle =
|
||||
read_only
|
||||
? ::CreateFileA(source_path.c_str(), GENERIC_READ,
|
||||
FILE_SHARE_READ | FILE_SHARE_WRITE, nullptr,
|
||||
OPEN_ALWAYS, FILE_FLAG_RANDOM_ACCESS, nullptr)
|
||||
: ::CreateFileA(source_path.c_str(), GENERIC_READ | GENERIC_WRITE,
|
||||
FILE_SHARE_READ | FILE_SHARE_WRITE, nullptr,
|
||||
OPEN_ALWAYS, FILE_FLAG_RANDOM_ACCESS, nullptr);
|
||||
#else
|
||||
auto handle = should_chmod ? ::open(source_path.c_str(),
|
||||
O_CREAT | O_RDWR | O_CLOEXEC, 0600u)
|
||||
: ::open(source_path.c_str(), O_RDWR | O_CLOEXEC);
|
||||
if (should_chmod) {
|
||||
chmod(source_path.c_str(), 0600u);
|
||||
auto handle =
|
||||
read_only
|
||||
? ::open(source_path.c_str(), O_CREAT | O_RDONLY | O_CLOEXEC, 0600U)
|
||||
: ::open(source_path.c_str(), O_CREAT | O_RDWR | O_CLOEXEC, 0600U);
|
||||
if (not read_only) {
|
||||
chmod(source_path.c_str(), 0600U);
|
||||
}
|
||||
#endif
|
||||
nf = native_file::attach(handle);
|
||||
ptr = native_file::attach(handle);
|
||||
return ((handle == REPERTORY_INVALID_HANDLE) ? api_error::os_error
|
||||
: api_error::success);
|
||||
}
|
||||
|
||||
auto native_file::create_or_open(const std::string &source_path,
|
||||
native_file_ptr &nf) -> api_error {
|
||||
return create_or_open(source_path, true, nf);
|
||||
native_file_ptr &ptr) -> api_error {
|
||||
return create_or_open(source_path, false, ptr);
|
||||
}
|
||||
|
||||
auto native_file::open(const std::string &source_path, native_file_ptr &nf)
|
||||
auto native_file::open(const std::string &source_path, native_file_ptr &ptr)
|
||||
-> api_error {
|
||||
return open(source_path, true, nf);
|
||||
return open(source_path, false, ptr);
|
||||
}
|
||||
|
||||
auto native_file::open(const std::string &source_path,
|
||||
[[maybe_unused]] bool should_chmod, native_file_ptr &nf)
|
||||
-> api_error {
|
||||
auto native_file::open(const std::string &source_path, bool read_only,
|
||||
native_file_ptr &ptr) -> api_error {
|
||||
#ifdef _WIN32
|
||||
auto handle = ::CreateFileA(source_path.c_str(), GENERIC_READ | GENERIC_WRITE,
|
||||
FILE_SHARE_READ | FILE_SHARE_WRITE, nullptr,
|
||||
OPEN_EXISTING, FILE_FLAG_RANDOM_ACCESS, nullptr);
|
||||
auto handle =
|
||||
read_only
|
||||
? ::CreateFileA(source_path.c_str(), GENERIC_READ,
|
||||
FILE_SHARE_READ | FILE_SHARE_WRITE, nullptr,
|
||||
OPEN_EXISTING, FILE_FLAG_RANDOM_ACCESS, nullptr)
|
||||
: ::CreateFileA(source_path.c_str(), GENERIC_READ | GENERIC_WRITE,
|
||||
FILE_SHARE_READ | FILE_SHARE_WRITE, nullptr,
|
||||
OPEN_EXISTING, FILE_FLAG_RANDOM_ACCESS, nullptr);
|
||||
#else
|
||||
auto handle = should_chmod
|
||||
? ::open(source_path.c_str(), O_RDWR | O_CLOEXEC, 0600u)
|
||||
: ::open(source_path.c_str(), O_RDONLY | O_CLOEXEC);
|
||||
if (should_chmod) {
|
||||
chmod(source_path.c_str(), 0600u);
|
||||
auto handle = read_only ? ::open(source_path.c_str(), O_RDONLY | O_CLOEXEC)
|
||||
: ::open(source_path.c_str(), O_RDWR | O_CLOEXEC);
|
||||
if (not read_only) {
|
||||
chmod(source_path.c_str(), 0600U);
|
||||
}
|
||||
#endif
|
||||
nf = native_file::attach(handle);
|
||||
ptr = native_file::attach(handle);
|
||||
return ((handle == REPERTORY_INVALID_HANDLE) ? api_error::os_error
|
||||
: api_error::success);
|
||||
}
|
||||
@@ -116,12 +125,12 @@ auto native_file::open(const std::string &source_path,
|
||||
auto native_file::allocate(std::uint64_t file_size) -> bool {
|
||||
#ifdef _WIN32
|
||||
LARGE_INTEGER li{};
|
||||
li.QuadPart = file_size;
|
||||
li.QuadPart = static_cast<LONGLONG>(file_size);
|
||||
return (::SetFilePointerEx(handle_, li, nullptr, FILE_BEGIN) &&
|
||||
::SetEndOfFile(handle_));
|
||||
#endif
|
||||
#ifdef __linux__
|
||||
return (fallocate(handle_, 0, 0, file_size) >= 0);
|
||||
return (fallocate(handle_, 0, 0, static_cast<off_t>(file_size)) >= 0);
|
||||
#endif
|
||||
#ifdef __APPLE__
|
||||
return (ftruncate(handle_, file_size) >= 0);
|
||||
@@ -139,19 +148,19 @@ void native_file::close() {
|
||||
}
|
||||
}
|
||||
|
||||
auto native_file::copy_from(const native_file_ptr &nf) -> bool {
|
||||
auto ret = false;
|
||||
std::uint64_t file_size = 0u;
|
||||
if ((ret = nf->get_file_size(file_size))) {
|
||||
auto native_file::copy_from(const native_file_ptr &ptr) -> bool {
|
||||
std::uint64_t file_size{};
|
||||
auto ret = ptr->get_file_size(file_size);
|
||||
if (ret) {
|
||||
data_buffer buffer;
|
||||
buffer.resize(65536u * 2u);
|
||||
std::uint64_t offset = 0u;
|
||||
while (ret && (file_size > 0u)) {
|
||||
buffer.resize(65536ULL * 2ULL);
|
||||
std::uint64_t offset{};
|
||||
while (ret && (file_size > 0U)) {
|
||||
std::size_t bytes_read{};
|
||||
if ((ret = nf->read_bytes(&buffer[0u], buffer.size(), offset,
|
||||
bytes_read))) {
|
||||
std::size_t bytes_written = 0u;
|
||||
ret = write_bytes(&buffer[0u], bytes_read, offset, bytes_written);
|
||||
ret = ptr->read_bytes(buffer.data(), buffer.size(), offset, bytes_read);
|
||||
if (ret) {
|
||||
std::size_t bytes_written{};
|
||||
ret = write_bytes(buffer.data(), bytes_read, offset, bytes_written);
|
||||
file_size -= bytes_read;
|
||||
offset += bytes_read;
|
||||
}
|
||||
@@ -164,10 +173,10 @@ auto native_file::copy_from(const native_file_ptr &nf) -> bool {
|
||||
|
||||
auto native_file::copy_from(const std::string &path) -> bool {
|
||||
auto ret = false;
|
||||
native_file_ptr nf;
|
||||
if (native_file::create_or_open(path, nf) == api_error ::success) {
|
||||
ret = copy_from(nf);
|
||||
nf->close();
|
||||
native_file_ptr ptr;
|
||||
if (native_file::create_or_open(path, ptr) == api_error ::success) {
|
||||
ret = copy_from(ptr);
|
||||
ptr->close();
|
||||
}
|
||||
|
||||
return ret;
|
||||
@@ -191,14 +200,15 @@ auto native_file::get_file_size(std::uint64_t &file_size) -> bool {
|
||||
}
|
||||
#else
|
||||
#if __APPLE__
|
||||
struct stat st {};
|
||||
if (fstat(handle_, &st) >= 0) {
|
||||
struct stat unix_st {};
|
||||
if (fstat(handle_, &unix_st) >= 0) {
|
||||
#else
|
||||
struct stat64 st {};
|
||||
if (fstat64(handle_, &st) >= 0) {
|
||||
struct stat64 unix_st {};
|
||||
if (fstat64(handle_, &unix_st) >= 0) {
|
||||
#endif
|
||||
if ((ret = (st.st_size >= 0))) {
|
||||
file_size = static_cast<uint64_t>(st.st_size);
|
||||
ret = (unix_st.st_size >= 0);
|
||||
if (ret) {
|
||||
file_size = static_cast<uint64_t>(unix_st.st_size);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
@@ -214,7 +224,7 @@ auto native_file::read_bytes(char *buffer, std::size_t read_size,
|
||||
auto ret = false;
|
||||
bytes_read = 0u;
|
||||
LARGE_INTEGER li{};
|
||||
li.QuadPart = read_offset;
|
||||
li.QuadPart = static_cast<LONGLONG>(read_offset);
|
||||
if ((ret = !!::SetFilePointerEx(handle_, li, nullptr, FILE_BEGIN))) {
|
||||
DWORD current_read = 0u;
|
||||
do {
|
||||
@@ -236,11 +246,11 @@ auto native_file::read_bytes(char *buffer, std::size_t read_size,
|
||||
auto native_file::read_bytes(char *buffer, std::size_t read_size,
|
||||
std::uint64_t read_offset, std::size_t &bytes_read)
|
||||
-> bool {
|
||||
bytes_read = 0u;
|
||||
bytes_read = 0U;
|
||||
ssize_t result = 0;
|
||||
do {
|
||||
result = pread64(handle_, &buffer[bytes_read], read_size - bytes_read,
|
||||
read_offset + bytes_read);
|
||||
static_cast<off_t>(read_offset + bytes_read));
|
||||
if (result > 0) {
|
||||
bytes_read += static_cast<size_t>(result);
|
||||
}
|
||||
@@ -253,11 +263,11 @@ auto native_file::truncate(std::uint64_t file_size) -> bool {
|
||||
#ifdef _WIN32
|
||||
recur_mutex_lock l(read_write_mutex_);
|
||||
LARGE_INTEGER li{};
|
||||
li.QuadPart = file_size;
|
||||
li.QuadPart = static_cast<LONGLONG>(file_size);
|
||||
return (::SetFilePointerEx(handle_, li, nullptr, FILE_BEGIN) &&
|
||||
::SetEndOfFile(handle_));
|
||||
#else
|
||||
return (ftruncate(handle_, file_size) >= 0);
|
||||
return (ftruncate(handle_, static_cast<off_t>(file_size)) >= 0);
|
||||
#endif
|
||||
}
|
||||
|
||||
@@ -271,7 +281,7 @@ auto native_file::write_bytes(const char *buffer, std::size_t write_size,
|
||||
auto ret = true;
|
||||
|
||||
LARGE_INTEGER li{};
|
||||
li.QuadPart = write_offset;
|
||||
li.QuadPart = static_cast<LONGLONG>(write_offset);
|
||||
if ((ret = !!::SetFilePointerEx(handle_, li, nullptr, FILE_BEGIN))) {
|
||||
do {
|
||||
DWORD current_write = 0u;
|
||||
@@ -288,11 +298,12 @@ auto native_file::write_bytes(const char *buffer, std::size_t write_size,
|
||||
auto native_file::write_bytes(const char *buffer, std::size_t write_size,
|
||||
std::uint64_t write_offset,
|
||||
std::size_t &bytes_written) -> bool {
|
||||
bytes_written = 0;
|
||||
ssize_t result = 0;
|
||||
bytes_written = 0U;
|
||||
ssize_t result{};
|
||||
do {
|
||||
result = pwrite64(handle_, &buffer[bytes_written],
|
||||
write_size - bytes_written, write_offset + bytes_written);
|
||||
result =
|
||||
pwrite64(handle_, &buffer[bytes_written], write_size - bytes_written,
|
||||
static_cast<off_t>(write_offset + bytes_written));
|
||||
if (result > 0) {
|
||||
bytes_written += static_cast<size_t>(result);
|
||||
}
|
||||
|
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
Copyright <2018-2023> <scott.e.graves@protonmail.com>
|
||||
Copyright <2018-2024> <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
|
||||
|
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
Copyright <2018-2023> <scott.e.graves@protonmail.com>
|
||||
Copyright <2018-2024> <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
|
||||
|
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
Copyright <2018-2023> <scott.e.graves@protonmail.com>
|
||||
Copyright <2018-2024> <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
|
||||
|
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
Copyright <2018-2023> <scott.e.graves@protonmail.com>
|
||||
Copyright <2018-2024> <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
|
||||
@@ -30,13 +30,15 @@ namespace repertory::utils::string {
|
||||
return std::equal(val.rbegin(), val.rend(), str.rbegin());
|
||||
}
|
||||
|
||||
auto from_bool(bool val) -> std::string { return std::to_string(val); }
|
||||
auto from_bool(bool val) -> std::string {
|
||||
return std::to_string(static_cast<int>(val));
|
||||
}
|
||||
|
||||
auto from_dynamic_bitset(const boost::dynamic_bitset<> &bitset) -> std::string {
|
||||
std::stringstream ss;
|
||||
boost::archive::text_oarchive archive(ss);
|
||||
std::stringstream stream;
|
||||
boost::archive::text_oarchive archive(stream);
|
||||
archive << bitset;
|
||||
return ss.str();
|
||||
return stream.str();
|
||||
}
|
||||
|
||||
auto from_utf8(const std::string &str) -> std::wstring {
|
||||
@@ -46,27 +48,28 @@ auto from_utf8(const std::string &str) -> std::wstring {
|
||||
.from_bytes(str);
|
||||
}
|
||||
|
||||
/* constexpr c++20 */ auto is_numeric(std::string_view s) -> bool {
|
||||
if ((s.length() > 1u) && (s[0u] == '+' || s[0u] == '-')) {
|
||||
s = s.substr(1u);
|
||||
/* constexpr c++20 */ auto is_numeric(std::string_view str) -> bool {
|
||||
if ((str.length() > 1U) && (str[0U] == '+' || str[0U] == '-')) {
|
||||
str = str.substr(1U);
|
||||
}
|
||||
|
||||
if (s.empty()) {
|
||||
if (str.empty()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
auto has_decimal = false;
|
||||
return std::find_if(
|
||||
s.begin(), s.end(),
|
||||
[&has_decimal](const std::string_view::value_type &c) -> bool {
|
||||
if (has_decimal && c == '.') {
|
||||
return true;
|
||||
}
|
||||
if ((has_decimal = has_decimal || c == '.')) {
|
||||
return false;
|
||||
}
|
||||
return not std::isdigit(c);
|
||||
}) == s.end();
|
||||
return std::find_if(str.begin(), str.end(),
|
||||
[&has_decimal](
|
||||
const std::string_view::value_type &cur_ch) -> bool {
|
||||
if (has_decimal && cur_ch == '.') {
|
||||
return true;
|
||||
}
|
||||
has_decimal = has_decimal || cur_ch == '.';
|
||||
if (has_decimal) {
|
||||
return false;
|
||||
}
|
||||
return std::isdigit(cur_ch) == 0;
|
||||
}) == str.end();
|
||||
}
|
||||
|
||||
auto join(const std::vector<std::string> &arr, const char &delim)
|
||||
@@ -76,15 +79,17 @@ auto join(const std::vector<std::string> &arr, const char &delim)
|
||||
}
|
||||
|
||||
return std::accumulate(
|
||||
std::next(arr.begin()), arr.end(), arr[0u],
|
||||
[&delim](auto s, const auto &v) { return s + delim + v; });
|
||||
std::next(arr.begin()), arr.end(), arr[0U],
|
||||
[&delim](auto str, const auto &cur) { return str + delim + cur; });
|
||||
}
|
||||
|
||||
auto left_trim(std::string &s) -> std::string & { return left_trim(s, ' '); }
|
||||
auto left_trim(std::string &str) -> std::string & {
|
||||
return left_trim(str, ' ');
|
||||
}
|
||||
|
||||
auto left_trim(std::string &s, const char &c) -> std::string & {
|
||||
s.erase(0, s.find_first_not_of(c));
|
||||
return s;
|
||||
auto left_trim(std::string &str, const char &trim_ch) -> std::string & {
|
||||
str.erase(0, str.find_first_not_of(trim_ch));
|
||||
return str;
|
||||
}
|
||||
|
||||
auto replace(std::string &src, const char &character, const char &with)
|
||||
@@ -115,47 +120,49 @@ auto replace_copy(std::string src, const std::string &find,
|
||||
return replace(src, find, with, start_pos);
|
||||
}
|
||||
|
||||
auto right_trim(std::string &s) -> std::string & { return right_trim(s, ' '); }
|
||||
auto right_trim(std::string &str) -> std::string & {
|
||||
return right_trim(str, ' ');
|
||||
}
|
||||
|
||||
auto right_trim(std::string &s, const char &c) -> std::string & {
|
||||
s.erase(s.find_last_not_of(c) + 1);
|
||||
return s;
|
||||
auto right_trim(std::string &str, const char &trim_ch) -> std::string & {
|
||||
str.erase(str.find_last_not_of(trim_ch) + 1);
|
||||
return str;
|
||||
}
|
||||
|
||||
auto split(const std::string &str, const char &delim, bool should_trim)
|
||||
-> std::vector<std::string> {
|
||||
std::vector<std::string> ret;
|
||||
std::stringstream ss(str);
|
||||
std::stringstream stream(str);
|
||||
std::string item;
|
||||
while (std::getline(ss, item, delim)) {
|
||||
while (std::getline(stream, item, delim)) {
|
||||
ret.push_back(should_trim ? trim(item) : item);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
auto to_bool(std::string val) -> bool {
|
||||
auto b = false;
|
||||
auto ret = false;
|
||||
|
||||
trim(val);
|
||||
if (is_numeric(val)) {
|
||||
if (contains(val, ".")) {
|
||||
b = (to_double(val) != 0.0);
|
||||
ret = (to_double(val) != 0.0);
|
||||
} else {
|
||||
std::istringstream(val) >> b;
|
||||
std::istringstream(val) >> ret;
|
||||
}
|
||||
} else {
|
||||
std::istringstream(to_lower(val)) >> std::boolalpha >> b;
|
||||
std::istringstream(to_lower(val)) >> std::boolalpha >> ret;
|
||||
}
|
||||
|
||||
return b;
|
||||
return ret;
|
||||
}
|
||||
|
||||
auto to_double(const std::string &str) -> double { return std::stod(str); }
|
||||
|
||||
auto to_dynamic_bitset(const std::string &val) -> boost::dynamic_bitset<> {
|
||||
std::stringstream ss(val);
|
||||
std::stringstream stream(val);
|
||||
boost::dynamic_bitset<> bitset;
|
||||
boost::archive::text_iarchive archive(ss);
|
||||
boost::archive::text_iarchive archive(stream);
|
||||
archive >> bitset;
|
||||
return bitset;
|
||||
}
|
||||
@@ -209,15 +216,15 @@ auto trim(std::string &str) -> std::string & {
|
||||
return right_trim(left_trim(str));
|
||||
}
|
||||
|
||||
auto trim(std::string &str, const char &c) -> std::string & {
|
||||
return right_trim(left_trim(str, c), c);
|
||||
auto trim(std::string &str, const char &trim_ch) -> std::string & {
|
||||
return right_trim(left_trim(str, trim_ch), trim_ch);
|
||||
}
|
||||
|
||||
auto trim_copy(std::string str) -> std::string {
|
||||
return right_trim(left_trim(str));
|
||||
}
|
||||
|
||||
auto trim_copy(std::string str, const char &c) -> std::string {
|
||||
return right_trim(left_trim(str, c), c);
|
||||
auto trim_copy(std::string str, const char &trim_ch) -> std::string {
|
||||
return right_trim(left_trim(str, trim_ch), trim_ch);
|
||||
}
|
||||
} // namespace repertory::utils::string
|
||||
|
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
Copyright <2018-2023> <scott.e.graves@protonmail.com>
|
||||
Copyright <2018-2024> <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
|
||||
|
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
Copyright <2018-2023> <scott.e.graves@protonmail.com>
|
||||
Copyright <2018-2024> <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
|
||||
|
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
Copyright <2018-2023> <scott.e.graves@protonmail.com>
|
||||
Copyright <2018-2024> <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
|
||||
@@ -28,13 +28,13 @@
|
||||
|
||||
namespace repertory::utils {
|
||||
#ifndef __APPLE__
|
||||
auto convert_to_uint64(const pthread_t &t) -> std::uint64_t {
|
||||
return static_cast<std::uint64_t>(t);
|
||||
auto convert_to_uint64(const pthread_t &thread) -> std::uint64_t {
|
||||
return static_cast<std::uint64_t>(thread);
|
||||
}
|
||||
#endif
|
||||
|
||||
auto from_api_error(const api_error &e) -> int {
|
||||
switch (e) {
|
||||
auto from_api_error(const api_error &err) -> int {
|
||||
switch (err) {
|
||||
case api_error::access_denied:
|
||||
return -EACCES;
|
||||
case api_error::bad_address:
|
||||
@@ -107,18 +107,16 @@ auto get_thread_id() -> std::uint64_t {
|
||||
}
|
||||
|
||||
auto is_uid_member_of_group(const uid_t &uid, const gid_t &gid) -> bool {
|
||||
static const auto function_name = __FUNCTION__;
|
||||
|
||||
std::vector<gid_t> groups{};
|
||||
use_getpwuid(uid, [&groups](struct passwd *pw) {
|
||||
use_getpwuid(uid, [&groups](struct passwd *pass) {
|
||||
int group_count{};
|
||||
if (getgrouplist(pw->pw_name, pw->pw_gid, nullptr, &group_count) < 0) {
|
||||
if (getgrouplist(pass->pw_name, pass->pw_gid, nullptr, &group_count) < 0) {
|
||||
groups.resize(static_cast<std::size_t>(group_count));
|
||||
#ifdef __APPLE__
|
||||
getgrouplist(pw->pw_name, pw->pw_gid,
|
||||
getgrouplist(pass->pw_name, pass->pw_gid,
|
||||
reinterpret_cast<int *>(groups.data()), &group_count);
|
||||
#else
|
||||
getgrouplist(pw->pw_name, pw->pw_gid, groups.data(), &group_count);
|
||||
getgrouplist(pass->pw_name, pass->pw_gid, groups.data(), &group_count);
|
||||
#endif
|
||||
}
|
||||
});
|
||||
@@ -126,8 +124,8 @@ auto is_uid_member_of_group(const uid_t &uid, const gid_t &gid) -> bool {
|
||||
return collection_includes(groups, gid);
|
||||
}
|
||||
|
||||
auto to_api_error(int e) -> api_error {
|
||||
switch (abs(e)) {
|
||||
auto to_api_error(int err) -> api_error {
|
||||
switch (abs(err)) {
|
||||
case 0:
|
||||
return api_error::success;
|
||||
case EBADF:
|
||||
@@ -196,8 +194,8 @@ auto to_api_error(int e) -> api_error {
|
||||
|
||||
void set_last_error_code(int error_code) { errno = error_code; }
|
||||
|
||||
auto unix_error_to_windows(int e) -> std::int32_t {
|
||||
switch (e) {
|
||||
auto unix_error_to_windows(int err) -> std::int32_t {
|
||||
switch (err) {
|
||||
case 0:
|
||||
return STATUS_SUCCESS;
|
||||
case EACCES:
|
||||
@@ -236,20 +234,23 @@ auto unix_error_to_windows(int e) -> std::int32_t {
|
||||
}
|
||||
}
|
||||
|
||||
auto unix_time_to_windows_time(const remote::file_time &ts) -> UINT64 {
|
||||
return (ts / 100ull) + 116444736000000000ull;
|
||||
auto unix_time_to_windows_time(const remote::file_time &file_time) -> UINT64 {
|
||||
return (file_time / 100ULL) + 116444736000000000ULL;
|
||||
}
|
||||
|
||||
void use_getpwuid(uid_t uid, std::function<void(struct passwd *pw)> fn) {
|
||||
void use_getpwuid(uid_t uid,
|
||||
std::function<void(struct passwd *pass)> callback) {
|
||||
constexpr const auto *function_name = static_cast<const char *>(__FUNCTION__);
|
||||
|
||||
static std::mutex mtx{};
|
||||
mutex_lock lock{mtx};
|
||||
auto *pw = getpwuid(uid);
|
||||
if (not pw) {
|
||||
utils::error::raise_error(__FUNCTION__, "'getpwuid' returned nullptr");
|
||||
auto *temp_pw = getpwuid(uid);
|
||||
if (temp_pw == nullptr) {
|
||||
utils::error::raise_error(function_name, "'getpwuid' returned nullptr");
|
||||
return;
|
||||
}
|
||||
|
||||
fn(pw);
|
||||
callback(temp_pw);
|
||||
}
|
||||
|
||||
void windows_create_to_unix(const UINT32 &create_options,
|
||||
@@ -257,20 +258,20 @@ void windows_create_to_unix(const UINT32 &create_options,
|
||||
remote::file_mode &mode) {
|
||||
mode = S_IRUSR | S_IWUSR;
|
||||
flags = O_CREAT | O_RDWR;
|
||||
if (create_options & FILE_DIRECTORY_FILE) {
|
||||
if ((create_options & FILE_DIRECTORY_FILE) != 0U) {
|
||||
mode |= S_IXUSR;
|
||||
flags = O_DIRECTORY;
|
||||
}
|
||||
|
||||
if ((granted_access & GENERIC_EXECUTE) ||
|
||||
(granted_access & FILE_GENERIC_EXECUTE) ||
|
||||
(granted_access & FILE_EXECUTE)) {
|
||||
if (((granted_access & GENERIC_EXECUTE) != 0U) ||
|
||||
((granted_access & FILE_GENERIC_EXECUTE) != 0U) ||
|
||||
((granted_access & FILE_EXECUTE) != 0U)) {
|
||||
mode |= (S_IXUSR);
|
||||
}
|
||||
}
|
||||
|
||||
auto windows_time_to_unix_time(std::uint64_t t) -> remote::file_time {
|
||||
return (t - 116444736000000000ull) * 100ull;
|
||||
auto windows_time_to_unix_time(std::uint64_t win_time) -> remote::file_time {
|
||||
return (win_time - 116444736000000000ULL) * 100ULL;
|
||||
}
|
||||
} // namespace repertory::utils
|
||||
|
||||
|
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
Copyright <2018-2023> <scott.e.graves@protonmail.com>
|
||||
Copyright <2018-2024> <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
|
||||
@@ -30,7 +30,6 @@
|
||||
#include "utils/native_file.hpp"
|
||||
#include "utils/path_utils.hpp"
|
||||
#include "utils/string_utils.hpp"
|
||||
#include <limits>
|
||||
|
||||
namespace repertory::utils {
|
||||
void calculate_allocation_size(bool directory, std::uint64_t file_size,
|
||||
@@ -171,16 +170,16 @@ auto download_type_to_string(const download_type &type) -> std::string {
|
||||
// https://www.frenk.com/2009/12/convert-filetime-to-unix-timestamp/
|
||||
auto filetime_to_unix_time(const FILETIME &ft) -> remote::file_time {
|
||||
LARGE_INTEGER date{};
|
||||
date.HighPart = ft.dwHighDateTime;
|
||||
date.HighPart = static_cast<LONG>(ft.dwHighDateTime);
|
||||
date.LowPart = ft.dwLowDateTime;
|
||||
date.QuadPart -= 116444736000000000ULL;
|
||||
date.QuadPart -= 116444736000000000LL;
|
||||
|
||||
return date.QuadPart * 100ULL;
|
||||
return static_cast<remote::file_time>(date.QuadPart) * 100ULL;
|
||||
}
|
||||
|
||||
void unix_time_to_filetime(const remote::file_time &ts, FILETIME &ft) {
|
||||
const auto win_time = (ts / 100ULL) + 116444736000000000ULL;
|
||||
ft.dwHighDateTime = win_time >> 32U;
|
||||
ft.dwHighDateTime = static_cast<DWORD>(win_time >> 32U);
|
||||
ft.dwLowDateTime = win_time & 0xFFFFFFFF;
|
||||
}
|
||||
#endif
|
||||
@@ -217,7 +216,8 @@ auto get_file_time_now() -> std::uint64_t {
|
||||
::GetSystemTime(&st);
|
||||
FILETIME ft{};
|
||||
::SystemTimeToFileTime(&st, &ft);
|
||||
return static_cast<std::uint64_t>(((LARGE_INTEGER *)&ft)->QuadPart);
|
||||
return static_cast<std::uint64_t>(
|
||||
(reinterpret_cast<LARGE_INTEGER *>(&ft))->QuadPart);
|
||||
#else
|
||||
return get_time_now();
|
||||
#endif
|
||||
@@ -231,13 +231,7 @@ void get_local_time_now(struct tm &local_time) {
|
||||
#ifdef _WIN32
|
||||
localtime_s(&local_time, &now);
|
||||
#else
|
||||
static std::mutex mtx{};
|
||||
mutex_lock lock{mtx};
|
||||
|
||||
const auto *tmp = std::localtime(&now);
|
||||
if (tmp != nullptr) {
|
||||
memcpy(&local_time, tmp, sizeof(local_time));
|
||||
}
|
||||
localtime_r(&now, &local_time);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
Copyright <2018-2023> <scott.e.graves@protonmail.com>
|
||||
Copyright <2018-2024> <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
|
||||
@@ -28,7 +28,7 @@
|
||||
#include "utils/string_utils.hpp"
|
||||
|
||||
#ifndef STATUS_DEVICE_INSUFFICIENT_RESOURCES
|
||||
#define STATUS_DEVICE_INSUFFICIENT_RESOURCES ((NTSTATUS)0xC0000468L)
|
||||
#define STATUS_DEVICE_INSUFFICIENT_RESOURCES static_cast<NTSTATUS>(0xC0000468L)
|
||||
#endif
|
||||
|
||||
namespace repertory::utils {
|
||||
@@ -95,9 +95,9 @@ auto get_local_app_data_directory() -> const std::string & {
|
||||
PWSTR local_app_data{};
|
||||
if (SUCCEEDED(::SHGetKnownFolderPath(FOLDERID_LocalAppData, 0, nullptr,
|
||||
&local_app_data))) {
|
||||
auto app_data = utils::string::to_utf8(local_app_data);
|
||||
auto ret = utils::string::to_utf8(local_app_data);
|
||||
::CoTaskMemFree(local_app_data);
|
||||
return app_data;
|
||||
return ret;
|
||||
}
|
||||
|
||||
throw startup_exception("unable to detect local application data folder");
|
||||
@@ -164,14 +164,14 @@ auto run_process_elevated(std::vector<const char *> args) -> int {
|
||||
sei.nShow = SW_NORMAL;
|
||||
if (::ShellExecuteEx(&sei)) {
|
||||
::WaitForSingleObject(sei.hProcess, INFINITE);
|
||||
DWORD exit_code = 0u;
|
||||
DWORD exit_code{};
|
||||
::GetExitCodeProcess(sei.hProcess, &exit_code);
|
||||
::CloseHandle(sei.hProcess);
|
||||
return exit_code;
|
||||
return static_cast<int>(exit_code);
|
||||
}
|
||||
}
|
||||
|
||||
return ::GetLastError();
|
||||
return static_cast<int>(::GetLastError());
|
||||
}
|
||||
|
||||
void set_last_error_code(DWORD error_code) { ::SetLastError(error_code); }
|
||||
@@ -234,7 +234,7 @@ auto unix_open_flags_to_flags_and_perms(const remote::file_mode & /*mode*/,
|
||||
}
|
||||
|
||||
auto time64_to_unix_time(const __time64_t &t) -> remote::file_time {
|
||||
return t * NANOS_PER_SECOND;
|
||||
return static_cast<remote::file_time>(t * NANOS_PER_SECOND);
|
||||
}
|
||||
} // namespace repertory::utils
|
||||
|
||||
|
Reference in New Issue
Block a user