initial commit
Some checks failed
BlockStorage/repertory_osx/pipeline/head There was a failure building this commit
BlockStorage/repertory_windows/pipeline/head This commit looks good
BlockStorage/repertory_linux_builds/pipeline/head This commit looks good

This commit is contained in:
2022-03-05 00:30:50 -06:00
commit 3ff46723b8
626 changed files with 178600 additions and 0 deletions

382
include/app_config.hpp Normal file
View File

@ -0,0 +1,382 @@
/*
Copyright <2018-2022> <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_APP_CONFIG_HPP_
#define INCLUDE_APP_CONFIG_HPP_
#include "common.hpp"
#include "events/events.hpp"
#include "events/event_system.hpp"
#include "types/repertory.hpp"
#include "types/skynet.hpp"
namespace repertory {
class app_config final {
public:
static std::string default_agent_name(const provider_type &pt);
static std::uint16_t default_api_port(const provider_type &pt);
static std::string default_data_directory(const provider_type &pt);
static std::uint16_t default_rpc_port(const provider_type &pt);
static std::string get_provider_api_password(const provider_type &pt);
static std::string get_provider_display_name(const provider_type &pt);
static std::string get_provider_minimum_version(const provider_type &pt);
static std::string get_provider_name(const provider_type &pt);
static std::string get_provider_path_name(const provider_type &pt);
public:
explicit app_config(const provider_type &pt, const std::string &data_directory = "");
~app_config() { save(); }
private:
const provider_type pt_;
std::string api_auth_;
std::uint16_t api_port_;
std::string api_user_;
bool config_changed_;
const std::string data_directory_;
std::uint8_t download_timeout_secs_;
bool enable_chunk_downloader_timeout_;
bool enable_comm_duration_events_;
bool enable_drive_events_;
bool enable_max_cache_size_;
#ifdef _WIN32
bool enable_mount_manager_;
#endif
bool enable_remote_mount_;
event_level event_level_;
std::uint32_t eviction_delay_mins_;
bool eviction_uses_accessed_time_;
std::uint8_t high_freq_interval_secs_;
bool is_remote_mount_;
std::uint32_t low_freq_interval_secs_;
std::uint64_t max_cache_size_bytes_;
std::uint8_t max_upload_count_;
std::uint8_t min_download_timeout_secs_;
double minimum_redundancy_;
std::uint16_t online_check_retry_secs_;
std::uint16_t orphaned_file_retention_days_;
std::string preferred_download_type_;
std::uint8_t read_ahead_count_;
std::uint8_t remote_client_pool_size_;
std::string remote_host_name_or_ip_;
std::uint8_t remote_max_connections_;
std::uint16_t remote_port_;
std::uint16_t remote_receive_timeout_secs_;
std::uint16_t remote_send_timeout_secs_;
std::string remote_token_;
std::uint16_t retry_read_count_;
std::uint16_t ring_buffer_file_size_;
api_currency storage_byte_month_;
std::uint64_t version_ = REPERTORY_CONFIG_VERSION;
std::string cache_directory_;
host_config hc_;
s3_config s3_config_;
skynet_config skynet_config_;
std::string log_directory_;
std::recursive_mutex read_write_mutex_;
std::recursive_mutex remote_mount_mutex_;
private:
bool load();
template <typename dest>
bool get_value(const json &json_document, const std::string &name, dest &dst,
bool &success_flag) {
auto ret = false;
try {
if (json_document.find(name) != json_document.end()) {
dst = json_document[name].get<dest>();
ret = true;
} else {
success_flag = false;
}
} catch (const json::exception &ex) {
event_system::instance().raise<repertory_exception>(__FUNCTION__, ex.what());
success_flag = false;
ret = false;
}
return ret;
}
template <typename dest, typename source> bool set_value(dest &dst, const source &src) {
auto ret = false;
recur_mutex_lock l(read_write_mutex_);
if (dst != src) {
dst = src;
config_changed_ = true;
save();
ret = true;
if (reinterpret_cast<void *>(&dst) == &skynet_config_.portal_list) {
event_system::instance().raise<skynet_portal_list_changed>();
}
}
return ret;
}
public:
std::string get_api_auth() const { return api_auth_; }
std::uint16_t get_api_port() const { return api_port_; }
std::string get_api_user() const { return api_user_; }
std::string get_cache_directory() const { return cache_directory_; }
std::uint8_t get_chunk_downloader_timeout_secs() const {
return std::max(min_download_timeout_secs_, download_timeout_secs_);
}
std::string get_config_file_path() const;
std::string get_data_directory() const { return data_directory_; }
bool get_enable_chunk_download_timeout() const { return enable_chunk_downloader_timeout_; }
bool get_enable_comm_duration_events() const { return enable_comm_duration_events_; }
bool get_enable_drive_events() const { return enable_drive_events_; }
#ifdef _WIN32
bool get_enable_mount_manager() const { return enable_mount_manager_; }
#endif
bool get_enable_max_cache_size() const { return enable_max_cache_size_; }
bool get_enable_remote_mount() const { return enable_remote_mount_; }
event_level get_event_level() const { return event_level_; }
std::uint32_t get_eviction_delay_mins() const { return eviction_delay_mins_; }
bool get_eviction_uses_accessed_time() const { return eviction_uses_accessed_time_; }
std::uint8_t get_high_frequency_interval_secs() const {
return std::max((std::uint8_t)1, high_freq_interval_secs_);
}
host_config get_host_config() const { return hc_; }
bool get_is_remote_mount() const { return is_remote_mount_; }
json get_json() const;
std::string get_log_directory() const { return log_directory_; }
std::uint32_t get_low_frequency_interval_secs() const {
return std::max((std::uint32_t)1, low_freq_interval_secs_);
}
std::uint64_t get_max_cache_size_bytes() const;
std::uint8_t get_max_upload_count() const {
return std::max(std::uint8_t(1u), max_upload_count_);
}
double get_minimum_redundancy() const { return std::max(1.5, minimum_redundancy_); }
std::uint16_t get_online_check_retry_secs() const {
return std::max(std::uint16_t(15), online_check_retry_secs_);
}
std::uint16_t get_orphaned_file_retention_days() const {
return std::min((std::uint16_t)31, std::max((std::uint16_t)1, orphaned_file_retention_days_));
}
download_type get_preferred_download_type() const {
return utils::download_type_from_string(preferred_download_type_, download_type::fallback);
}
provider_type get_provider_type() const { return pt_; }
std::uint8_t get_read_ahead_count() const { return std::max((std::uint8_t)1, read_ahead_count_); }
std::uint8_t get_remote_client_pool_size() const {
return std::max((std::uint8_t)5u, remote_client_pool_size_);
}
std::string get_remote_host_name_or_ip() const { return remote_host_name_or_ip_; }
std::uint8_t get_remote_max_connections() const {
return std::max((std::uint8_t)1, remote_max_connections_);
}
std::uint16_t get_remote_port() const { return remote_port_; }
std::uint16_t get_remote_receive_timeout_secs() const { return remote_receive_timeout_secs_; }
std::uint16_t get_remote_send_timeout_secs() const { return remote_send_timeout_secs_; }
std::string get_remote_token() const { return remote_token_; }
std::uint16_t get_retry_read_count() const {
return std::max(std::uint16_t(2), retry_read_count_);
}
std::uint16_t get_ring_buffer_file_size() const {
return std::max((std::uint16_t)64, std::min((std::uint16_t)1024, ring_buffer_file_size_));
}
s3_config get_s3_config() const { return s3_config_; }
skynet_config get_skynet_config() const { return skynet_config_; }
api_currency get_storage_byte_month() const { return storage_byte_month_; }
std::string get_value_by_name(const std::string &name);
std::uint64_t get_version() const { return version_; }
void save();
void set_api_auth(const std::string &api_auth) { set_value(api_auth_, api_auth); }
void set_api_port(const std::uint16_t &api_port) { set_value(api_port_, api_port); }
void set_api_user(const std::string &api_user) { set_value(api_user_, api_user); }
void set_chunk_downloader_timeout_secs(const std::uint8_t &chunk_downloader_timeout_secs) {
set_value(download_timeout_secs_, chunk_downloader_timeout_secs);
}
void set_enable_chunk_downloader_timeout(const bool &enable_chunk_downloader_timeout) {
set_value(enable_chunk_downloader_timeout_, enable_chunk_downloader_timeout);
}
void set_enable_comm_duration_events(const bool &enable_comm_duration_events) {
set_value(enable_comm_duration_events_, enable_comm_duration_events);
}
void set_enable_drive_events(const bool &enable_drive_events) {
set_value(enable_drive_events_, enable_drive_events);
}
void set_enable_max_cache_size(const bool &enable_max_cache_size) {
set_value(enable_max_cache_size_, enable_max_cache_size);
}
#ifdef _WIN32
void set_enable_mount_manager(const bool &enable_mount_manager) {
set_value(enable_mount_manager_, enable_mount_manager);
}
#endif
void set_enable_remote_mount(const bool &enable_remote_mount);
void set_event_level(const event_level &level) {
if (set_value(event_level_, level)) {
event_system::instance().raise<event_level_changed>(event_level_to_string(level));
}
}
void set_eviction_delay_mins(const std::uint32_t &eviction_delay_mins) {
set_value(eviction_delay_mins_, eviction_delay_mins);
}
void set_eviction_uses_accessed_time(const bool &eviction_uses_accessed_time) {
set_value(eviction_uses_accessed_time_, eviction_uses_accessed_time);
}
void set_high_frequency_interval_secs(const std::uint8_t &high_frequency_interval_secs) {
set_value(high_freq_interval_secs_, high_frequency_interval_secs);
}
void set_is_remote_mount(const bool &is_remote_mount);
void set_low_frequency_interval_secs(const std::uint32_t &low_frequency_interval_secs) {
set_value(low_freq_interval_secs_, low_frequency_interval_secs);
}
void set_max_cache_size_bytes(const std::uint64_t &max_cache_size_bytes) {
set_value(max_cache_size_bytes_, max_cache_size_bytes);
}
void set_max_upload_count(const std::uint8_t &max_upload_count) {
set_value(max_upload_count_, max_upload_count);
}
void set_minimum_redundancy(const double &minimum_redundancy) {
set_value(minimum_redundancy_, minimum_redundancy);
}
void set_online_check_retry_secs(const std::uint16_t &online_check_retry_secs) {
set_value(online_check_retry_secs_, online_check_retry_secs);
}
void set_orphaned_file_retention_days(const std::uint16_t &orphaned_file_retention_days) {
set_value(orphaned_file_retention_days_, orphaned_file_retention_days);
}
void set_preferred_download_type(const download_type &dt) {
set_value(preferred_download_type_, utils::download_type_to_string(dt));
}
void set_read_ahead_count(const std::uint8_t &read_ahead_count) {
set_value(read_ahead_count_, read_ahead_count);
}
void set_remote_client_pool_size(const std::uint8_t &remote_client_pool_size) {
set_value(remote_client_pool_size_, remote_client_pool_size);
}
void set_ring_buffer_file_size(const std::uint16_t &ring_buffer_file_size) {
set_value(ring_buffer_file_size_, ring_buffer_file_size);
}
void set_remote_host_name_or_ip(const std::string &remote_host_name_or_ip) {
set_value(remote_host_name_or_ip_, remote_host_name_or_ip);
}
void set_remote_max_connections(const std::uint8_t &remote_max_connections) {
set_value(remote_max_connections_, remote_max_connections);
}
void set_remote_port(const std::uint16_t &remote_port) { set_value(remote_port_, remote_port); }
void set_remote_receive_timeout_secs(const std::uint16_t &remote_receive_timeout_secs) {
set_value(remote_receive_timeout_secs_, remote_receive_timeout_secs);
}
void set_remote_send_timeout_secs(const std::uint16_t &remote_send_timeout_secs) {
set_value(remote_send_timeout_secs_, remote_send_timeout_secs);
}
void set_remote_token(const std::string &remote_token) { set_value(remote_token_, remote_token); }
void set_retry_read_count(const std::uint16_t &retry_read_count) {
set_value(retry_read_count_, retry_read_count);
}
void set_storage_byte_month(const api_currency &storage_byte_month);
std::string set_value_by_name(const std::string &name, const std::string &value);
};
} // namespace repertory
#endif // INCLUDE_APP_CONFIG_HPP_

96
include/cli/actions.hpp Normal file
View File

@ -0,0 +1,96 @@
/*
Copyright <2018-2022> <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_CLI_ACTIONS_HPP_
#define INCLUDE_CLI_ACTIONS_HPP_
#include "common.hpp"
#include "cli/check_version.hpp"
#include "cli/display_config.hpp"
#include "cli/drive_information.hpp"
#include "cli/export.hpp"
#include "cli/export_all.hpp"
#include "cli/get.hpp"
#include "cli/get_directory_items.hpp"
#include "cli/get_pinned_files.hpp"
#include "cli/help.hpp"
#include "cli/import.hpp"
#include "cli/import_json.hpp"
#include "cli/mount.hpp"
#include "cli/open_files.hpp"
#include "cli/pin_file.hpp"
#include "cli/pinned_status.hpp"
#include "cli/set.hpp"
#include "cli/status.hpp"
#include "cli/test_skynet_auth.hpp"
#include "cli/unmount.hpp"
#include "cli/unpin_file.hpp"
#include "cli/version.hpp"
#include "utils/cli_utils.hpp"
namespace repertory::cli::actions {
typedef std::function<exit_code(const int &argc, char *argv[], const std::string &data_directory,
const provider_type &pt, const std::string &unique_id,
std::string user, std::string password)>
action;
struct option_hasher {
std::size_t operator()(const utils::cli::option &opt) const {
return std::hash<std::string>()(opt[0u] + '|' + opt[1u]);
}
};
static const std::unordered_map<utils::cli::option, action, option_hasher> option_actions = {
{utils::cli::options::check_version_option, cli::actions::check_version},
{utils::cli::options::display_config_option, cli::actions::display_config},
{utils::cli::options::drive_information_option, cli::actions::drive_information},
{utils::cli::options::export_option, cli::actions::export_action},
{utils::cli::options::export_all_option, cli::actions::export_all},
{utils::cli::options::get_directory_items_option, cli::actions::get_directory_items},
{utils::cli::options::get_option, cli::actions::get},
{utils::cli::options::get_pinned_files_option, cli::actions::get_pinned_files},
{utils::cli::options::import_option, cli::actions::import},
{utils::cli::options::import_json_option, cli::actions::import_json},
{utils::cli::options::open_files_option, cli::actions::open_files},
{utils::cli::options::pin_file_option, cli::actions::pin_file},
{utils::cli::options::pinned_status_option, cli::actions::pinned_status},
{utils::cli::options::set_option, cli::actions::set},
{utils::cli::options::status_option, cli::actions::status},
#if defined(REPERTORY_ENABLE_SKYNET)
{utils::cli::options::test_skynet_auth_option, cli::actions::test_skynet_auth},
#endif
{utils::cli::options::unmount_option, cli::actions::unmount},
{utils::cli::options::unpin_file_option, cli::actions::unpin_file},
};
static exit_code perform_action(const utils::cli::option &opt, const int &argc, char *argv[],
const std::string &data_directory, const provider_type &pt,
const std::string &unique_id, std::string user,
std::string password) {
if (utils::cli::has_option(argc, argv, opt)) {
if (option_actions.find(opt) != option_actions.end()) {
return option_actions.at(opt)(argc, argv, data_directory, pt, unique_id, std::move(user),
std::move(password));
}
}
return exit_code::option_not_found;
}
} // namespace repertory::cli::actions
#endif // INCLUDE_CLI_ACTIONS_HPP_

View File

@ -0,0 +1,63 @@
/*
Copyright <2018-2022> <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_CLI_CHECK_VERSION_HPP_
#define INCLUDE_CLI_CHECK_VERSION_HPP_
#include "common.hpp"
#include "comm/curl/curl_comm.hpp"
#include "app_config.hpp"
#include "types/repertory.hpp"
namespace repertory::cli::actions {
static exit_code check_version(const int &, char *[], const std::string &data_directory,
const provider_type &pt, const std::string &, std::string,
std::string) {
auto ret = exit_code::success;
if (not((pt == provider_type::remote) || (pt == provider_type::s3) ||
(pt == provider_type::skynet))) {
app_config config(pt, data_directory);
curl_comm comm(config);
json data, err;
if (comm.get("/daemon/version", data, err) == api_error::success) {
const auto res = utils::compare_version_strings(data["version"].get<std::string>(),
app_config::get_provider_minimum_version(pt));
if (res < 0) {
ret = exit_code::incompatible_version;
std::cerr << "Failed!" << std::endl;
std::cerr << " Actual: " << data["version"].get<std::string>() << std::endl;
std::cerr << " Minimum: " << app_config::get_provider_minimum_version(pt) << std::endl;
} else {
std::cout << "Success!" << std::endl;
std::cout << " Actual: " << data["version"].get<std::string>() << std::endl;
std::cout << " Minimum: " << app_config::get_provider_minimum_version(pt) << std::endl;
}
} else {
std::cerr << "Failed!" << std::endl;
std::cerr << err.dump(2) << std::endl;
ret = exit_code::communication_error;
}
}
return ret;
}
} // namespace repertory::cli::actions
#endif // INCLUDE_CLI_CHECK_VERSION_HPP_

View File

@ -0,0 +1,53 @@
/*
Copyright <2018-2022> <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_CLI_DISPLAY_CONFIG_HPP_
#define INCLUDE_CLI_DISPLAY_CONFIG_HPP_
#include "common.hpp"
#include "app_config.hpp"
#include "platform/platform.hpp"
#include "rpc/client/client.hpp"
#include "types/repertory.hpp"
#include "types/rpc.hpp"
#include "utils/cli_utils.hpp"
namespace repertory::cli::actions {
static exit_code display_config(const int &, char *[], const std::string &data_directory,
const provider_type &pt, const std::string &unique_id,
std::string user, std::string password) {
lock_data lock(pt, unique_id);
const auto res = lock.grab_lock(1u);
if (res == lock_result::success) {
app_config config(pt, data_directory);
const auto cfg = config.get_json();
std::cout << 0 << std::endl;
std::cout << cfg.dump(2) << std::endl;
} else if (res == lock_result::locked) {
auto port = app_config::default_api_port(pt);
utils::cli::get_api_authentication_data(user, password, port, pt, data_directory);
const auto response = client({"localhost", password, port, user}).get_config();
std::cout << static_cast<int>(response.response_type) << std::endl;
std::cout << response.data.dump(2) << std::endl;
}
return exit_code::success;
}
} // namespace repertory::cli::actions
#endif // INCLUDE_CLI_DISPLAY_CONFIG_HPP_

View File

@ -0,0 +1,53 @@
/*
Copyright <2018-2022> <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_CLI_DRIVE_INFORMATION_HPP_
#define INCLUDE_CLI_DRIVE_INFORMATION_HPP_
#include "common.hpp"
#include "app_config.hpp"
#include "platform/platform.hpp"
#include "rpc/client/client.hpp"
#include "types/repertory.hpp"
#include "types/rpc.hpp"
#include "utils/cli_utils.hpp"
namespace repertory::cli::actions {
static exit_code drive_information(const int &, char *[], const std::string &data_directory,
const provider_type &pt, const std::string &unique_id,
std::string user, std::string password) {
auto ret = exit_code::success;
lock_data lock(pt, unique_id);
const auto res = lock.grab_lock(1u);
if (res == lock_result::locked) {
auto port = app_config::default_api_port(pt);
utils::cli::get_api_authentication_data(user, password, port, pt, data_directory);
const auto response = client({"localhost", password, port, user}).get_drive_information();
std::cout << static_cast<int>(response.response_type) << std::endl;
std::cout << response.data.dump(2) << std::endl;
} else {
std::cerr << app_config::get_provider_display_name(pt) << " is not mounted." << std::endl;
ret = exit_code::not_mounted;
}
return ret;
}
} // namespace repertory::cli::actions
#endif // INCLUDE_CLI_DRIVE_INFORMATION_HPP_

53
include/cli/export.hpp Normal file
View File

@ -0,0 +1,53 @@
/*
Copyright <2018-2022> <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_CLI_EXPORT_HPP_
#define INCLUDE_CLI_EXPORT_HPP_
#include "common.hpp"
#include "app_config.hpp"
#include "rpc/client/client.hpp"
#include "types/repertory.hpp"
#include "types/rpc.hpp"
#include "utils/cli_utils.hpp"
namespace repertory::cli::actions {
static exit_code export_action(const int &argc, char *argv[], const std::string &data_directory,
const provider_type &pt, const std::string &, std::string user,
std::string password) {
std::string data;
auto ret = utils::cli::parse_string_option(argc, argv,
repertory::utils::cli::options::export_option, data);
if (ret == exit_code::success) {
auto port = app_config::default_api_port(pt);
utils::cli::get_api_authentication_data(user, password, port, pt, data_directory);
const auto response =
client({"localhost", password, port, user}).export_list(utils::string::split(data, ','));
if (response.response_type == rpc_response_type::success) {
std::cout << response.data.dump(2) << std::endl;
} else {
std::cerr << response.data.dump(2) << std::endl;
ret = exit_code::export_failed;
}
}
return ret;
}
} // namespace repertory::cli::actions
#endif // INCLUDE_CLI_EXPORT_HPP_

View File

@ -0,0 +1,49 @@
/*
Copyright <2018-2022> <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_CLI_EXPORT_ALL_HPP_
#define INCLUDE_CLI_EXPORT_ALL_HPP_
#include "common.hpp"
#include "app_config.hpp"
#include "rpc/client/client.hpp"
#include "types/repertory.hpp"
#include "types/rpc.hpp"
#include "types/skynet.hpp"
#include "utils/cli_utils.hpp"
namespace repertory::cli::actions {
static exit_code export_all(const int &, char *[], const std::string &data_directory,
const provider_type &pt, const std::string &, std::string user,
std::string password) {
auto ret = exit_code::success;
auto port = app_config::default_api_port(pt);
utils::cli::get_api_authentication_data(user, password, port, pt, data_directory);
const auto response = client({"localhost", password, port, user}).export_all();
if (response.response_type == rpc_response_type::success) {
std::cout << response.data.dump(2) << std::endl;
} else {
std::cerr << response.data.dump(2) << std::endl;
ret = exit_code::export_failed;
}
return ret;
}
} // namespace repertory::cli::actions
#endif // INCLUDE_CLI_EXPORT_ALL_HPP_

60
include/cli/get.hpp Normal file
View File

@ -0,0 +1,60 @@
/*
Copyright <2018-2022> <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_CLI_GET_HPP_
#define INCLUDE_CLI_GET_HPP_
#include "common.hpp"
#include "app_config.hpp"
#include "platform/platform.hpp"
#include "rpc/client/client.hpp"
#include "types/repertory.hpp"
#include "types/rpc.hpp"
#include "utils/cli_utils.hpp"
namespace repertory::cli::actions {
static exit_code get(const int &argc, char *argv[], const std::string &data_directory,
const provider_type &pt, const std::string &unique_id, std::string user,
std::string password) {
std::string data;
auto ret =
utils::cli::parse_string_option(argc, argv, repertory::utils::cli::options::get_option, data);
if (ret == exit_code::success) {
lock_data lock(pt, unique_id);
const auto res = lock.grab_lock(1);
if (res == lock_result::success) {
app_config config(pt, data_directory);
const auto value = config.get_value_by_name(data);
std::cout << (value.empty() ? static_cast<int>(rpc_response_type::config_value_not_found) : 0)
<< std::endl;
std::cout << json({{"value", value}}).dump(2) << std::endl;
} else if (res == lock_result::locked) {
auto port = app_config::default_api_port(pt);
utils::cli::get_api_authentication_data(user, password, port, pt, data_directory);
const auto response =
client({"localhost", password, port, user}).get_config_value_by_name(data);
std::cout << static_cast<int>(response.response_type) << std::endl;
std::cout << response.data.dump(2) << std::endl;
}
}
return ret;
}
} // namespace repertory::cli::actions
#endif // INCLUDE_CLI_GET_HPP_

View File

@ -0,0 +1,53 @@
/*
Copyright <2018-2022> <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_CLI_GET_DIRECTORY_ITEMS_HPP_
#define INCLUDE_CLI_GET_DIRECTORY_ITEMS_HPP_
#include "common.hpp"
#include "app_config.hpp"
#include "rpc/client/client.hpp"
#include "types/repertory.hpp"
#include "types/rpc.hpp"
#include "types/skynet.hpp"
#include "utils/cli_utils.hpp"
namespace repertory::cli::actions {
static exit_code get_directory_items(const int &argc, char *argv[],
const std::string &data_directory, const provider_type &pt,
const std::string &, std::string user, std::string password) {
std::string data;
auto ret = utils::cli::parse_string_option(
argc, argv, repertory::utils::cli::options::get_directory_items_option, data);
if (ret == exit_code::success) {
auto port = app_config::default_api_port(pt);
utils::cli::get_api_authentication_data(user, password, port, pt, data_directory);
const auto response = client({"localhost", password, port, user}).get_directory_items(data);
if (response.response_type == rpc_response_type::success) {
std::cout << response.data.dump(2) << std::endl;
} else {
std::cerr << response.data.dump(2) << std::endl;
ret = exit_code::export_failed;
}
}
return ret;
}
} // namespace repertory::cli::actions
#endif // INCLUDE_CLI_GETDIRECTORYITEMS_HPP_

View File

@ -0,0 +1,48 @@
/*
Copyright <2018-2022> <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_CLI_GET_PINNED_FILES_HPP_
#define INCLUDE_CLI_GET_PINNED_FILES_HPP_
#include "common.hpp"
#include "app_config.hpp"
#include "rpc/client/client.hpp"
#include "types/repertory.hpp"
#include "types/rpc.hpp"
#include "utils/cli_utils.hpp"
namespace repertory::cli::actions {
static exit_code get_pinned_files(const int &, char *[], const std::string &data_directory,
const provider_type &pt, const std::string &, std::string user,
std::string password) {
auto ret = exit_code::success;
auto port = app_config::default_api_port(pt);
utils::cli::get_api_authentication_data(user, password, port, pt, data_directory);
const auto response = client({"localhost", password, port, user}).get_pinned_files();
if (response.response_type == rpc_response_type::success) {
std::cout << response.data.dump(2) << std::endl;
} else {
std::cerr << response.data.dump(2) << std::endl;
ret = exit_code::export_failed;
}
return ret;
}
} // namespace repertory::cli::actions
#endif // INCLUDE_CLI_GET_PINNED_FILES_HPP_

106
include/cli/help.hpp Normal file
View File

@ -0,0 +1,106 @@
/*
Copyright <2018-2022> <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_CLI_HELP_HPP_
#define INCLUDE_CLI_HELP_HPP_
#include "common.hpp"
namespace repertory::cli::actions {
template <typename drive> static void help(const int &argc, char *argv[]) {
drive::display_options(argc, argv);
std::cout << "Repertory options:" << std::endl;
std::cout << " -cv,--check_version Check daemon version compatibility"
<< std::endl;
std::cout << " -dc,--display_config Display configuration" << std::endl;
std::cout << " -dd,--data_directory [directory] Override data directory" << std::endl;
std::cout << " -di,--drive_information Display mounted drive information"
<< std::endl;
#if defined(REPERTORY_ENABLE_SKYNET)
std::cout << " -ea,--export_all Export all Skynet skylinks" << std::endl;
std::cout << " -ex,--export [path1,path2,...] Export one or more Skynet skylinks"
<< std::endl;
#endif // defined(REPERTORY_ENABLE_SKYNET)
#if defined(REPERTORY_ENABLE_S3)
std::cout << " -s3,--s3 Enables S3 mode" << std::endl;
std::cout << " -na,--name Unique name for S3 instance [Required]"
<< std::endl;
#endif // defined(REPERTORY_ENABLE_S3)
std::cout << " -gc,--generate_config Generate initial configuration" << std::endl;
std::cout << " -get,--get [name] Get configuration value" << std::endl;
std::cout << " -gdi,--get_directory_items Get directory list in json format"
<< std::endl
<< " [API path]" << std::endl;
std::cout << " -gpf,--get_pinned_files Get a list of all pinned files" << std::endl;
std::cout << " -gt,--generate_template Generate configuration template" << std::endl;
#if defined(REPERTORY_ENABLE_SKYNET)
std::cout << " -ij,--import_json [json_array] Import Skynet skylink(s)" << std::endl;
std::cout << " [json_array] format:" << std::endl;
std::cout << " [{" << std::endl;
std::cout << R"( "directory": "/parent",)" << std::endl;
std::cout << R"( "skylink": "AACeCiD6WQG6DzDcCdIu3cFPSxMUMoQPx46NYSyijNMKUA",)"
<< std::endl;
std::cout << R"( "token": "encryption password")" << std::endl;
std::cout << " }]" << std::endl;
std::cout << " NOTE: 'directory' and 'token' are optional" << std::endl;
std::cout << " -im,--import [list] Import Skynet skylink(s)" << std::endl;
std::cout << " [list] format:" << std::endl;
std::cout << " directory=<directory>:skylink=<skylink>:token=<token>;..." << std::endl;
std::cout << std::endl;
std::cout << " NOTE: 'directory' and 'token' are optional" << std::endl;
std::cout << " NOTE: Use '@sem@' to escape a ';'" << std::endl;
std::cout << " Use '@comma@' to escape a ','" << std::endl;
std::cout << " Use '@equal@' to escape an '='" << std::endl;
std::cout << " Use '@dbl_quote@' to escape a '\"'" << std::endl;
#endif // defined(REPERTORY_ENABLE_SKYNET)
std::cout << " -nc Force disable console output" << std::endl;
std::cout << " -of,--open_files List all open files and count" << std::endl;
std::cout << " -rm,--remote_mount [host/ip:port] Enables remote mount mode" << std::endl;
std::cout << " -pf,--pin_file [API path] Pin a file to cache to prevent eviction"
<< std::endl;
std::cout << " -ps,--pinned_status [API path] Return pinned status for a file" << std::endl;
std::cout << " -pw,--password Specify API password" << std::endl;
#if defined(REPERTORY_ENABLE_SKYNET)
std::cout << " -sk,--skynet [EXPERIMENTAL] Enables Skynet mode"
<< std::endl;
#endif // defined(REPERTORY_ENABLE_SKYNET)
#ifndef _WIN32
#if defined(REPERTORY_ENABLE_S3)
std::cout << " -o s3 Enables S3 mode for 'fstab' mounts"
<< std::endl;
#endif // defined(REPERTORY_ENABLE_S3)
#if defined(REPERTORY_ENABLE_SKYNET)
std::cout << " -o sk,-o skynet Enables Skynet mode for 'fstab' mounts"
<< std::endl;
#endif // defined(REPERTORY_ENABLE_SKYNET)
#endif // _WIN32
std::cout << " -set,--set [name] [value] Set configuration value" << std::endl;
std::cout << " -status Display mount status" << std::endl;
#if defined(REPERTORY_ENABLE_SKYNET)
std::cout << " -tsa,--test_skynet_auth Test Skynet portal authentication"
<< std::endl;
std::cout << " [URL] [user] [password] [agent string] [API key]" << std::endl;
#endif // defined(REPERTORY_ENABLE_SKYNET)
std::cout << " -unmount,--unmount Unmount and shutdown" << std::endl;
std::cout << " -uf,--unpin_file [API path] Unpin a file from cache to allow eviction"
<< std::endl;
std::cout << " -us,--user Specify API user name" << std::endl;
}
} // namespace repertory::cli::actions
#endif // INCLUDE_CLI_HELP_HPP_

62
include/cli/import.hpp Normal file
View File

@ -0,0 +1,62 @@
/*
Copyright <2018-2022> <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_CLI_IMPORT_HPP_
#define INCLUDE_CLI_IMPORT_HPP_
#include "common.hpp"
#include "app_config.hpp"
#include "rpc/client/client.hpp"
#include "types/repertory.hpp"
#include "types/rpc.hpp"
#include "types/skynet.hpp"
#include "utils/cli_utils.hpp"
namespace repertory::cli::actions {
static exit_code import(const int &argc, char *argv[], const std::string &data_directory,
const provider_type &pt, const std::string &, std::string user,
std::string password) {
std::string data;
auto ret = utils::cli::parse_string_option(argc, argv,
repertory::utils::cli::options::import_option, data);
if (ret == exit_code::success) {
utils::string::replace(data, "@dbl_quote@", "\"");
const auto parts = utils::string::split(data, ';');
skylink_import_list list;
for (const auto &part : parts) {
list.emplace_back(
skylink_import::from_string(utils::string::replace_copy(part, "@sem@", ";")));
}
auto port = app_config::default_api_port(pt);
utils::cli::get_api_authentication_data(user, password, port, pt, data_directory);
const auto response = client({"localhost", password, port, user}).import_skylink(list);
std::cout << static_cast<int>(response.response_type) << std::endl;
if (response.response_type == rpc_response_type::success) {
std::cout << response.data.dump(2) << std::endl;
} else {
std::cerr << response.data.dump(2) << std::endl;
ret = exit_code::import_failed;
}
}
return ret;
}
} // namespace repertory::cli::actions
#endif // INCLUDE_CLI_IMPORT_HPP_

View File

@ -0,0 +1,68 @@
/*
Copyright <2018-2022> <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_CLI_IMPORT_JSON_HPP_
#define INCLUDE_CLI_IMPORT_JSON_HPP_
#include "common.hpp"
#include "app_config.hpp"
#include "rpc/client/client.hpp"
#include "types/repertory.hpp"
#include "types/rpc.hpp"
#include "types/skynet.hpp"
#include "utils/cli_utils.hpp"
namespace repertory::cli::actions {
static exit_code import_json(const int &argc, char *argv[], const std::string &data_directory,
const provider_type &pt, const std::string &, std::string user,
std::string password) {
std::string data;
auto ret = utils::cli::parse_string_option(argc, argv, {"-ij", "--import_json"}, data);
if (ret == exit_code::success) {
utils::string::replace(data, "@dbl_quote@", "\"");
skylink_import_list list;
try {
const auto json_data = json::parse(data);
for (const auto &j : json_data) {
list.emplace_back(skylink_import::from_json(j));
}
} catch (const std::exception &e) {
std::cerr << "Import JSON failed:" << std::endl << e.what() << std::endl;
ret = exit_code::import_failed;
}
if (not list.empty()) {
auto port = app_config::default_api_port(pt);
utils::cli::get_api_authentication_data(user, password, port, pt, data_directory);
const auto response = client({"localhost", password, port, user}).import_skylink(list);
std::cout << static_cast<int>(response.response_type) << std::endl;
if (response.response_type == rpc_response_type::success) {
std::cout << response.data.dump(2) << std::endl;
} else {
std::cerr << response.data.dump(2) << std::endl;
ret = exit_code::import_failed;
}
}
}
return ret;
}
} // namespace repertory::cli::actions
#endif // INCLUDE_CLI_IMPORT_JSON_HPP_

159
include/cli/mount.hpp Normal file
View File

@ -0,0 +1,159 @@
/*
Copyright <2018-2022> <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_CLI_MOUNT_HPP_
#define INCLUDE_CLI_MOUNT_HPP_
#include "common.hpp"
#include "platform/platform.hpp"
#include "providers/provider.hpp"
#include "types/repertory.hpp"
#include "utils/cli_utils.hpp"
#include "utils/com_init_wrapper.hpp"
#include "utils/file_utils.hpp"
#ifdef _WIN32
#include "drives/winfsp/remotewinfsp/remote_client.hpp"
#include "drives/winfsp/remotewinfsp/remote_winfsp_drive.hpp"
#include "drives/winfsp/winfsp_drive.hpp"
typedef repertory::winfsp_drive repertory_drive;
typedef repertory::remote_winfsp::remote_client remote_client;
typedef repertory::remote_winfsp::remote_winfsp_drive remote_drive;
typedef repertory::remote_winfsp::i_remote_instance remote_instance;
#else
#include "drives/fuse/fuse_drive.hpp"
#include "drives/fuse/remotefuse/remote_client.hpp"
#include "drives/fuse/remotefuse/remote_fuse_drive.hpp"
typedef repertory::fuse_drive repertory_drive;
typedef repertory::remote_fuse::remote_client remote_client;
typedef repertory::remote_fuse::remote_fuse_drive remote_drive;
typedef repertory::remote_fuse::i_remote_instance remote_instance;
#endif
namespace repertory::cli::actions {
static exit_code mount(const int &argc, char *argv[], std::string data_directory, int &mount_result,
provider_type pt, const std::string &remote_host,
const std::uint16_t &remote_port, const std::string &unique_id) {
auto ret = exit_code::success;
lock_data lock(pt, unique_id);
const auto res = lock.grab_lock();
if (res == lock_result::locked) {
ret = exit_code::mount_active;
std::cerr << app_config::get_provider_display_name(pt) << " mount is already active"
<< std::endl;
} else if (res == lock_result::success) {
curl_global_init(CURL_GLOBAL_DEFAULT);
{
const auto generate_config =
utils::cli::has_option(argc, argv, utils::cli::options::generate_config_option);
if (generate_config) {
app_config config(pt, data_directory);
if (pt == provider_type::remote) {
config.set_enable_remote_mount(false);
config.set_is_remote_mount(true);
config.set_remote_host_name_or_ip(remote_host);
config.set_remote_port(remote_port);
}
std::cout << "Generated " << app_config::get_provider_display_name(pt) << " Configuration"
<< std::endl;
std::cout << config.get_config_file_path() << std::endl;
ret = utils::file::is_file(config.get_config_file_path()) ? exit_code::success
: exit_code::file_creation_failed;
} else {
#ifdef _WIN32
if (utils::cli::has_option(argc, argv, utils::cli::options::hidden_option)) {
::ShowWindow(::GetConsoleWindow(), SW_HIDE);
}
#endif
const auto driveArgs = utils::cli::parse_drive_options(argc, argv, pt, data_directory);
std::cout << "Initializing " << app_config::get_provider_display_name(pt)
<< (unique_id.empty() ? ""
: (pt == provider_type::s3)
? " [" + unique_id + ']'
: " [" + remote_host + ':' + std::to_string(remote_port) + ']')
<< " Drive" << std::endl;
app_config config(pt, data_directory);
if (pt == provider_type::remote) {
std::uint16_t port = 0u;
if (utils::get_next_available_port(config.get_api_port(), port)) {
config.set_remote_host_name_or_ip(remote_host);
config.set_remote_port(remote_port);
config.set_api_port(port);
config.set_is_remote_mount(true);
config.set_enable_remote_mount(false);
config.save();
try {
remote_drive drive(config, lock, [&config]() -> std::unique_ptr<remote_instance> {
return std::unique_ptr<remote_instance>(new remote_client(config));
});
lock.set_mount_state(true, "", -1);
mount_result = drive.mount(driveArgs);
ret = exit_code::mount_result;
} catch (const std::exception &e) {
std::cerr << "FATAL: " << e.what() << std::endl;
ret = exit_code::startup_exception;
}
} else {
std::cerr << "FATAL: Unable to get available port" << std::endl;
ret = exit_code::startup_exception;
}
} else {
#ifdef _WIN32
if (config.get_enable_mount_manager() && not utils::is_process_elevated()) {
com_init_wrapper cw;
lock.set_mount_state(true, "elevating", -1);
lock.release();
mount_result = utils::run_process_elevated(argc, argv);
lock_data lockData2(pt, unique_id);
if (lockData2.grab_lock() == lock_result::success) {
lockData2.set_mount_state(false, "", -1);
lockData2.release();
}
return exit_code::mount_result;
}
#endif
config.set_is_remote_mount(false);
try {
auto provider = create_provider(pt, config);
repertory_drive drive(config, lock, *provider);
lock.set_mount_state(true, "", -1);
mount_result = drive.mount(driveArgs);
ret = exit_code::mount_result;
} catch (const std::exception &e) {
std::cerr << "FATAL: " << e.what() << std::endl;
ret = exit_code::startup_exception;
}
}
}
}
curl_global_cleanup();
} else {
ret = exit_code::lock_failed;
}
return ret;
}
} // namespace repertory::cli::actions
#endif // INCLUDE_CLI_MOUNT_HPP_

View File

@ -0,0 +1,52 @@
/*
Copyright <2018-2022> <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_CLI_OPEN_FILES_HPP_
#define INCLUDE_CLI_OPEN_FILES_HPP_
#include "common.hpp"
#include "app_config.hpp"
#include "platform/platform.hpp"
#include "rpc/client/client.hpp"
#include "types/repertory.hpp"
#include "types/rpc.hpp"
#include "utils/cli_utils.hpp"
namespace repertory::cli::actions {
static exit_code open_files(const int &, char *[], const std::string &data_directory,
const provider_type &pt, const std::string &unique_id, std::string user,
std::string password) {
auto ret = exit_code::success;
lock_data lock(pt, unique_id);
const auto res = lock.grab_lock(1u);
if (res == lock_result::locked) {
auto port = app_config::default_api_port(pt);
utils::cli::get_api_authentication_data(user, password, port, pt, data_directory);
const auto response = client({"localhost", password, port, user}).get_open_files();
std::cout << static_cast<int>(response.response_type) << std::endl;
std::cout << response.data.dump(2) << std::endl;
} else {
std::cerr << app_config::get_provider_display_name(pt) << " is not mounted." << std::endl;
ret = exit_code::not_mounted;
}
return ret;
}
} // namespace repertory::cli::actions
#endif // INCLUDE_CLI_OPEN_FILES_HPP_

53
include/cli/pin_file.hpp Normal file
View File

@ -0,0 +1,53 @@
/*
Copyright <2018-2022> <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_CLI_PIN_FILE_HPP_
#define INCLUDE_CLI_PIN_FILE_HPP_
#include "common.hpp"
#include "app_config.hpp"
#include "rpc/client/client.hpp"
#include "types/repertory.hpp"
#include "types/rpc.hpp"
#include "types/skynet.hpp"
#include "utils/cli_utils.hpp"
namespace repertory::cli::actions {
static exit_code pin_file(const int &argc, char *argv[], const std::string &data_directory,
const provider_type &pt, const std::string &, std::string user,
std::string password) {
std::string data;
auto ret = utils::cli::parse_string_option(argc, argv,
repertory::utils::cli::options::pin_file_option, data);
if (ret == exit_code::success) {
auto port = app_config::default_api_port(pt);
utils::cli::get_api_authentication_data(user, password, port, pt, data_directory);
const auto response = client({"localhost", password, port, user}).pin_file(data);
if (response.response_type == rpc_response_type::success) {
std::cout << response.data.dump(2) << std::endl;
} else {
std::cerr << response.data.dump(2) << std::endl;
ret = exit_code::pin_failed;
}
}
return ret;
}
} // namespace repertory::cli::actions
#endif // INCLUDE_CLI_PIN_FILE_HPP_

View File

@ -0,0 +1,53 @@
/*
Copyright <2018-2022> <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_CLI_PINNED_STATUS_HPP_
#define INCLUDE_CLI_PINNED_STATUS_HPP_
#include "common.hpp"
#include "app_config.hpp"
#include "rpc/client/client.hpp"
#include "types/repertory.hpp"
#include "types/rpc.hpp"
#include "types/skynet.hpp"
#include "utils/cli_utils.hpp"
namespace repertory::cli::actions {
static exit_code pinned_status(const int &argc, char *argv[], const std::string &data_directory,
const provider_type &pt, const std::string &, std::string user,
std::string password) {
std::string data;
auto ret = utils::cli::parse_string_option(
argc, argv, repertory::utils::cli::options::pinned_status_option, data);
if (ret == exit_code::success) {
auto port = app_config::default_api_port(pt);
utils::cli::get_api_authentication_data(user, password, port, pt, data_directory);
const auto response = client({"localhost", password, port, user}).pinned_status(data);
if (response.response_type == rpc_response_type::success) {
std::cout << response.data.dump(2) << std::endl;
} else {
std::cerr << response.data.dump(2) << std::endl;
ret = exit_code::export_failed;
}
}
return ret;
}
} // namespace repertory::cli::actions
#endif // INCLUDE_CLI_PINNED_STATUS_HPP_

72
include/cli/set.hpp Normal file
View File

@ -0,0 +1,72 @@
/*
Copyright <2018-2022> <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_CLI_SET_HPP_
#define INCLUDE_CLI_SET_HPP_
#include "common.hpp"
#include "app_config.hpp"
#include "platform/platform.hpp"
#include "rpc/client/client.hpp"
#include "types/repertory.hpp"
#include "types/rpc.hpp"
#include "utils/cli_utils.hpp"
namespace repertory::cli::actions {
static exit_code set(const int &argc, char *argv[], const std::string &data_directory,
const provider_type &pt, const std::string &unique_id, std::string user,
std::string password) {
auto ret = exit_code::success;
auto data = utils::cli::parse_option(argc, argv, "-set", 2u);
if (data.empty()) {
data = utils::cli::parse_option(argc, argv, "--set", 2u);
if (data.empty()) {
ret = exit_code::invalid_syntax;
std::cerr << "Invalid syntax for '-set'" << std::endl;
}
}
if (ret == exit_code::success) {
lock_data lock(pt, unique_id);
const auto res = lock.grab_lock(1u);
if (res == lock_result::success) {
app_config config(pt, data_directory);
const auto value = config.set_value_by_name(data[0u], data[1u]);
const auto notFound = value.empty() && not data[1u].empty();
ret = notFound ? exit_code::set_option_not_found : exit_code::success;
std::cout << (notFound ? static_cast<int>(rpc_response_type::config_value_not_found) : 0)
<< std::endl;
std::cout << json({{"value", value}}).dump(2) << std::endl;
} else if (res == lock_result::locked) {
auto port = app_config::default_api_port(pt);
utils::cli::get_api_authentication_data(user, password, port, pt, data_directory);
const auto response =
client({"localhost", password, port, user}).set_config_value_by_name(data[0u], data[1u]);
std::cout << static_cast<int>(response.response_type) << std::endl;
std::cout << response.data.dump(2) << std::endl;
ret = response.response_type == rpc_response_type::config_value_not_found
? exit_code::set_option_not_found
: response.response_type == rpc_response_type::success ? exit_code::success
: exit_code::communication_error;
}
}
return ret;
}
} // namespace repertory::cli::actions
#endif // INCLUDE_CLI_SET_HPP_

44
include/cli/status.hpp Normal file
View File

@ -0,0 +1,44 @@
/*
Copyright <2018-2022> <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_CLI_STATUS_HPP_
#define INCLUDE_CLI_STATUS_HPP_
#include "common.hpp"
#include "platform/platform.hpp"
#include "types/repertory.hpp"
namespace repertory::cli::actions {
static exit_code status(const int &, char *[], const std::string &, const provider_type &pt,
const std::string &unique_id, std::string, std::string) {
auto ret = exit_code::success;
lock_data lock(pt, unique_id);
lock.grab_lock(10u);
json mount_state;
if (lock.get_mount_state(mount_state)) {
std::cout << mount_state.dump(2) << std::endl;
} else {
std::cout << "{}" << std::endl;
ret = exit_code::failed_to_get_mount_state;
}
return ret;
}
} // namespace repertory::cli::actions
#endif // INCLUDE_CLI_STATUS_HPP_

View File

@ -0,0 +1,91 @@
/*
Copyright <2018-2022> <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_CLI_TEST_SKYNET_AUTH_HPP_
#define INCLUDE_CLI_TEST_SKYNET_AUTH_HPP_
#ifdef REPERTORY_ENABLE_SKYNET
#include "common.hpp"
#include "comm/curl/curl_comm.hpp"
#include "app_config.hpp"
#include "events/consumers/console_consumer.hpp"
#include "events/event_system.hpp"
#include "types/repertory.hpp"
#include "utils/cli_utils.hpp"
#include "utils/file_utils.hpp"
#include "utils/path_utils.hpp"
#include "utils/utils.hpp"
namespace repertory::cli::actions {
static exit_code test_skynet_auth(const int &argc, char *argv[], const std::string &,
const provider_type &, const std::string &, std::string,
std::string) {
auto ret = exit_code::success;
auto data = utils::cli::parse_option(argc, argv, "-tsa", 5u);
if (data.empty()) {
data = utils::cli::parse_option(argc, argv, "--test_skynet_auth", 5u);
if (data.empty()) {
ret = exit_code::invalid_syntax;
std::cerr << "Invalid syntax for '-tsa'" << std::endl;
}
}
const auto uuid = utils::create_uuid_string();
const auto config_directory = utils::path::absolute(utils::path::combine("./", {uuid}));
if (ret == exit_code::success) {
utils::file::change_to_process_directory();
{
console_consumer c;
event_system::instance().start();
app_config config(provider_type::skynet, config_directory);
host_config hc{};
hc.auth_url = data[0];
hc.auth_user = data[1];
hc.auth_password = data[2];
hc.agent_string = data[3];
hc.api_password = data[4];
curl_comm comm(config);
std::string session;
CURL *curl_handle = nullptr;
ret = (comm.create_auth_session(curl_handle, config, hc, session))
? exit_code::success
: exit_code::communication_error;
if (ret == exit_code::success) {
curl_easy_cleanup(curl_handle);
comm.release_auth_session(config, hc, session);
}
event_system::instance().stop();
}
if (ret == exit_code::success) {
std::cout << std::endl << "Authentication Succeeded!" << std::endl;
} else {
std::cerr << std::endl << "Authentication Failed!" << std::endl;
}
}
utils::file::delete_directory_recursively(config_directory);
return ret;
}
} // namespace repertory::cli::actions
#endif // REPERTORY_ENABLE_SKYNET
#endif // INCLUDE_CLI_TEST_SKYNET_AUTH_HPP_

49
include/cli/unmount.hpp Normal file
View File

@ -0,0 +1,49 @@
/*
Copyright <2018-2022> <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_CLI_UNMOUNT_HPP_
#define INCLUDE_CLI_UNMOUNT_HPP_
#include "common.hpp"
#include "app_config.hpp"
#include "rpc/client/client.hpp"
#include "types/repertory.hpp"
#include "types/rpc.hpp"
#include "utils/cli_utils.hpp"
namespace repertory::cli::actions {
static exit_code unmount(const int &, char *[], const std::string &data_directory,
const provider_type &pt, const std::string &, std::string user,
std::string password) {
auto ret = exit_code::success;
auto port = app_config::default_api_port(pt);
utils::cli::get_api_authentication_data(user, password, port, pt, data_directory);
const auto response = client({"localhost", password, port, user}).unmount();
std::cout << static_cast<int>(response.response_type) << std::endl;
if (response.response_type == rpc_response_type::success) {
std::cout << response.data.dump(2) << std::endl;
} else {
std::cerr << response.data.dump(2) << std::endl;
ret = exit_code::communication_error;
}
return ret;
}
} // namespace repertory::cli::actions
#endif // INCLUDE_CLI_UNMOUNT_HPP_

View File

@ -0,0 +1,53 @@
/*
Copyright <2018-2022> <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_CLI_UNPIN_FILE_HPP_
#define INCLUDE_CLI_UNPIN_FILE_HPP_
#include "common.hpp"
#include "app_config.hpp"
#include "rpc/client/client.hpp"
#include "types/repertory.hpp"
#include "types/rpc.hpp"
#include "types/skynet.hpp"
#include "utils/cli_utils.hpp"
namespace repertory::cli::actions {
static exit_code unpin_file(const int &argc, char *argv[], const std::string &data_directory,
const provider_type &pt, const std::string &, std::string user,
std::string password) {
std::string data;
auto ret = utils::cli::parse_string_option(
argc, argv, repertory::utils::cli::options::unpin_file_option, data);
if (ret == exit_code::success) {
auto port = app_config::default_api_port(pt);
utils::cli::get_api_authentication_data(user, password, port, pt, data_directory);
const auto response = client({"localhost", password, port, user}).unpin_file(data);
if (response.response_type == rpc_response_type::success) {
std::cout << response.data.dump(2) << std::endl;
} else {
std::cerr << response.data.dump(2) << std::endl;
ret = exit_code::unpin_failed;
}
}
return ret;
}
} // namespace repertory::cli::actions
#endif // INCLUDE_CLI_UNPIN_FILE_HPP_

32
include/cli/version.hpp Normal file
View File

@ -0,0 +1,32 @@
/*
Copyright <2018-2022> <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_CLI_VERSION_HPP_
#define INCLUDE_CLI_VERSION_HPP_
#include "common.hpp"
namespace repertory::cli::actions {
template <typename drive> static void version(const int &argc, char *argv[]) {
std::cout << "Repertory core version: " << get_repertory_version() << std::endl;
std::cout << "Repertory Git revision: " << get_repertory_git_revision() << std::endl;
drive::display_version_information(argc, argv);
}
} // namespace repertory::cli::actions
#endif // INCLUDE_CLI_VERSION_HPP_

View File

@ -0,0 +1,124 @@
/*
Copyright <2018-2022> <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_COMM_AWS_S3_AWS_S3_COMM_HPP_
#define INCLUDE_COMM_AWS_S3_AWS_S3_COMM_HPP_
#if defined(REPERTORY_ENABLE_S3)
#include "common.hpp"
#include "comm/i_s3_comm.hpp"
namespace repertory {
class app_config;
class aws_s3_comm final : public virtual i_s3_comm {
public:
explicit aws_s3_comm(const app_config &config);
~aws_s3_comm() override;
private:
struct cache_entry final {
std::chrono::system_clock::time_point expiration;
directory_item_list items;
void reset_timeout(std::chrono::seconds timeout) {
timeout = std::max(std::chrono::seconds(5u), timeout);
expiration = std::chrono::system_clock::now() + timeout;
}
};
private:
const app_config &config_;
s3_config s3_config_;
Aws::SDKOptions sdk_options_;
std::unique_ptr<Aws::S3::S3Client> s3_client_;
mutable std::recursive_mutex cached_directories_mutex_;
mutable std::unordered_map<std::string, cache_entry> cached_directories_;
private:
void clear_expired_directories();
bool get_cached_directory_item_count(const std::string &api_path, std::size_t &count) const;
bool get_cached_directory_items(const std::string &api_path,
const meta_provider_callback &meta_provider,
directory_item_list &list) const;
bool get_cached_file_exists(const std::string &api_path, bool &exists) const;
api_error grab_directory_items(const std::string &api_path,
const meta_provider_callback &meta_provider,
directory_item_list &list) const;
api_error get_file_list(const std::string &bucket_name,
const get_api_file_token_callback &get_api_file_token,
const get_name_callback &get_name, api_file_list &list) const;
void remove_cached_directory(const std::string &api_path);
void set_cached_directory_items(const std::string &api_path, directory_item_list list) const;
public:
api_error create_bucket(const std::string &api_path) override;
bool exists(const std::string &api_path, const get_key_callback &get_key) const override;
void get_bucket_name_and_object_name(const std::string &api_path, const get_key_callback &getKey,
std::string &bucketName,
std::string &objectName) const override;
std::size_t get_directory_item_count(const std::string &api_path,
const meta_provider_callback &meta_provider) const override;
api_error get_directory_items(const std::string &api_path,
const meta_provider_callback &meta_provider,
directory_item_list &list) const override;
api_error get_file(const std::string &api_path, const get_key_callback &get_key,
const get_name_callback &get_name, const get_token_callback &get_token,
api_file &file) const override;
api_error get_file_list(const get_api_file_token_callback &get_api_file_token,
const get_name_callback &get_name, api_file_list &list) const override;
s3_config get_s3_config() override { return s3_config_; }
s3_config get_s3_config() const override { return s3_config_; }
bool is_online() const override { return s3_client_->ListBuckets().IsSuccess(); }
api_error read_file_bytes(const std::string &api_path, const std::size_t &size,
const std::uint64_t &offset, std::vector<char> &data,
const get_key_callback &get_key, const get_size_callback &get_size,
const get_token_callback &get_token,
const bool &stop_requested) const override;
api_error remove_bucket(const std::string &api_path) override;
api_error remove_file(const std::string &api_path, const get_key_callback &get_key) override;
api_error rename_file(const std::string &api_path, const std::string &new_api_path) override;
api_error upload_file(const std::string &api_path, const std::string &source_path,
const std::string &encryption_token, const get_key_callback &get_key,
const set_key_callback &set_key, const bool &stop_requested) override;
};
} // namespace repertory
#endif // REPERTORY_ENABLE_S3
#endif // INCLUDE_COMM_AWS_S3_AWS_S3_COMM_HPP_

View File

@ -0,0 +1,270 @@
/*
Copyright <2018-2022> <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_COMM_CURL_CURL_COMM_HPP_
#define INCLUDE_COMM_CURL_CURL_COMM_HPP_
#include "common.hpp"
#include "comm/curl/multi_request.hpp"
#include "comm/curl/session_manager.hpp"
#include "comm/i_comm.hpp"
#include "app_config.hpp"
namespace repertory {
class curl_resolver;
namespace utils::encryption {
class encrypting_reader;
}
struct curl_setup;
struct raw_write_data;
class curl_comm : public virtual i_comm {
public:
typedef size_t (*curl_read_callback)(char *, size_t, size_t, void *);
typedef size_t (*curl_write_callback)(char *, size_t, size_t, void *);
static curl_read_callback read_data_callback_;
static curl_write_callback write_data_callback_;
static curl_write_callback write_header_callback_;
static curl_write_callback write_null_callback_;
static curl_write_callback write_string_callback_;
public:
explicit curl_comm(const app_config &config) : config_(config) {}
~curl_comm() override = default;
private:
const app_config &config_;
session_manager session_manager_;
public:
static std::string construct_url(CURL *curl_handle, const std::string &relative_path,
const host_config &hc);
static bool create_auth_session(CURL *&curl_handle, const app_config &config, host_config hc,
std::string &session);
static std::string http_range_to_string(const http_range &range);
static void release_auth_session(const app_config &config, host_config hc,
const std::string &session);
static void update_auth_session(CURL *curl_handle, const app_config &config,
const std::string &session);
private:
CURL *common_curl_setup(const std::string &path, curl_setup &setup, std::string &url,
std::string &fields);
CURL *common_curl_setup(CURL *curl_handle, const std::string &path, curl_setup &setup,
std::string &url, std::string &fields);
template <typename begin, typename end>
api_error execute_binary_operation(CURL *curl_handle, const std::string &url,
std::vector<char> &data, json &error,
const bool &stop_requested,
const CURLcode &default_code = CURLE_OK) {
auto curl_code = default_code;
long http_code = 400;
execute_operation<begin>(curl_handle, url, curl_code, http_code, stop_requested);
const auto ret = process_binary_response(url, curl_code, http_code, data, error);
if (config_.get_event_level() >= end::level) {
event_system::instance().raise<end>(url, curl_code, http_code,
((ret == api_error::success) ? "" : error.dump(2)));
}
return ret;
}
template <typename begin, typename end>
api_error execute_json_operation(CURL *curl_handle, const std::string &url,
const std::string &result, json &data, json &error,
const bool &stop_requested,
const CURLcode &default_code = CURLE_OK) {
auto curl_code = default_code;
long http_code = 400;
execute_operation<begin>(curl_handle, url, curl_code, http_code, stop_requested);
const auto ret = process_json_response(url, curl_code, http_code, result, data, error);
if (config_.get_event_level() >= end::level) {
event_system::instance().raise<end>(url, curl_code, http_code,
((ret == api_error::success) ? "" : error.dump(2)));
}
return ret;
}
template <typename begin>
void execute_operation(CURL *curl_handle, const std::string &url, CURLcode &curl_code,
long &http_code, const bool &stop_requested) {
if (config_.get_event_level() >= begin::level) {
event_system::instance().raise<begin>(url);
}
if (curl_code == CURLE_OK) {
multi_request request(curl_handle, stop_requested);
request.get_result(curl_code, http_code);
}
}
api_error get_or_post(const host_config &hc, const bool &post, const std::string &path,
const http_parameters &parameters, json &data, json &error,
http_headers *headers = nullptr,
std::function<void(CURL *curl_handle)> cb = nullptr);
api_error get_range(const host_config &hc, const std::string &path,
const std::uint64_t &data_size, const http_parameters &parameters,
const std::string &encryption_token, std::vector<char> &data,
const http_ranges &ranges, json &error, http_headers *headers,
const bool &stop_requested);
api_error get_range_unencrypted(const host_config &hc, const std::string &path,
const http_parameters &parameters, std::vector<char> &data,
const http_ranges &ranges, json &error, http_headers *headers,
const bool &stop_requested);
api_error process_binary_response(const std::string &url, const CURLcode &res,
const long &http_code, std::vector<char> data, json &error);
api_error process_json_response(const std::string &url, const CURLcode &res,
const long &http_code, const std::string &result, json &data,
json &error);
api_error process_response(const std::string &url, const CURLcode &res, const long &http_code,
const std::size_t &data_size,
const std::function<std::string()> &to_string_converter,
const std::function<void()> &success_handler, json &error) const;
static std::string url_encode(CURL *curl_handle, const std::string &data,
const bool &allow_slash = false);
public:
api_error get(const std::string &path, json &data, json &error) override {
return get_or_post(config_.get_host_config(), false, path, {}, data, error);
}
api_error get(const host_config &hc, const std::string &path, json &data, json &error) override {
return get_or_post(hc, false, path, {}, data, error);
}
api_error get(const std::string &path, const http_parameters &parameters, json &data,
json &error) override {
return get_or_post(config_.get_host_config(), false, path, parameters, data, error);
}
api_error get(const host_config &hc, const std::string &path, const http_parameters &parameters,
json &data, json &error) override {
return get_or_post(hc, false, path, parameters, data, error);
}
api_error get_range(const std::string &path, const std::uint64_t &data_size,
const http_parameters &parameters, const std::string &encryption_token,
std::vector<char> &data, const http_ranges &ranges, json &error,
const bool &stop_requested) override {
return get_range(config_.get_host_config(), path, data_size, parameters, encryption_token, data,
ranges, error, nullptr, stop_requested);
}
api_error get_range(const host_config &hc, const std::string &path,
const std::uint64_t &data_size, const http_parameters &parameters,
const std::string &encryption_token, std::vector<char> &data,
const http_ranges &ranges, json &error, const bool &stop_requested) override {
return get_range(hc, path, data_size, parameters, encryption_token, data, ranges, error,
nullptr, stop_requested);
}
api_error get_range_and_headers(const std::string &path, const std::uint64_t &dataSize,
const http_parameters &parameters,
const std::string &encryption_token, std::vector<char> &data,
const http_ranges &ranges, json &error, http_headers &headers,
const bool &stop_requested) override {
return get_range(config_.get_host_config(), path, dataSize, parameters, encryption_token, data,
ranges, error, &headers, stop_requested);
}
api_error get_range_and_headers(const host_config &hc, const std::string &path,
const std::uint64_t &dataSize, const http_parameters &parameters,
const std::string &encryption_token, std::vector<char> &data,
const http_ranges &ranges, json &error, http_headers &headers,
const bool &stop_requested) override {
return get_range(hc, path, dataSize, parameters, encryption_token, data, ranges, error,
&headers, stop_requested);
}
api_error get_raw(const std::string &path, const http_parameters &parameters,
std::vector<char> &data, json &error, const bool &stop_requested) override {
return get_raw(config_.get_host_config(), path, parameters, data, error, stop_requested);
}
api_error get_raw(const host_config &hc, const std::string &path,
const http_parameters &parameters, std::vector<char> &data, json &error,
const bool &stop_requested) override;
api_error post(const std::string &path, json &data, json &error) override {
return get_or_post(config_.get_host_config(), true, path, {}, data, error);
}
api_error post(const host_config &hc, const std::string &path, json &data, json &error) override {
return get_or_post(hc, true, path, {}, data, error);
}
api_error post(const std::string &path, const http_parameters &parameters, json &data,
json &error) override {
return get_or_post(config_.get_host_config(), true, path, parameters, data, error);
}
api_error post(const host_config &hc, const std::string &path, const http_parameters &parameters,
json &data, json &error) override {
return get_or_post(hc, true, path, parameters, data, error);
}
api_error post_file(const std::string &path, const std::string &source_path,
const http_parameters &parameters, json &data, json &error,
const bool &stop_requested) override {
return post_file(config_.get_host_config(), path, source_path, parameters, data, error,
stop_requested);
}
api_error post_file(const host_config &hc, const std::string &path,
const std::string &source_path, const http_parameters &parameters, json &data,
json &error, const bool &stop_requested) override;
api_error post_multipart_file(const std::string &path, const std::string &file_name,
const std::string &source_path, const std::string &encryption_token,
json &data, json &error, const bool &stop_requested) override {
return post_multipart_file(config_.get_host_config(), path, file_name, source_path,
encryption_token, data, error, stop_requested);
}
api_error post_multipart_file(const host_config &hc, const std::string &path,
const std::string &file_name, const std::string &source_path,
const std::string &encryption_token, json &data, json &error,
const bool &stop_requested) override;
bool tus_upload(host_config hc, const std::string &source_path, const std::string &file_name,
std::uint64_t file_size, const std::string &location, std::string &skylink,
const bool &stop_requested, utils::encryption::encrypting_reader *reader);
bool tus_upload_create(host_config hc, const std::string &file_name,
const std::uint64_t &file_size, std::string &location);
};
} // namespace repertory
#endif // INCLUDE_COMM_CURL_CURL_COMM_HPP_

View File

@ -0,0 +1,45 @@
/*
Copyright <2018-2022> <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_COMM_CURL_CURL_RESOLVER_HPP_
#define INCLUDE_COMM_CURL_CURL_RESOLVER_HPP_
#include "common.hpp"
namespace repertory {
class curl_resolver final {
public:
curl_resolver() = delete;
curl_resolver(const curl_resolver &) noexcept = delete;
curl_resolver(curl_resolver &&) noexcept = delete;
curl_resolver &operator=(const curl_resolver &) noexcept = delete;
curl_resolver &operator=(curl_resolver &&) noexcept = delete;
public:
curl_resolver(CURL *handle, std::vector<std::string> items, const bool &ignore_root = false);
~curl_resolver();
private:
std::vector<std::string> items_;
struct curl_slist *host_list_ = nullptr;
};
} // namespace repertory
#endif // INCLUDE_COMM_CURL_CURL_RESOLVER_HPP_

View File

@ -0,0 +1,41 @@
/*
Copyright <2018-2022> <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_COMM_CURL_MULTI_REQUEST_HPP_
#define INCLUDE_COMM_CURL_MULTI_REQUEST_HPP_
#include "common.hpp"
namespace repertory {
class multi_request final {
public:
multi_request(CURL *curl_handle, const bool &stop_requested);
~multi_request();
private:
CURL *curl_handle_;
const bool &stop_requested_;
CURLM *multi_handle_;
public:
void get_result(CURLcode &curl_code, long &http_code);
};
} // namespace repertory
#endif // INCLUDE_COMM_CURL_MULTI_REQUEST_HPP_

View File

@ -0,0 +1,43 @@
/*
Copyright <2018-2022> <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_COMM_CURL_SESSION_MANAGER_HPP_
#define INCLUDE_COMM_CURL_SESSION_MANAGER_HPP_
#include "common.hpp"
#include "types/repertory.hpp"
namespace repertory {
class app_config;
class session_manager final {
private:
std::string session_;
std::uint64_t session_count_ = 0u;
std::mutex session_mutex_;
public:
bool create_auth_session(CURL *&curl_handle, const app_config &config, host_config hc,
std::string &session);
void release_auth_session(const app_config &config, host_config hc, const std::string &session);
void update_auth_session(CURL *curl_handle, const app_config &config, const host_config &hc);
};
} // namespace repertory
#endif // INCLUDE_COMM_CURL_SESSION_MANAGER_HPP_

107
include/comm/i_comm.hpp Normal file
View File

@ -0,0 +1,107 @@
/*
Copyright <2018-2022> <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_COMM_I_COMM_HPP_
#define INCLUDE_COMM_I_COMM_HPP_
#include "common.hpp"
#include "types/repertory.hpp"
namespace repertory {
class i_comm {
INTERFACE_SETUP(i_comm);
public:
virtual api_error get(const std::string &path, json &data, json &error) = 0;
virtual api_error get(const host_config &hc, const std::string &path, json &data,
json &error) = 0;
virtual api_error get(const std::string &path, const http_parameters &parameters, json &data,
json &error) = 0;
virtual api_error get(const host_config &hc, const std::string &path,
const http_parameters &parameters, json &data, json &error) = 0;
virtual api_error get_range(const std::string &path, const std::uint64_t &data_size,
const http_parameters &parameters,
const std::string &encryption_token, std::vector<char> &data,
const http_ranges &ranges, json &error,
const bool &stop_requested) = 0;
virtual api_error get_range(const host_config &hc, const std::string &path,
const std::uint64_t &data_size, const http_parameters &parameters,
const std::string &encryption_token, std::vector<char> &data,
const http_ranges &ranges, json &error,
const bool &stop_requested) = 0;
virtual api_error get_range_and_headers(const std::string &path, const std::uint64_t &data_size,
const http_parameters &parameters,
const std::string &encryption_token,
std::vector<char> &data, const http_ranges &ranges,
json &error, http_headers &headers,
const bool &stop_requested) = 0;
virtual api_error get_range_and_headers(const host_config &hc, const std::string &path,
const std::uint64_t &data_size,
const http_parameters &parameters,
const std::string &encryption_token,
std::vector<char> &data, const http_ranges &ranges,
json &error, http_headers &headers,
const bool &stop_requested) = 0;
virtual api_error get_raw(const std::string &path, const http_parameters &parameters,
std::vector<char> &data, json &error, const bool &stop_requested) = 0;
virtual api_error get_raw(const host_config &hc, const std::string &path,
const http_parameters &parameters, std::vector<char> &data, json &error,
const bool &stop_requested) = 0;
virtual api_error post(const std::string &path, json &data, json &error) = 0;
virtual api_error post(const host_config &hc, const std::string &path, json &data,
json &error) = 0;
virtual api_error post(const std::string &path, const http_parameters &parameters, json &data,
json &error) = 0;
virtual api_error post(const host_config &hc, const std::string &path,
const http_parameters &parameters, json &data, json &error) = 0;
virtual api_error post_file(const std::string &path, const std::string &sourcePath,
const http_parameters &parameters, json &data, json &error,
const bool &stop_requested) = 0;
virtual api_error post_file(const host_config &hc, const std::string &path,
const std::string &sourcePath, const http_parameters &parameters,
json &data, json &error, const bool &stop_requested) = 0;
virtual api_error post_multipart_file(const std::string &path, const std::string &file_name,
const std::string &source_path,
const std::string &encryption_token, json &data,
json &error, const bool &stop_requested) = 0;
virtual api_error post_multipart_file(const host_config &hc, const std::string &path,
const std::string &file_name,
const std::string &source_path,
const std::string &encryption_token, json &data,
json &error, const bool &stop_requested) = 0;
};
} // namespace repertory
#endif // INCLUDE_COMM_I_COMM_HPP_

View File

@ -0,0 +1,92 @@
/*
Copyright <2018-2022> <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_COMM_I_S3_COMM_HPP_
#define INCLUDE_COMM_I_S3_COMM_HPP_
#if defined(REPERTORY_ENABLE_S3)
#include "common.hpp"
#include "types/repertory.hpp"
namespace repertory {
class i_provider;
class i_s3_comm {
INTERFACE_SETUP(i_s3_comm);
public:
typedef std::function<std::string(const std::string &api_path)> get_api_file_token_callback;
typedef std::function<std::string()> get_key_callback;
typedef std::function<std::string(const std::string &key, const std::string &object_name)>
get_name_callback;
typedef std::function<std::uint64_t()> get_size_callback;
typedef std::function<std::string()> get_token_callback;
typedef std::function<api_error(const std::string &key)> set_key_callback;
public:
virtual api_error create_bucket(const std::string &api_path) = 0;
virtual bool exists(const std::string &api_path, const get_key_callback &get_key) const = 0;
virtual void get_bucket_name_and_object_name(const std::string &api_path,
const get_key_callback &get_key,
std::string &bucket_name,
std::string &object_name) const = 0;
virtual std::size_t
get_directory_item_count(const std::string &api_path,
const meta_provider_callback &meta_provider) const = 0;
virtual api_error get_directory_items(const std::string &api_path,
const meta_provider_callback &meta_provider,
directory_item_list &list) const = 0;
virtual s3_config get_s3_config() = 0;
virtual s3_config get_s3_config() const = 0;
virtual api_error get_file(const std::string &api_path, const get_key_callback &get_key,
const get_name_callback &get_name, const get_token_callback &get_token,
api_file &file) const = 0;
virtual api_error get_file_list(const get_api_file_token_callback &get_api_file_token,
const get_name_callback &get_name, api_file_list &list) const = 0;
virtual bool is_online() const = 0;
virtual api_error read_file_bytes(const std::string &api_path, const std::size_t &size,
const std::uint64_t &offset, std::vector<char> &data,
const get_key_callback &get_key,
const get_size_callback &get_size,
const get_token_callback &get_token,
const bool &stop_requested) const = 0;
virtual api_error remove_file(const std::string &api_path, const get_key_callback &get_key) = 0;
virtual api_error remove_bucket(const std::string &api_path) = 0;
virtual api_error rename_file(const std::string &api_path, const std::string &new_api_path) = 0;
virtual api_error upload_file(const std::string &api_path, const std::string &source_path,
const std::string &encryption_token,
const get_key_callback &get_key, const set_key_callback &set_key,
const bool &stop_requested) = 0;
};
} // namespace repertory
#endif // REPERTORY_ENABLE_S3
#endif // INCLUDE_COMM_I_S3_COMM_HPP_

View File

@ -0,0 +1,89 @@
/*
Copyright <2018-2022> <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_COMM_PACKET_CLIENT_POOL_HPP_
#define INCLUDE_COMM_PACKET_CLIENT_POOL_HPP_
#include "common.hpp"
#include "comm/packet/packet.hpp"
#include "types/repertory.hpp"
namespace repertory {
class client_pool final {
public:
typedef std::function<packet::error_type()> worker_callback;
typedef std::function<void(const packet::error_type &result)> worker_complete_callback;
private:
class pool final {
private:
struct work_item final {
work_item(const worker_callback &worker, const worker_complete_callback &worker_complete)
: work(worker), work_complete(worker_complete) {}
worker_callback work;
worker_complete_callback work_complete;
};
struct work_queue final {
std::mutex mutex;
std::condition_variable notify;
std::deque<std::shared_ptr<work_item>> queue;
};
public:
explicit pool(const std::uint8_t &pool_size);
~pool() { shutdown(); }
private:
std::vector<std::unique_ptr<work_queue>> pool_queues_;
std::vector<std::thread> pool_threads_;
bool shutdown_ = false;
std::atomic<std::uint8_t> thread_index_;
public:
void execute(const std::uint64_t &thread_id, const worker_callback &worker,
const worker_complete_callback &worker_complete);
void shutdown();
};
public:
explicit client_pool(const std::uint8_t &pool_size = 10u)
: pool_size_(pool_size ? pool_size : 10u) {}
~client_pool() { shutdown(); }
private:
const std::uint8_t pool_size_;
std::unordered_map<std::string, std::shared_ptr<pool>> pool_lookup_;
std::mutex pool_mutex_;
bool shutdown_ = false;
public:
void execute(const std::string &client_id, const std::uint64_t &thread_id,
const worker_callback &worker, const worker_complete_callback &worker_complete);
void remove_client(const std::string &client_id);
void shutdown();
};
} // namespace repertory
#endif // INCLUDE_COMM_PACKET_CLIENT_POOL_HPP_

View File

@ -0,0 +1,213 @@
/*
Copyright <2018-2022> <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_COMM_PACKET_PACKET_HPP_
#define INCLUDE_COMM_PACKET_PACKET_HPP_
#include "common.hpp"
#include "types/remote.hpp"
#include "types/repertory.hpp"
namespace repertory {
#define DECODE_OR_RETURN(p, value) \
if ((ret = (p)->decode(value)) != 0) \
return ret
#define DECODE_OR_IGNORE(p, value) \
if (ret == 0) \
ret = (p)->decode(value)
class packet final {
public:
typedef std::int32_t error_type;
public:
packet() = default;
explicit packet(std::vector<char> buffer) : buffer_(std::move(buffer)) {}
explicit packet(std::vector<char> &&buffer) : buffer_(std::move(buffer)) {}
packet(const packet &p) noexcept : buffer_(p.buffer_), decode_offset_(p.decode_offset_) {}
packet(packet &&p) noexcept : buffer_(std::move(p.buffer_)), decode_offset_(p.decode_offset_) {}
private:
std::vector<char> buffer_;
std::size_t decode_offset_ = 0u;
public:
static int decode_json(packet &response, json &json_data);
public:
void clear();
char *current_pointer() {
return (decode_offset_ < buffer_.size()) ? &buffer_[decode_offset_] : nullptr;
}
const char *current_pointer() const {
return (decode_offset_ < buffer_.size()) ? &buffer_[decode_offset_] : nullptr;
}
error_type decode(std::string &data);
error_type decode(std::wstring &data);
error_type decode(void *buffer, const size_t &size);
error_type decode(void *&ptr);
error_type decode(std::int8_t &i);
error_type decode(std::uint8_t &i);
error_type decode(std::int16_t &i);
error_type decode(std::uint16_t &i);
error_type decode(std::int32_t &i);
error_type decode(std::uint32_t &i);
error_type decode(std::int64_t &i);
error_type decode(std::uint64_t &i);
error_type decode(remote::open_flags &i) {
return decode(reinterpret_cast<std::uint32_t &>(i));
}
error_type decode(remote::setattr_x &i);
error_type decode(remote::stat &i);
error_type decode(remote::statfs &i);
error_type decode(remote::statfs_x &i);
error_type decode(remote::file_info &i);
error_type decrypt(const std::string &token);
void encode(const void *buffer, const std::size_t &size, bool should_reserve = true);
void encode(char *str) { encode(std::string(str ? str : "")); }
void encode(const char *str) { encode(std::string(str ? str : "")); }
void encode(const std::string &str);
void encode(wchar_t *str);
void encode(const wchar_t *str);
void encode(const std::wstring &str);
void encode(void *ptr) {
encode(static_cast<std::uint64_t>(reinterpret_cast<std::uintptr_t>(ptr)));
}
void encode(std::int8_t i);
void encode(std::uint8_t i);
void encode(std::int16_t i);
void encode(std::uint16_t i);
void encode(std::int32_t i);
void encode(std::uint32_t i);
void encode(std::int64_t i);
void encode(std::uint64_t i);
void encode(remote::open_flags i) { encode(static_cast<std::uint32_t>(i)); }
void encode(remote::setattr_x i);
void encode(remote::stat i);
void encode(remote::statfs i, bool should_reserve = true);
void encode(remote::statfs_x i);
void encode(remote::file_info i);
void encode_top(const void *buffer, const std::size_t &size, bool should_reserve = true);
void encode_top(const std::string &str);
void encode_top(const std::wstring &str);
void encode_top(void *ptr) {
encode_top(static_cast<std::uint64_t>(reinterpret_cast<std::uintptr_t>(ptr)));
}
void encode_top(std::int8_t i);
void encode_top(std::uint8_t i);
void encode_top(std::int16_t i);
void encode_top(std::uint16_t i);
void encode_top(std::int32_t i);
void encode_top(std::uint32_t i);
void encode_top(std::int64_t i);
void encode_top(std::uint64_t i);
void encode_top(remote::open_flags i) { encode_top(static_cast<std::uint32_t>(i)); }
void encode_top(remote::setattr_x i);
void encode_top(remote::stat i);
void encode_top(remote::statfs i, bool should_reserve = true);
void encode_top(remote::statfs_x i);
void encode_top(remote::file_info i);
void encrypt(const std::string &token);
std::uint32_t get_size() const { return static_cast<std::uint32_t>(buffer_.size()); }
void transfer_into(std::vector<char> &buffer);
public:
packet &operator=(const std::vector<char> &buffer) noexcept;
packet &operator=(std::vector<char> &&buffer) noexcept;
packet &operator=(const packet &p) noexcept;
packet &operator=(packet &&p) noexcept;
char &operator[](const size_t &index) { return buffer_[index]; }
const char &operator[](const size_t &index) const { return buffer_.at(index); }
};
typedef packet packet;
} // namespace repertory
#endif // INCLUDE_COMM_PACKET_PACKET_HPP_

View File

@ -0,0 +1,84 @@
/*
Copyright <2018-2022> <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_COMM_PACKET_PACKET_CLIENT_HPP_
#define INCLUDE_COMM_PACKET_PACKET_CLIENT_HPP_
#include "common.hpp"
#include "comm/packet/packet.hpp"
using boost::asio::ip::tcp;
namespace repertory {
class packet_client final {
private:
struct client {
client(boost::asio::io_context &ctx) : nonce(""), socket(ctx) {}
std::string nonce;
tcp::socket socket;
};
public:
packet_client(std::string host_name_or_ip, const std::uint8_t &max_connections,
const std::uint16_t &port, const std::uint16_t &receive_timeout,
const std::uint16_t &send_timeout, std::string encryption_token);
~packet_client();
private:
boost::asio::io_context io_context_;
const std::string host_name_or_ip_;
const std::uint8_t max_connections_;
const std::uint16_t port_;
const std::uint16_t receive_timeout_;
const std::uint16_t send_timeout_;
const std::string encryption_token_;
std::string unique_id_;
bool allow_connections_ = true;
boost::asio::ip::basic_resolver<boost::asio::ip::tcp>::results_type resolve_results_;
std::mutex clients_mutex_;
std::vector<std::shared_ptr<client>> clients_;
private:
void close(client &c) const;
void close_all();
bool connect(client &c);
std::shared_ptr<client> get_client();
void put_client(std::shared_ptr<client> &c);
packet::error_type read_packet(client &c, packet &response);
void resolve();
public:
packet::error_type send(const std::string &method, std::uint32_t &service_flags);
packet::error_type send(const std::string &method, packet &request, std::uint32_t &service_flags);
packet::error_type send(const std::string &method, packet &request, packet &response,
std::uint32_t &service_flags);
};
} // namespace repertory
#endif // INCLUDE_COMM_PACKET_PACKET_CLIENT_HPP_

View File

@ -0,0 +1,90 @@
/*
Copyright <2018-2022> <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_COMM_PACKET_PACKET_SERVER_HPP_
#define INCLUDE_COMM_PACKET_PACKET_SERVER_HPP_
#include "common.hpp"
#include "comm/packet/client_pool.hpp"
#include "utils/utils.hpp"
using namespace boost::asio;
using boost::asio::ip::tcp;
namespace repertory {
class packet_server final {
public:
typedef std::function<void(const std::string &clientId)> closed_callback;
typedef client_pool::worker_complete_callback message_complete_callback;
typedef std::function<void(const std::uint32_t &service_flags, const std::string &client_id,
const std::uint64_t &thread_id, const std::string &method,
packet *request, packet &response,
message_complete_callback message_complete)>
message_handler_callback;
public:
packet_server(const std::uint16_t &port, std::string token, std::uint8_t pool_size,
closed_callback closed, message_handler_callback message_handler);
~packet_server();
private:
struct connection {
connection(boost::asio::io_service &io_service, tcp::acceptor &acceptor)
: socket(io_service), acceptor(acceptor) {}
tcp::socket socket;
tcp::acceptor &acceptor;
std::vector<char> buffer;
std::string client_id;
std::string nonce;
void generate_nonce() { nonce = utils::generate_random_string(256u); }
};
private:
const std::string encryption_token_;
closed_callback closed_;
message_handler_callback message_handler_;
boost::asio::io_context io_context_;
std::unique_ptr<std::thread> server_thread_;
std::vector<std::thread> service_threads_;
std::recursive_mutex connection_mutex_;
std::unordered_map<std::string, std::uint32_t> connection_lookup_;
private:
void add_client(connection &c, const std::string &client_id);
void initialize(const uint16_t &port, uint8_t pool_size);
void listen_for_connection(tcp::acceptor &acceptor);
void on_accept(std::shared_ptr<connection> c, boost::system::error_code ec);
void read_header(std::shared_ptr<connection> c);
void read_packet(std::shared_ptr<connection> c, const std::uint32_t &data_size);
void remove_client(connection &c);
void send_response(std::shared_ptr<connection> c, const packet::error_type &result,
packet &response);
};
} // namespace repertory
#endif // INCLUDE_COMM_PACKET_PACKET_SERVER_HPP_

324
include/common.hpp Normal file
View File

@ -0,0 +1,324 @@
/*
Copyright <2018-2022> <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_COMMON_HPP_
#define INCLUDE_COMMON_HPP_
#ifdef _WIN32
#include <WinSock2.h>
#include <ws2tcpip.h>
#include <Windows.h>
#include <Shlwapi.h>
#include <ShlObj.h>
#include <ciso646>
#include <direct.h>
#include <fcntl.h>
#include <io.h>
#else
#define FUSE_USE_VERSION 29
#include <climits>
#include <dirent.h>
#include <fcntl.h>
#include <grp.h>
#include <libgen.h>
#include <pwd.h>
#include <sys/file.h>
#include <sys/stat.h>
#ifdef __linux__
#include <sys/statfs.h>
#endif
#include <unistd.h>
#ifdef HAS_SETXATTR
#include <sys/types.h>
#include <sys/xattr.h>
#endif
#ifdef __APPLE__
#include <libproc.h>
#include <sys/attr.h>
#include <sys/vnode.h>
#endif
#if __APPLE__
#include <sys/mount.h>
#include <sys/statvfs.h>
#endif
#if __linux__
#include <utils/uuid++.hh>
#else
#include <uuid/uuid.h>
#endif
#endif
#include <algorithm>
#include <atomic>
#include <boost/archive/text_iarchive.hpp>
#include <boost/archive/text_oarchive.hpp>
#include <boost/asio.hpp>
#include <boost/bind/bind.hpp>
#include <boost/dynamic_bitset.hpp>
#include <boost/dynamic_bitset/serialization.hpp>
#include <boost/endian/conversion.hpp>
#include <boost/filesystem.hpp>
#include <boost/serialization/vector.hpp>
#include <chacha.h>
#include <chachapoly.h>
#include <chrono>
#include <codecvt>
#include <condition_variable>
#include <curl/curl.h>
#include <curl/multi.h>
#include <deque>
#include <fstream>
#include <future>
#include <iostream>
#include <jsonrp.hpp>
#include <limits>
#include <microhttpd.h>
#include <httpserver.hpp>
#include <mutex>
#if !IS_DEBIAN9_DISTRO && HAS_STD_OPTIONAL
#include <optional>
#else
#include <utils/optional.h>
#endif
#include <files.h>
#include <hex.h>
#include <json.hpp>
#include <osrng.h>
#include <random>
#include <regex>
#include <rocksdb/db.h>
#include <sha.h>
#include <sstream>
#include <string>
#include <thread>
#include <ttmath.h>
#include <type_traits>
#include <unordered_map>
#include <vector>
#ifdef _WIN32
#include <sddl.h>
#include <winfsp/winfsp.hpp>
#else
#include <fuse/fuse.h>
#endif
#if defined(REPERTORY_ENABLE_S3)
#include <aws/core/Aws.h>
#include <aws/core/auth/AWSCredentials.h>
#include <aws/core/utils/logging/AWSLogging.h>
#include <aws/core/utils/logging/DefaultLogSystem.h>
#include <aws/s3/S3Client.h>
#include <aws/s3/model/CopyObjectRequest.h>
#include <aws/s3/model/CreateBucketRequest.h>
#include <aws/s3/model/DeleteBucketRequest.h>
#include <aws/s3/model/DeleteObjectRequest.h>
#include <aws/s3/model/GetObjectRequest.h>
#include <aws/s3/model/HeadObjectRequest.h>
#include <aws/s3/model/ListObjectsRequest.h>
#include <aws/s3/model/Object.h>
#include <aws/s3/model/PutObjectRequest.h>
#endif
using namespace std::chrono_literals;
using json = nlohmann::json;
const std::string &get_repertory_git_revision();
const std::string &get_repertory_version();
#ifdef _WIN32
#ifdef CreateDirectory
#undef CreateDirectory
#endif
#ifdef CreateFile
#undef CreateFile
#endif
#ifdef DeleteFile
#undef DeleteFile
#endif
#ifdef RemoveDirectory
#undef RemoveDirectory
#endif
#endif
#define MIN_REMOTE_VERSION "2.0.0"
#define MIN_SIA_VERSION "1.4.1"
#define MIN_SP_VERSION "1.4.1.2"
#define REPERTORY_CONFIG_VERSION 0ull
#define REPERTORY "repertory"
#define REPERTORY_DATA_NAME "repertory2"
#define REPERTORY_W L"repertory"
#define NANOS_PER_SECOND 1000000000L
#ifdef _WIN32
#define REPERTORY_INVALID_HANDLE INVALID_HANDLE_VALUE
#define REPERTORY_API_INVALID_HANDLE static_cast<std::uint64_t>(-1)
#define OSHandle HANDLE
#else
#define REPERTORY_INVALID_HANDLE -1
#define REPERTORY_API_INVALID_HANDLE REPERTORY_INVALID_HANDLE
#define OSHandle int
#endif
#ifndef _WIN32
#ifdef __APPLE__
#define G_PREFIX "org"
#define G_KAUTH_FILESEC_XATTR G_PREFIX ".apple.system.Security"
#define A_PREFIX "com"
#define A_KAUTH_FILESEC_XATTR A_PREFIX ".apple.system.Security"
#define XATTR_APPLE_PREFIX "com.apple."
#endif
#ifndef XATTR_NAME_MAX
#define XATTR_NAME_MAX 255 /* # chars in an extended attribute name */
#endif
#ifndef XATTR_SIZE_MAX
#define XATTR_SIZE_MAX 65536
#endif
#endif
#if __APPLE__
#define pread64 pread
#define pwrite64 pwrite
#endif
#define WINFSP_ALLOCATION_UNIT UINT64(4096U)
#ifdef _WIN32
#define UTIME_NOW ((1l << 30) - 1l)
#define UTIME_OMIT ((1l << 30) - 2l)
#define CONVERT_STATUS_NOT_IMPLEMENTED(e) e
#else
#define VOID void
#define PVOID VOID *
typedef PVOID HANDLE;
#define WCHAR wchar_t
#define PWSTR WCHAR *
#define BOOLEAN std::uint8_t
#define UINT16 std::uint16_t
#define UINT32 std::uint32_t
#define PUINT32 UINT32 *
#define UINT64 std::uint64_t
#define SIZE_T std::uint64_t
#define DWORD std::uint32_t
#define FILE_ATTRIBUTE_READONLY 0x00000001
#define FILE_ATTRIBUTE_HIDDEN 0x00000002
#define FILE_ATTRIBUTE_SYSTEM 0x00000004
#define FILE_ATTRIBUTE_DIRECTORY 0x00000010
#define FILE_ATTRIBUTE_ARCHIVE 0x00000020
#define FILE_ATTRIBUTE_DEVICE 0x00000040
#define FILE_ATTRIBUTE_NORMAL 0x00000080
#define FILE_ATTRIBUTE_TEMPORARY 0x00000100
#define FILE_ATTRIBUTE_SPARSE_FILE 0x00000200
#define FILE_ATTRIBUTE_REPARSE_POINT 0x00000400
#define FILE_ATTRIBUTE_COMPRESSED 0x00000800
#define FILE_ATTRIBUTE_OFFLINE 0x00001000
#define FILE_ATTRIBUTE_NOT_CONTENT_INDEXED 0x00002000
#define FILE_ATTRIBUTE_ENCRYPTED 0x00004000
#define FILE_ATTRIBUTE_INTEGRITY_STREAM 0x00008000
#define FILE_ATTRIBUTE_VIRTUAL 0x00010000
#define FILE_ATTRIBUTE_NO_SCRUB_DATA 0x00020000
#define FILE_ATTRIBUTE_EA 0x00040000
#define FILE_ATTRIBUTE_PINNED 0x00080000
#define FILE_ATTRIBUTE_UNPINNED 0x00100000
#define FILE_ATTRIBUTE_RECALL_ON_OPEN 0x00040000
#define FILE_ATTRIBUTE_RECALL_ON_DATA_ACCESS 0x00400000
#define FILE_DIRECTORY_FILE 0x00000001
#define FILE_EXECUTE (0x0020)
#define FILE_GENERIC_EXECUTE (0x00020000L | 0x0080 | 0x0020 | 0x00100000L)
#define GENERIC_READ (0x80000000L)
#define GENERIC_WRITE (0x40000000L)
#define GENERIC_EXECUTE (0x20000000L)
#define GENERIC_ALL (0x10000000L)
#define INVALID_FILE_ATTRIBUTES ((DWORD)-1)
#define MAX_PATH 260
#define STATUS_SUCCESS std::int32_t(0)
#define STATUS_ACCESS_DENIED std::int32_t(0xC0000022L)
#define STATUS_DEVICE_BUSY std::int32_t(0x80000011L)
#define STATUS_DEVICE_INSUFFICIENT_RESOURCES std::int32_t(0xC0000468L)
#define STATUS_DIRECTORY_NOT_EMPTY std::int32_t(0xC0000101L)
#define STATUS_FILE_IS_A_DIRECTORY std::int32_t(0xC00000BAL)
#define STATUS_FILE_TOO_LARGE std::int32_t(0xC0000904L)
#define STATUS_INSUFFICIENT_RESOURCES std::int32_t(0xC000009AL)
#define STATUS_INTERNAL_ERROR std::int32_t(0xC00000E5L)
#define STATUS_INVALID_ADDRESS std::int32_t(0xC0000141L)
#define STATUS_INVALID_HANDLE std::int32_t(0xC0000006L)
#define STATUS_INVALID_IMAGE_FORMAT std::int32_t(0xC000007BL)
#define STATUS_INVALID_PARAMETER std::int32_t(0xC000000DL)
#define STATUS_NO_MEMORY std::int32_t(0xC0000017L)
#define STATUS_NOT_IMPLEMENTED std::int32_t(0xC0000002L)
#define STATUS_OBJECT_NAME_EXISTS std::int32_t(0x40000000L)
#define STATUS_OBJECT_NAME_NOT_FOUND std::int32_t(0xC0000034L)
#define STATUS_OBJECT_PATH_INVALID std::int32_t(0xC0000039L)
#define STATUS_UNEXPECTED_IO_ERROR std::int32_t(0xC00000E9L)
#define CONVERT_STATUS_NOT_IMPLEMENTED(e) \
((std::int32_t(e) == STATUS_NOT_IMPLEMENTED) ? -ENOTSUP : e)
namespace Fsp::FileSystemBase {
enum {
FspCleanupDelete = 0x01,
FspCleanupSetAllocationSize = 0x02,
FspCleanupSetArchiveBit = 0x10,
FspCleanupSetLastAccessTime = 0x20,
FspCleanupSetLastWriteTime = 0x40,
FspCleanupSetChangeTime = 0x80
};
struct FSP_FSCTL_FILE_INFO {
UINT32 FileAttributes;
UINT32 ReparseTag;
UINT64 AllocationSize;
UINT64 FileSize;
UINT64 CreationTime;
UINT64 LastAccessTime;
UINT64 LastWriteTime;
UINT64 ChangeTime;
UINT64 IndexNumber;
UINT32 HardLinks;
UINT32 EaSize;
};
typedef FSP_FSCTL_FILE_INFO FileInfo;
} // namespace Fsp::FileSystemBase
#endif
using namespace Fsp;
#define INTERFACE_SETUP(name) \
public: \
name(const name &) noexcept = delete; \
name(name &&) noexcept = delete; \
name &operator=(const name &) noexcept = delete; \
name &operator=(name &&) noexcept = delete; \
\
protected: \
name() = default; \
\
public: \
virtual ~name() = default
#endif // INCLUDE_COMMON_HPP_

101
include/db/directory_db.hpp Normal file
View File

@ -0,0 +1,101 @@
/*
Copyright <2018-2022> <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_DB_DIRECTORY_DB_HPP_
#define INCLUDE_DB_DIRECTORY_DB_HPP_
#include "common.hpp"
#include "app_config.hpp"
#include "types/repertory.hpp"
#include "utils/rocksdb_utils.hpp"
namespace repertory {
class directory_db final {
private:
class directory_tree final {
private:
std::unordered_map<std::string, std::vector<std::string>> sub_directory_lookup_;
public:
void add_path(const std::string &api_path, const std::vector<std::string> &files,
rocksdb::DB &db);
std::size_t get_count(const std::string &api_path) const;
std::vector<std::string> get_directories() const;
std::vector<std::string> get_sub_directories(const std::string &api_path) const;
bool is_directory(const std::string &api_path) const;
bool remove_directory(const std::string &api_path, rocksdb::DB &db,
const bool &allow_remove_root = false);
};
public:
explicit directory_db(const app_config &config);
public:
~directory_db();
private:
mutable std::recursive_mutex directory_mutex_;
std::unique_ptr<rocksdb::DB> db_;
directory_tree tree_;
const std::string DIRDB_NAME = "directory_db";
private:
json get_directory_data(const std::string &api_path) const;
public:
api_error create_directory(const std::string &api_path, const bool &create_always = false);
api_error create_file(const std::string &api_path);
std::uint64_t get_directory_item_count(const std::string &api_path) const;
api_error get_file(const std::string &api_path, api_file &file,
api_file_provider_callback api_file_provider) const;
api_error get_file_list(api_file_list &list, api_file_provider_callback api_file_provider) const;
std::size_t get_sub_directory_count(const std::string &api_path) const;
std::uint64_t get_total_item_count() const;
bool is_directory(const std::string &api_path) const;
bool is_file(const std::string &api_path) const;
void populate_directory_files(const std::string &api_path,
const meta_provider_callback &meta_provider,
directory_item_list &list) const;
void populate_sub_directories(const std::string &api_path,
const meta_provider_callback &meta_provider,
directory_item_list &list) const;
api_error remove_directory(const std::string &api_path, const bool &allow_remove_root = false);
bool remove_file(const std::string &api_path);
api_error rename_file(const std::string &from_api_path, const std::string &to_api_path);
};
} // namespace repertory
#endif // INCLUDE_DB_DIRECTORY_DB_HPP_

81
include/db/meta_db.hpp Normal file
View File

@ -0,0 +1,81 @@
/*
Copyright <2018-2022> <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_DB_META_DB_HPP_
#define INCLUDE_DB_META_DB_HPP_
#include "common.hpp"
#include "app_config.hpp"
#include "types/repertory.hpp"
#include "utils/rocksdb_utils.hpp"
namespace repertory {
class meta_db final {
public:
explicit meta_db(const app_config &config);
public:
~meta_db();
private:
std::unique_ptr<rocksdb::DB> db_;
std::unique_ptr<rocksdb::ColumnFamilyHandle> default_family_;
std::unique_ptr<rocksdb::ColumnFamilyHandle> source_family_;
std::unique_ptr<rocksdb::ColumnFamilyHandle> keys_family_;
const std::string METADB_NAME = "meta_db";
private:
api_error get_item_meta_json(const std::string &api_path, json &json_data) const;
void release_resources();
public:
std::shared_ptr<rocksdb::Iterator> create_iterator(const bool &source_family);
api_error get_api_path_from_key(const std::string &key, std::string &api_path) const;
api_error get_api_path_from_source(const std::string &source_path, std::string &api_path) const;
api_error get_item_meta(const std::string &api_path, api_meta_map &meta) const;
api_error get_item_meta(const std::string &api_path, const std::string &key,
std::string &value) const;
bool get_item_meta_exists(const std::string &api_path) const;
std::vector<std::string> get_pinned_files() const;
bool get_source_path_exists(const std::string &source_path) const;
void remove_item_meta(const std::string &api_path);
api_error remove_item_meta(const std::string &api_path, const std::string &key);
api_error rename_item_meta(const std::string &source_path, const std::string &from_api_path,
const std::string &to_api_path);
api_error set_item_meta(const std::string &api_path, const std::string &key,
const std::string &value);
api_error set_item_meta(const std::string &api_path, const api_meta_map &meta);
api_error set_source_path(const std::string &api_path, const std::string &source_path);
};
} // namespace repertory
#endif // INCLUDE_DB_META_DB_HPP_

63
include/db/retry_db.hpp Normal file
View File

@ -0,0 +1,63 @@
/*
Copyright <2018-2022> <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_DB_RETRY_DB_HPP_
#define INCLUDE_DB_RETRY_DB_HPP_
#include "common.hpp"
#include "app_config.hpp"
#include "events/events.hpp"
#include "events/event_system.hpp"
#include "types/repertory.hpp"
#include "utils/path_utils.hpp"
#include "utils/rocksdb_utils.hpp"
namespace repertory {
class retry_db final {
public:
typedef std::function<bool(const std::string &api_path)> process_callback;
public:
explicit retry_db(const app_config &config);
~retry_db();
private:
std::unique_ptr<rocksdb::DB> db_;
bool paused_ = false;
std::mutex processing_mutex_;
const std::string ROCKS_DB_NAME = "retry_db";
public:
bool exists(const std::string &api_path) const;
void pause();
bool process_all(const process_callback &process);
void remove(const std::string &api_path);
void rename(const std::string &from_api_path, const std::string &to_api_path);
void resume();
void set(const std::string &api_path);
};
} // namespace repertory
#endif // INCLUDE_DB_RETRY_DB_HPP_

View File

@ -0,0 +1,78 @@
/*
Copyright <2018-2022> <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_DOWNLOAD_BUFFERED_READER_HPP_
#define INCLUDE_DOWNLOAD_BUFFERED_READER_HPP_
#include "common.hpp"
#include "types/repertory.hpp"
namespace repertory {
class app_config;
class buffered_reader final {
public:
buffered_reader(const app_config &config, const filesystem_item &fsi,
const api_reader_callback &api_reader, const std::size_t &chunk_size,
const std::size_t &total_chunks, const std::size_t &start_chunk);
~buffered_reader();
private:
const filesystem_item &fsi_;
const api_reader_callback &api_reader_;
const std::size_t chunk_size_;
const std::size_t total_chunks_;
boost::dynamic_bitset<> ring_state_;
api_error error_ = api_error::success;
std::unique_ptr<std::vector<char>> first_chunk_data_;
std::unique_ptr<std::vector<char>> last_chunk_data_;
std::size_t read_chunk_index_ = 0u;
std::mutex read_mutex_;
std::condition_variable read_notify_;
std::size_t read_offset_ = 0u;
bool reset_reader_ = false;
std::vector<std::vector<char>> ring_data_;
std::unique_ptr<std::thread> reader_thread_;
bool stop_requested_ = false;
std::mutex write_mutex_;
std::size_t write_chunk_index_ = 0u;
private:
bool is_active() const { return not stop_requested_ && (error_ == api_error::success); }
void reader_thread();
public:
std::size_t get_chunk_size() const { return chunk_size_; }
void get_first_chunk(std::vector<char> *&data) { data = first_chunk_data_.get(); }
void get_last_chunk(std::vector<char> *&data) { data = last_chunk_data_.get(); }
bool has_first_chunk() const { return static_cast<bool>(first_chunk_data_); }
bool has_last_chunk() const { return static_cast<bool>(last_chunk_data_); }
void notify_stop_requested();
api_error read_chunk(const std::size_t &chunk_index, std::vector<char> &data);
};
} // namespace repertory
#endif // INCLUDE_DOWNLOAD_BUFFERED_READER_HPP_

View File

@ -0,0 +1,99 @@
/*
Copyright <2018-2022> <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_DOWNLOAD_DIRECT_DOWNLOAD_HPP_
#define INCLUDE_DOWNLOAD_DIRECT_DOWNLOAD_HPP_
#include "common.hpp"
#include "download/i_download.hpp"
#include "types/repertory.hpp"
namespace repertory {
class buffered_reader;
class app_config;
class direct_download final : public virtual i_download {
public:
direct_download(const app_config &config, filesystem_item fsi,
const api_reader_callback &api_reader, const std::uint64_t &handle);
~direct_download() override;
private:
const app_config &config_;
const filesystem_item fsi_;
const api_reader_callback &api_reader_;
const std::uint64_t handle_;
api_error error_ = api_error::success;
std::unique_ptr<buffered_reader> buffered_reader_;
bool disable_download_end_ = false;
bool download_end_notified_ = false;
double progress_ = 0.0;
std::mutex read_mutex_;
bool stop_requested_ = false;
private:
bool is_active() const { return not stop_requested_ && (error_ == api_error::success); }
void notify_download_end();
void set_api_error(const api_error &error);
public:
api_error allocate(const std::uint64_t & /*handle*/, const std::uint64_t & /*size*/,
const allocator_callback & /*allocator*/,
const completer_callback & /*completer*/) override {
return api_error::not_implemented;
}
api_error download_all() override { return api_error::not_implemented; }
api_error get_result() const override { return error_; }
std::string get_source_path() const override { return ""; }
void get_state_information(filesystem_item &, std::size_t &, std::size_t &,
boost::dynamic_bitset<> &, boost::dynamic_bitset<> &) override {}
bool get_write_supported() const override { return false; }
void notify_stop_requested() override;
bool pause() override { return false; }
api_error read_bytes(const std::uint64_t &, std::size_t read_size,
const std::uint64_t &read_offset, std::vector<char> &data) override;
void reset_timeout(const bool &) override {}
void resume() override {}
void set_api_path(const std::string &) override {}
void set_disable_download_end(const bool &disable) override { disable_download_end_ = disable; }
api_error write_bytes(const std::uint64_t &, const std::uint64_t &, std::vector<char>,
std::size_t &bytes_written,
const completer_callback & /*completer*/) override {
bytes_written = 0u;
return api_error::not_implemented;
}
};
} // namespace repertory
#endif // INCLUDE_DOWNLOAD_DIRECT_DOWNLOAD_HPP_

View File

@ -0,0 +1,191 @@
/*
Copyright <2018-2022> <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_DOWNLOAD_DOWNLOAD_HPP_
#define INCLUDE_DOWNLOAD_DOWNLOAD_HPP_
#include "common.hpp"
#include "app_config.hpp"
#include "download/i_download.hpp"
#include "types/repertory.hpp"
#include "utils/native_file.hpp"
namespace repertory {
class i_open_file_table;
class download final : public virtual i_download {
private:
struct active_chunk {
explicit active_chunk(std::thread worker) : worker(std::move(worker)) {}
std::thread worker;
std::mutex mutex;
std::condition_variable notify;
};
typedef std::shared_ptr<active_chunk> active_chunk_ptr;
struct read_data {
read_data(std::vector<char> &data, const std::uint64_t &offset)
: complete(false), data(data), offset(offset) {}
bool complete;
std::vector<char> &data;
const std::uint64_t offset;
std::mutex mutex;
std::condition_variable notify;
};
typedef std::shared_ptr<read_data> read_data_ptr;
struct write_data {
write_data(const std::size_t &chunk, std::vector<char> data, const std::uint64_t &offset)
: chunk_index(chunk), data(std::move(data)), offset(offset) {}
write_data(const std::uint64_t &offset, std::vector<char> data)
: chunk_index(0u), data(std::move(data)), offset(offset), from_read(false) {}
std::size_t chunk_index;
std::vector<char> data;
const std::uint64_t offset;
bool from_read = true;
bool complete = false;
std::mutex mutex;
std::condition_variable notify;
std::size_t written = 0u;
};
typedef std::shared_ptr<write_data> write_data_ptr;
public:
download(const app_config &config, filesystem_item &fsi, const api_reader_callback &api_reader,
const std::size_t &chunk_size, i_open_file_table &oft);
download(const app_config &config, filesystem_item &fsi, const api_reader_callback &api_reader,
const std::size_t &chunk_size, std::size_t &last_chunk_size,
boost::dynamic_bitset<> &read_state, boost::dynamic_bitset<> &write_state,
i_open_file_table &oft);
~download() override;
private:
// Constructor initialization
const app_config &config_;
filesystem_item fsi_;
const api_reader_callback &api_reader_;
i_open_file_table &oft_;
const std::size_t chunk_size_;
boost::dynamic_bitset<> read_chunk_state_;
std::size_t last_chunk_size_;
boost::dynamic_bitset<> write_chunk_state_;
// Default initialization
bool auto_close_ = false;
std::unordered_map<std::size_t, active_chunk_ptr> active_chunks_;
api_error error_ = api_error::success;
std::vector<std::thread> background_workers_;
std::size_t current_chunk_index_ = 0u;
bool disable_download_end_ = false;
std::unique_ptr<std::thread> io_thread_;
std::uint64_t open_file_handle_ = REPERTORY_API_INVALID_HANDLE;
bool paused_ = false;
bool processed_ = false;
std::condition_variable processed_notify_;
double progress_ = 0.0;
std::size_t read_offset_ = 0u;
std::deque<read_data_ptr> read_queue_;
native_file_ptr read_write_file_;
std::mutex read_write_mutex_;
std::condition_variable read_write_notify_;
bool stop_requested_ = false;
std::chrono::system_clock::time_point timeout_ =
std::chrono::system_clock::now() +
std::chrono::seconds(config_.get_chunk_downloader_timeout_secs());
std::deque<write_data_ptr> write_queue_;
private:
void create_active_chunk(std::size_t chunk_index);
void download_chunk(std::size_t chunk_index, bool inactive_only);
bool get_complete() const;
bool get_timeout_enabled() const;
void handle_active_chunk_complete(std::size_t chunk_index, unique_mutex_lock &lock);
void initialize_download(filesystem_item &fsi, const bool &delete_existing);
void io_data_worker();
void notify_progress();
void process_download_complete(unique_mutex_lock &lock);
void process_read_queue(unique_mutex_lock &lock);
void process_timeout(unique_mutex_lock &lock);
void process_write_queue(unique_mutex_lock &lock);
void read_ahead_worker();
void read_behind_worker();
void read_end_worker();
void shutdown(unique_mutex_lock &lock);
void wait_for_io(unique_mutex_lock &lock);
public:
api_error allocate(const std::uint64_t &handle, const std::uint64_t &size,
const allocator_callback &allocator,
const completer_callback &completer) override;
api_error download_all() override;
api_error get_result() const override { return error_; }
std::string get_source_path() const override { return fsi_.source_path; }
void get_state_information(filesystem_item &fsi, std::size_t &chunk_size,
std::size_t &last_chunk_size, boost::dynamic_bitset<> &read_state,
boost::dynamic_bitset<> &write_state) override;
bool get_write_supported() const override { return true; }
bool is_active() const { return not read_chunk_state_.all(); }
void notify_stop_requested() override;
bool pause() override;
api_error read_bytes(const std::uint64_t &handle, std::size_t read_size,
const std::uint64_t &read_offset, std::vector<char> &data) override;
void reset_timeout(const bool &) override;
void resume() override;
void set_api_path(const std::string &api_path) override;
void set_disable_download_end(const bool &disable) override { disable_download_end_ = disable; }
api_error write_bytes(const std::uint64_t &handle, const std::uint64_t &write_offset,
std::vector<char> data, std::size_t &bytes_written,
const completer_callback &completer) override;
};
} // namespace repertory
#endif // INCLUDE_DOWNLOAD_DOWNLOAD_HPP_

View File

@ -0,0 +1,102 @@
/*
Copyright <2018-2022> <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_DOWNLOAD_DOWNLOAD_MANAGER_HPP_
#define INCLUDE_DOWNLOAD_DOWNLOAD_MANAGER_HPP_
#include "common.hpp"
#include "download/i_download.hpp"
#include "download/i_download_manager.hpp"
#include "events/event_system.hpp"
namespace repertory {
class app_config;
class download_end;
class filesystem_item_handle_closed;
class i_open_file_table;
class download_manager final : public virtual i_download_manager {
E_CONSUMER();
public:
download_manager(const app_config &config, api_reader_callback api_reader,
const bool &force_download = false);
~download_manager() override;
private:
const app_config &config_;
const api_reader_callback api_reader_;
bool force_download_;
i_open_file_table *oft_ = nullptr;
mutable std::recursive_mutex download_mutex_;
std::unordered_map<std::string, std::unordered_map<std::uint64_t, download_ptr>> download_lookup_;
std::recursive_mutex start_stop_mutex_;
bool stop_requested_ = true;
std::unique_ptr<rocksdb::DB> restore_db_;
private:
bool contains_handle(const std::string &api_path, const std::uint64_t &handle) const;
download_ptr get_download(std::uint64_t handle, filesystem_item &fsi,
const bool &write_Supported);
void handle_download_end(const download_end &de);
void on_handle_closed(const filesystem_item_handle_closed &handle_closed);
void reset_timeout(const std::string &api_path, const bool &file_closed);
void start_incomplete();
public:
api_error allocate(const std::uint64_t &handle, filesystem_item &fsi, const std::uint64_t &size,
const i_download::allocator_callback &allocator) override;
bool contains_restore(const std::string &api_path) const override;
api_error download_file(const std::uint64_t &handle, filesystem_item &fsi) override;
std::size_t get_download_count() const { return download_lookup_.size(); }
std::string get_source_path(const std::string &api_path) const;
bool is_processing(const std::string &api_path) const override;
bool pause_download(const std::string &api_path) override;
api_error read_bytes(const std::uint64_t &handle, filesystem_item &fsi, std::size_t read_size,
const std::uint64_t &read_offset, std::vector<char> &data) override;
void rename_download(const std::string &from_api_path, const std::string &to_api_path) override;
api_error resize(const std::uint64_t &handle, filesystem_item &fsi,
const std::uint64_t &size) override;
void resume_download(const std::string &api_path) override;
void start(i_open_file_table *oft);
void stop();
api_error write_bytes(const std::uint64_t &handle, filesystem_item &fsi,
const std::uint64_t &write_offset, std::vector<char> data,
std::size_t &bytes_written) override;
};
} // namespace repertory
#endif // INCLUDE_DOWNLOAD_DOWNLOAD_MANAGER_HPP_

View File

@ -0,0 +1,85 @@
/*
Copyright <2018-2022> <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_DOWNLOAD_EVENTS_HPP_
#define INCLUDE_DOWNLOAD_EVENTS_HPP_
#include "common.hpp"
#include "events/events.hpp"
#include "types/repertory.hpp"
namespace repertory {
// clang-format off
E_SIMPLE2(download_begin, normal, true,
std::string, api_path, ap, E_STRING,
std::string, dest_path, dest, E_STRING
);
E_SIMPLE4(download_end, normal, true,
std::string, api_path, ap, E_STRING,
std::string, dest_path, dest, E_STRING,
std::uint64_t, handle, handle, E_FROM_UINT64,
api_error, result, result, E_FROM_API_FILE_ERROR
);
E_SIMPLE2(download_paused, normal, true,
std::string, api_path, ap, E_STRING,
std::string, dest_path, dest, E_STRING
);
E_SIMPLE3(download_progress, normal, true,
std::string, api_path, ap, E_STRING,
std::string, dest_path, dest, E_STRING,
double, progress, prog, E_DOUBLE_PRECISE
);
E_SIMPLE2(download_restored, normal, true,
std::string, api_path, ap, E_STRING,
std::string, dest_path, dest, E_STRING
);
E_SIMPLE3(download_restore_failed, error, true,
std::string, api_path, ap, E_STRING,
std::string, dest_path, dest, E_STRING,
std::string, error, err, E_STRING
);
E_SIMPLE2(download_resumed, normal, true,
std::string, api_path, ap, E_STRING,
std::string, dest_path, dest, E_STRING
);
E_SIMPLE2(download_stored, normal, true,
std::string, api_path, ap, E_STRING,
std::string, dest_path, dest, E_STRING
);
E_SIMPLE3(download_store_failed, error, true,
std::string, api_path, ap, E_STRING,
std::string, dest_path, dest, E_STRING,
std::string, error, err, E_STRING
);
E_SIMPLE2(download_timeout, warn, true,
std::string, api_path, ap, E_STRING,
std::string, dest_path, dest, E_STRING
);
// clang-format on
} // namespace repertory
#endif // INCLUDE_DOWNLOAD_EVENTS_HPP_

View File

@ -0,0 +1,76 @@
/*
Copyright <2018-2022> <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_DOWNLOAD_I_DOWNLOAD_HPP_
#define INCLUDE_DOWNLOAD_I_DOWNLOAD_HPP_
#include "common.hpp"
#include "types/repertory.hpp"
namespace repertory {
class i_download {
INTERFACE_SETUP(i_download);
public:
typedef std::function<api_error()> allocator_callback;
typedef std::function<void(std::uint64_t old_size, std::uint64_t new_size, bool changed)>
completer_callback;
public:
virtual api_error allocate(const std::uint64_t &handle, const std::uint64_t &size,
const allocator_callback &allocator,
const completer_callback &completer) = 0;
virtual api_error download_all() = 0;
virtual api_error get_result() const = 0;
virtual std::string get_source_path() const = 0;
virtual void get_state_information(filesystem_item &fsi, std::size_t &chunk_size,
std::size_t &last_chunk_size,
boost::dynamic_bitset<> &read_state,
boost::dynamic_bitset<> &write_state) = 0;
virtual bool get_write_supported() const = 0;
virtual void notify_stop_requested() = 0;
virtual bool pause() = 0;
virtual api_error read_bytes(const std::uint64_t &handle, std::size_t read_size,
const std::uint64_t &read_offset, std::vector<char> &data) = 0;
virtual void reset_timeout(const bool &file_closed) = 0;
virtual void resume() = 0;
virtual void set_api_path(const std::string &api_path) = 0;
virtual void set_disable_download_end(const bool &disable) = 0;
virtual api_error write_bytes(const std::uint64_t &handle, const std::uint64_t &write_offset,
std::vector<char> data, std::size_t &bytes_written,
const completer_callback &completer) = 0;
};
typedef std::shared_ptr<i_download> download_ptr;
} // namespace repertory
#endif // INCLUDE_DOWNLOAD_I_DOWNLOAD_HPP_

View File

@ -0,0 +1,61 @@
/*
Copyright <2018-2022> <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_DOWNLOAD_I_DOWNLOAD_MANAGER_HPP_
#define INCLUDE_DOWNLOAD_I_DOWNLOAD_MANAGER_HPP_
#include "common.hpp"
#include "download/i_download.hpp"
#include "types/repertory.hpp"
namespace repertory {
class i_download_manager {
INTERFACE_SETUP(i_download_manager);
public:
virtual api_error allocate(const std::uint64_t &handle, filesystem_item &fsi,
const std::uint64_t &size,
const i_download::allocator_callback &allocator) = 0;
virtual bool contains_restore(const std::string &api_path) const = 0;
virtual api_error download_file(const std::uint64_t &handle, filesystem_item &fsi) = 0;
virtual bool is_processing(const std::string &api_path) const = 0;
virtual bool pause_download(const std::string &api_path) = 0;
virtual api_error read_bytes(const std::uint64_t &handle, filesystem_item &fsi,
std::size_t read_size, const std::uint64_t &read_offset,
std::vector<char> &data) = 0;
virtual void rename_download(const std::string &from_api_path,
const std::string &to_api_path) = 0;
virtual api_error resize(const std::uint64_t &handle, filesystem_item &fsi,
const std::uint64_t &size) = 0;
virtual void resume_download(const std::string &api_path) = 0;
virtual api_error write_bytes(const std::uint64_t &handle, filesystem_item &fsi,
const std::uint64_t &write_offset, std::vector<char> data,
std::size_t &bytes_written) = 0;
};
} // namespace repertory
#endif // INCLUDE_DOWNLOAD_I_DOWNLOAD_MANAGER_HPP_

View File

@ -0,0 +1,87 @@
/*
Copyright <2018-2022> <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_DOWNLOAD_READER_POOL_HPP_
#define INCLUDE_DOWNLOAD_READER_POOL_HPP_
#include "common.hpp"
#include "types/repertory.hpp"
namespace repertory {
class reader_pool final {
public:
typedef std::function<void(api_error error)> completed_callback;
private:
struct pool_work_item {
pool_work_item(std::string api_path, const std::size_t &read_size,
const std::uint64_t &read_offset, std::vector<char> &data,
completed_callback completed)
: api_path(std::move(api_path)), read_size(read_size), read_offset(read_offset), data(data),
completed(completed) {}
std::string api_path;
std::size_t read_size;
std::uint64_t read_offset;
std::vector<char> &data;
completed_callback completed;
};
public:
reader_pool(const std::size_t &pool_size, const api_reader_callback &api_reader)
: pool_size_(pool_size), api_reader_(api_reader) {
start();
}
~reader_pool() { stop(); }
private:
const std::size_t pool_size_;
const api_reader_callback &api_reader_;
bool paused_ = false;
bool restart_active_ = false;
bool stop_requested_ = false;
std::mutex work_mutex_;
std::condition_variable work_notify_;
std::deque<std::shared_ptr<pool_work_item>> work_queue_;
std::vector<std::thread> work_threads_;
std::uint16_t active_count_ = 0u;
private:
void process_work_item(pool_work_item &work);
void start();
void stop();
void wait_for_resume(unique_mutex_lock &lock);
public:
void pause();
void queue_read_bytes(const std::string &api_path, const std::size_t &read_size,
const std::uint64_t &read_offset, std::vector<char> &data,
completed_callback completed);
void restart();
void resume();
};
} // namespace repertory
#endif // INCLUDE_DOWNLOAD_READER_POOL_HPP_

View File

@ -0,0 +1,136 @@
/*
Copyright <2018-2022> <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_DOWNLOAD_RING_DOWNLOAD_HPP_
#define INCLUDE_DOWNLOAD_RING_DOWNLOAD_HPP_
#include "common.hpp"
#include "download/i_download.hpp"
#include "utils/native_file.hpp"
#include "types/repertory.hpp"
namespace repertory {
class buffered_reader;
class app_config;
class ring_download final : public virtual i_download {
private:
struct io_action {
io_action(std::mutex &mtx, std::condition_variable &cv, std::function<void()> action)
: mutex(mtx), notify(cv), action(action) {}
std::mutex &mutex;
std::condition_variable &notify;
std::function<void()> action;
};
public:
ring_download(const app_config &config, filesystem_item fsi,
const api_reader_callback &api_reader, const std::uint64_t &handle,
const std::size_t &chunk_size, const std::size_t &ring_buffer_size);
~ring_download() override;
private:
const app_config &config_;
const filesystem_item fsi_;
const api_reader_callback &api_reader_;
const std::uint64_t handle_;
const std::size_t chunk_size_;
boost::dynamic_bitset<> ring_state_;
const std::size_t total_chunks_ = 0u;
api_error error_ = api_error::success;
native_file_ptr buffer_file_;
std::string buffer_file_path_;
buffered_reader *buffered_reader_ = nullptr;
bool disable_download_end_ = false;
std::size_t head_chunk_index_ = 0ull;
std::mutex io_mutex_;
std::condition_variable io_notify_;
std::deque<std::unique_ptr<io_action>> io_queue_;
std::unique_ptr<std::thread> io_thread_;
std::size_t read_chunk_ = 0ull;
std::unique_ptr<std::thread> buffer_thread_;
std::mutex read_mutex_;
std::condition_variable read_notify_;
bool stop_requested_ = false;
std::size_t write_chunk_ = 0ull;
std::mutex write_mutex_;
private:
void buffer_thread(std::size_t start_chunk_index);
void io_thread();
bool is_active() const { return not stop_requested_ && (error_ == api_error::success); }
bool queue_io_item(std::mutex &m, std::condition_variable &cv, const bool &is_read,
std::function<void()> action);
void read(std::size_t read_chunk_index, std::size_t read_size, std::size_t read_offset,
std::vector<char> &data);
void set_api_error(const api_error &error);
void start(const std::size_t &start_chunk_index);
void stop();
public:
api_error allocate(const std::uint64_t & /*handle*/, const std::uint64_t & /*size*/,
const allocator_callback & /*allocator*/,
const completer_callback & /*completer*/) override {
return api_error::not_implemented;
}
api_error download_all() override { return api_error::not_implemented; }
api_error get_result() const override { return error_; }
std::string get_source_path() const override { return buffer_file_path_; }
void get_state_information(filesystem_item &, std::size_t &, std::size_t &,
boost::dynamic_bitset<> &, boost::dynamic_bitset<> &) override {}
bool get_write_supported() const override { return false; }
void notify_stop_requested() override;
bool pause() override { return false; }
api_error read_bytes(const std::uint64_t &, std::size_t read_size,
const std::uint64_t &read_offset, std::vector<char> &data) override;
void reset_timeout(const bool &) override {}
void resume() override {}
void set_api_path(const std::string &) override {}
void set_disable_download_end(const bool &disable) override { disable_download_end_ = disable; }
api_error write_bytes(const std::uint64_t &, const std::uint64_t &, std::vector<char>,
std::size_t &bytes_written,
const completer_callback & /*completer*/) override {
bytes_written = 0u;
return api_error::not_implemented;
}
};
} // namespace repertory
#endif // INCLUDE_DOWNLOAD_RING_DOWNLOAD_HPP_

View File

@ -0,0 +1,41 @@
/*
Copyright <2018-2022> <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_DOWNLOAD_UTILS_HPP_
#define INCLUDE_DOWNLOAD_UTILS_HPP_
#include "common.hpp"
#include "app_config.hpp"
namespace repertory::utils::download {
template <typename event_type>
void notify_progress(const app_config &config, const std::string &api_path,
const std::string &source_path, const double &current, const double &total,
double &progress) {
if (config.get_event_level() >= event_type::level) {
const double next_progress = (current / total) * 100.0;
if ((next_progress == 0.0) || (next_progress >= (progress + 0.2)) ||
((next_progress == 100.00) && (next_progress != progress))) {
progress = next_progress;
event_system::instance().raise<event_type>(api_path, source_path, progress);
}
}
}
} // namespace repertory::utils::download
#endif // INCLUDE_DOWNLOAD_UTILS_HPP_

View File

@ -0,0 +1,68 @@
/*
Copyright <2018-2022> <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_DRIVES_DIRECTORY_CACHE_HPP_
#define INCLUDE_DRIVES_DIRECTORY_CACHE_HPP_
#include "common.hpp"
namespace repertory {
class directory_iterator;
class directory_cache final {
public:
typedef std::function<void(directory_iterator &iterator)> execute_callback;
private:
struct open_directory {
directory_iterator *iterator;
std::chrono::system_clock::time_point last_update = std::chrono::system_clock::now();
};
public:
directory_cache() = default;
~directory_cache() { stop(); }
private:
std::unordered_map<std::string, open_directory> directory_lookup_;
std::recursive_mutex directory_mutex_;
bool is_shutdown_ = true;
std::unique_ptr<std::thread> refresh_thread_;
std::mutex shutdown_mutex_;
std::condition_variable shutdown_notify_;
private:
void refresh_thread();
public:
bool execute_action(const std::string &api_path, const execute_callback &execute);
directory_iterator *remove_directory(const std::string &api_path);
void remove_directory(directory_iterator *iterator);
void set_directory(const std::string &api_path, directory_iterator *iterator);
void start();
void stop();
};
} // namespace repertory
#endif // INCLUDE_DRIVES_DIRECTORY_CACHE_HPP_

View File

@ -0,0 +1,71 @@
/*
Copyright <2018-2022> <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_DRIVES_DIRECTORY_ITERATOR_HPP_
#define INCLUDE_DRIVES_DIRECTORY_ITERATOR_HPP_
#include "common.hpp"
#include "types/remote.hpp"
#include "types/repertory.hpp"
namespace repertory {
class directory_iterator final {
public:
#ifndef _WIN32
typedef std::function<void(const std::string &api_path, const std::uint64_t &file_size,
const api_meta_map &meta, const bool &directory, struct stat *st)>
populate_stat_callback;
#endif
public:
explicit directory_iterator(directory_item_list list) : items_(std::move(list)) {}
directory_iterator(const directory_iterator &iterator) noexcept : items_(iterator.items_) {}
directory_iterator(directory_iterator &&iterator) noexcept : items_(std::move(iterator.items_)) {}
private:
directory_item_list items_;
public:
#ifndef _WIN32
int fill_buffer(const remote::file_offset &offset, fuse_fill_dir_t filler_function, void *buffer,
populate_stat_callback populate_stat);
#endif
int get(const std::size_t &offset, std::string &item);
std::size_t get_count() const { return items_.size(); }
api_error get_directory_item(const std::size_t &offset, directory_item &di);
api_error get_directory_item(const std::string &api_path, directory_item &di);
int get_json(const std::size_t &offset, json &item);
std::size_t get_next_directory_offset(const std::string &api_path) const;
public:
directory_iterator &operator=(const directory_iterator &iterator) noexcept;
directory_iterator &operator=(directory_iterator &&iterator) noexcept;
directory_iterator &operator=(directory_item_list list) noexcept;
};
} // namespace repertory
#endif // INCLUDE_DRIVES_DIRECTORY_ITERATOR_HPP_

View File

@ -0,0 +1,59 @@
/*
Copyright <2018-2022> <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_DRIVES_EVICTION_HPP_
#define INCLUDE_DRIVES_EVICTION_HPP_
#include "common.hpp"
namespace repertory {
class app_config;
class i_open_file_table;
class i_provider;
class eviction final {
public:
eviction(i_provider &provider, const app_config &config, i_open_file_table &oft)
: provider_(provider), config_(config), oft_(oft) {}
~eviction() = default;
private:
i_provider &provider_;
const app_config &config_;
i_open_file_table &oft_;
bool stop_requested_ = false;
std::mutex start_stop_mutex_;
std::condition_variable stop_notify_;
std::unique_ptr<std::thread> eviction_thread_;
std::mutex eviction_mutex_;
private:
void check_items_thread();
bool check_minimum_requirements(const std::string &file_path);
std::deque<std::string> get_filtered_cached_files();
public:
void start();
void stop();
};
} // namespace repertory
#endif // INCLUDE_DRIVES_EVICTION_HPP_

View File

@ -0,0 +1,39 @@
/*
Copyright <2018-2022> <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_DRIVES_FUSE_EVENTS_HPP_
#define INCLUDE_DRIVES_FUSE_EVENTS_HPP_
#include "common.hpp"
#include "events/event_system.hpp"
namespace repertory {
// clang-format off
E_SIMPLE3(fuse_event, debug, true,
std::string, function, func, E_STRING,
std::string, api_path, ap, E_STRING,
int, result, res, E_FROM_INT32
);
E_SIMPLE1(fuse_args_parsed, normal, true,
std::string, arguments, args, E_STRING
);
// clang-format on
} // namespace repertory
#endif // INCLUDE_DRIVES_FUSE_EVENTS_HPP_

View File

@ -0,0 +1,506 @@
/*
Copyright <2018-2022> <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_DRIVES_FUSE_FUSE_BASE_HPP_
#define INCLUDE_DRIVES_FUSE_FUSE_BASE_HPP_
#ifndef _WIN32
#include "common.hpp"
#include "events/event_system.hpp"
#include "drives/fuse/i_fuse_drive.hpp"
#include "utils/path_utils.hpp"
namespace repertory {
class app_config;
class i_provider;
class fuse_base : public i_fuse_drive {
E_CONSUMER();
public:
explicit fuse_base(app_config &config_);
virtual ~fuse_base();
protected:
app_config &config_;
private:
std::string mount_location_;
protected:
bool atime_enabled_ = true;
bool console_enabled_ = false;
std::optional<gid_t> forced_gid_;
std::optional<uid_t> forced_uid_;
std::optional<mode_t> forced_umask_;
private:
static fuse_base &instance();
private:
// clang-format off
struct fuse_operations fuse_ops_ {
.getattr = fuse_base::getattr_,
.readlink = nullptr, // int (*readlink) (const char *, char *, size_t);
.getdir = nullptr, // int (*getdir) (const char *, fuse_dirh_t, fuse_dirfil_t);
.mknod = nullptr, // int (*mknod) (const char *, mode_t, dev_t);
.mkdir = fuse_base::mkdir_,
.unlink = fuse_base::unlink_,
.rmdir = fuse_base::rmdir_,
.symlink = nullptr, // int (*symlink) (const char *, const char *);
.rename = fuse_base::rename_,
.link = nullptr, // int (*link) (const char *, const char *);
.chmod = fuse_base::chmod_,
.chown = fuse_base::chown_,
.truncate = fuse_base::truncate_,
.utime = nullptr, // int (*utime) (const char *, struct utimbuf *);
.open = fuse_base::open_,
.read = fuse_base::read_,
.write = fuse_base::write_,
#ifdef __APPLE__
.statfs = nullptr,
#else // __APPLE__
.statfs = fuse_base::statfs_,
#endif // __APPLE__
.flush = nullptr, // int (*flush) (const char *, struct fuse_file_info *);
.release = fuse_base::release_,
.fsync = fuse_base::fsync_,
#if HAS_SETXATTR
.setxattr = fuse_base::setxattr_,
.getxattr = fuse_base::getxattr_,
.listxattr = fuse_base::listxattr_,
.removexattr = fuse_base::removexattr_,
#else // HAS_SETXATTR
.setxattr = nullptr,
.getxattr = nullptr,
.listxattr = nullptr,
.removexattr = nullptr,
#endif // HAS_SETXATTR
.opendir = fuse_base::opendir_,
.readdir = fuse_base::readdir_,
.releasedir = fuse_base::releasedir_,
.fsyncdir = nullptr, // int (*fsyncdir) (const char *, int, struct fuse_file_info *);
.init = fuse_base::init_,
.destroy = fuse_base::destroy_,
.access = fuse_base::access_,
.create = fuse_base::create_,
.ftruncate = fuse_base::ftruncate_,
.fgetattr = fuse_base::fgetattr_,
.lock = nullptr, // int (*lock) (const char *, struct fuse_file_info *, int cmd, struct flock *);
.utimens = fuse_base::utimens_,
.bmap = nullptr, // int (*bmap) (const char *, size_t blocksize, uint64_t *idx);
.flag_nullpath_ok = 0,
.flag_nopath = 0,
.flag_utime_omit_ok = 1,
.flag_reserved = 0,
.ioctl = nullptr, // int (*ioctl) (const char *, int cmd, void *arg, struct fuse_file_info *, unsigned int flags, void *data);
.poll = nullptr, // int (*poll) (const char *, struct fuse_file_info *, struct fuse_pollhandle *ph, unsigned *reventsp);
.write_buf = nullptr, // int (*write_buf) (const char *, struct fuse_bufvec *buf, off_t off, struct fuse_file_info *);
.read_buf = nullptr, // int (*read_buf) (const char *, struct fuse_bufvec **bufp, size_t size, off_t off, struct fuse_file_info *);
.flock = nullptr, // int (*flock) (const char *, struct fuse_file_info *, int op);
.fallocate = fuse_base::fallocate_
};
// clang-format on
private:
int execute_callback(const std::string &function_name, const char *from, const char *to,
const std::function<api_error(const std::string &, const std::string &)> &cb,
const bool &disable_logging = false);
int execute_callback(const std::string &function_name, const char *path,
const std::function<api_error(const std::string &)> &cb,
const bool &disable_logging = false);
static void execute_void_callback(const std::string &function_name,
const std::function<void()> &cb);
static void *execute_void_pointer_callback(const std::string &function_name,
const std::function<void *()> &cb);
void raise_fuse_event(std::string function_name, const std::string &api_file, const int &ret,
const bool &disable_logging);
private:
static int access_(const char *path, int mask);
#ifdef __APPLE__
static int chflags_(const char *path, uint32_t flags);
#endif // __APPLE__
static int chmod_(const char *path, mode_t mode);
static int chown_(const char *path, uid_t uid, gid_t gid);
static int create_(const char *path, mode_t mode, struct fuse_file_info *fi);
static void destroy_(void *ptr);
static int fallocate_(const char *path, int mode, off_t offset, off_t length,
struct fuse_file_info *fi);
static int fgetattr_(const char *path, struct stat *st, struct fuse_file_info *fi);
#ifdef __APPLE__
static int fsetattr_x_(const char *path, struct setattr_x *attr, struct fuse_file_info *fi);
#endif // __APPLE__
static int fsync_(const char *path, int datasync, struct fuse_file_info *fi);
static int ftruncate_(const char *path, off_t size, struct fuse_file_info *fi);
static int getattr_(const char *path, struct stat *st);
#ifdef __APPLE__
static int getxtimes_(const char *path, struct timespec *bkuptime, struct timespec *crtime);
#endif // __APPLE__
static void *init_(struct fuse_conn_info *conn);
static int mkdir_(const char *path, mode_t mode);
static int open_(const char *path, struct fuse_file_info *fi);
static int opendir_(const char *path, struct fuse_file_info *fi);
static int read_(const char *path, char *buffer, size_t read_size, off_t read_offset,
struct fuse_file_info *fi);
static int readdir_(const char *path, void *buf, fuse_fill_dir_t fuse_fill_dir, off_t offset,
struct fuse_file_info *fi);
static int release_(const char *path, struct fuse_file_info *fi);
static int releasedir_(const char *path, struct fuse_file_info *fi);
static int rename_(const char *from, const char *to);
static int rmdir_(const char *path);
#ifdef HAS_SETXATTR
#ifdef __APPLE__
static int getxattr_(const char *path, const char *name, char *value, size_t size,
uint32_t position);
#else // __APPLE__
static int getxattr_(const char *path, const char *name, char *value, size_t size);
#endif // __APPLE__
static int listxattr_(const char *path, char *buffer, size_t size);
static int removexattr_(const char *path, const char *name);
#ifdef __APPLE__
static int setxattr_(const char *path, const char *name, const char *value, size_t size,
int flags, uint32_t position);
#else // __APPLE__
static int setxattr_(const char *path, const char *name, const char *value, size_t size,
int flags);
#endif // __APPLE__
#endif // HAS_SETXATTR
#ifdef __APPLE__
static int setattr_x_(const char *path, struct setattr_x *attr);
static int setbkuptime_(const char *path, const struct timespec *bkuptime);
static int setchgtime_(const char *path, const struct timespec *chgtime);
static int setcrtime_(const char *path, const struct timespec *crtime);
static int setvolname_(const char *volname);
static int statfs_x_(const char *path, struct statfs *stbuf);
#else // __APPLE__
static int statfs_(const char *path, struct statvfs *stbuf);
#endif // __APPLE__
static int truncate_(const char *path, off_t size);
static int unlink_(const char *path);
static int utimens_(const char *path, const struct timespec tv[2]);
static int write_(const char *path, const char *buffer, size_t write_size, off_t write_offset,
struct fuse_file_info *fi);
protected:
api_error check_access(const std::string &api_path, int mask) const;
api_error check_and_perform(const std::string &api_path, int parent_mask,
const std::function<api_error(api_meta_map &meta)> &action);
uid_t get_effective_uid() const;
gid_t get_effective_gid() const;
static api_error check_open_flags(const int &flags, const int &mask, const api_error &fail_error);
api_error check_owner(const api_meta_map &meta) const;
static api_error check_readable(const int &flags, const api_error &fail_error);
static api_error check_writeable(const int &flags, const api_error &fail_error);
#ifdef __APPLE__
static __uint32_t get_flags_from_meta(const api_meta_map &meta);
#endif // __APPLE__
static gid_t get_gid_from_meta(const api_meta_map &meta);
static mode_t get_mode_from_meta(const api_meta_map &meta);
static void get_timespec_from_meta(const api_meta_map &meta, const std::string &name,
struct timespec &ts);
static uid_t get_uid_from_meta(const api_meta_map &meta);
static void populate_stat(const std::string &api_path, const std::uint64_t &size_or_count,
const api_meta_map &meta, const bool &directory, i_provider &provider,
struct stat *st);
static void set_timespec_from_meta(const api_meta_map &meta, const std::string &name,
struct timespec &ts);
protected:
virtual api_error access_impl(std::string api_path, int mask) {
return check_access(api_path, mask);
}
#ifdef __APPLE__
virtual api_error chflags_impl(std::string /*api_path*/, uint32_t /*flags*/) {
return api_error::not_implemented;
}
#endif // __APPLE__
virtual api_error chmod_impl(std::string /*api_path*/, mode_t /*mode*/) {
return api_error::not_implemented;
}
virtual api_error chown_impl(std::string /*api_path*/, uid_t /*uid*/, gid_t /*gid*/) {
return api_error::not_implemented;
}
virtual api_error create_impl(std::string /*api_path*/, mode_t /*mode*/,
struct fuse_file_info * /*fi*/) {
return api_error::not_implemented;
}
virtual void destroy_impl(void * /*ptr*/) { return; }
virtual api_error fallocate_impl(std::string /*api_path*/, int /*mode*/, off_t /*offset*/,
off_t /*length*/, struct fuse_file_info * /*fi*/) {
return api_error::not_implemented;
}
virtual api_error fgetattr_impl(std::string /*api_path*/, struct stat * /*st*/,
struct fuse_file_info * /*fi*/) {
return api_error::not_implemented;
}
virtual api_error fsetattr_x_impl(std::string /*api_path*/, struct setattr_x * /*attr*/,
struct fuse_file_info * /*fi*/) {
return api_error::not_implemented;
}
virtual api_error fsync_impl(std::string /*api_path*/, int /*datasync*/,
struct fuse_file_info * /*fi*/) {
return api_error::not_implemented;
}
virtual api_error ftruncate_impl(std::string /*api_path*/, off_t /*size*/,
struct fuse_file_info * /*fi*/) {
return api_error::not_implemented;
}
virtual api_error getattr_impl(std::string /*api_path*/, struct stat * /*st*/) {
return api_error::not_implemented;
}
#ifdef __APPLE__
virtual api_error getxtimes_impl(std::string /*api_path*/, struct timespec * /*bkuptime*/,
struct timespec * /*crtime*/) {
return api_error::not_implemented;
}
#endif // __APPLE__
virtual void *init_impl(struct fuse_conn_info *conn);
virtual api_error mkdir_impl(std::string /*api_path*/, mode_t /*mode*/) {
return api_error::not_implemented;
}
virtual api_error open_impl(std::string /*api_path*/, struct fuse_file_info * /*fi*/) {
return api_error::not_implemented;
}
virtual api_error opendir_impl(std::string /*api_path*/, struct fuse_file_info * /*fi*/) {
return api_error::not_implemented;
}
virtual api_error read_impl(std::string /*api_path*/, char * /*buffer*/, size_t /*read_size*/,
off_t /*read_offset*/, struct fuse_file_info * /*fi*/,
std::size_t & /*bytes_read*/) {
return api_error::not_implemented;
}
virtual api_error readdir_impl(std::string /*api_path*/, void * /*buf*/,
fuse_fill_dir_t /*fuse_fill_dir*/, off_t /*offset*/,
struct fuse_file_info * /*fi*/) {
return api_error::not_implemented;
}
virtual api_error release_impl(std::string /*api_path*/, struct fuse_file_info * /*fi*/) {
return api_error::not_implemented;
}
virtual api_error releasedir_impl(std::string /*api_path*/, struct fuse_file_info * /*fi*/) {
return api_error::not_implemented;
}
virtual api_error rename_impl(std::string /*from_api_path*/, std::string /*to_api_path*/) {
return api_error::not_implemented;
}
virtual api_error rmdir_impl(std::string /*api_path*/) { return api_error::not_implemented; }
#ifdef HAS_SETXATTR
#ifdef __APPLE__
virtual api_error getxattr_impl(std::string /*api_path*/, const char * /*name*/, char * /*value*/,
size_t /*size*/, uint32_t /*position*/,
int & /*attribute_size*/) {
return api_error::not_implemented;
}
#else // __APPLE__
virtual api_error getxattr_impl(std::string /*api_path*/, const char * /*name*/, char * /*value*/,
size_t /*size*/, int & /*attribute_size*/) {
return api_error::not_implemented;
}
#endif // __APPLE__
virtual api_error listxattr_impl(std::string /*api_path*/, char * /*buffer*/, size_t /*size*/,
int & /*required_size*/, bool & /*return_size*/) {
return api_error::not_implemented;
}
virtual api_error removexattr_impl(std::string /*api_path*/, const char * /*name*/) {
return api_error::not_implemented;
}
#ifdef __APPLE__
virtual api_error setxattr_impl(std::string /*api_path*/, const char * /*name*/,
const char * /*value*/, size_t /*size*/, int /*flags*/,
uint32_t /*position*/) {
return api_error::not_implemented;
}
#else // __APPLE__
virtual api_error setxattr_impl(std::string /*api_path*/, const char * /*name*/,
const char * /*value*/, size_t /*size*/, int /*flags*/) {
return api_error::not_implemented;
}
#endif // __APPLE__
#endif // HAS_SETXATTR
#ifdef __APPLE__
virtual api_error setattr_x_impl(std::string /*api_path*/, struct setattr_x * /*attr*/) {
return api_error::not_implemented;
}
virtual api_error setbkuptime_impl(std::string /*api_path*/,
const struct timespec * /*bkuptime*/) {
return api_error::not_implemented;
}
virtual api_error setchgtime_impl(std::string /*api_path*/, const struct timespec * /*chgtime*/) {
return api_error::not_implemented;
}
virtual api_error setcrtime_impl(std::string /*api_path*/, const struct timespec * /*crtime*/) {
return api_error::not_implemented;
}
virtual api_error setvolname_impl(const char * /*volname*/) { return api_error::not_implemented; }
virtual api_error statfs_x_impl(std::string /*api_path*/, struct statfs * /*stbuf*/) {
return api_error::not_implemented;
}
#else // __APPLE__
virtual api_error statfs_impl(std::string /*api_path*/, struct statvfs * /*stbuf*/) {
return api_error::not_implemented;
}
#endif // __APPLE__
virtual api_error truncate_impl(std::string /*api_path*/, off_t /*size*/) {
return api_error::not_implemented;
}
virtual api_error unlink_impl(std::string /*api_path*/) { return api_error::not_implemented; }
virtual api_error utimens_impl(std::string /*api_path*/, const struct timespec /*tv*/[2]) {
return api_error::not_implemented;
}
virtual api_error write_impl(std::string /*api_path*/, const char * /*buffer*/,
size_t /*write_size*/, off_t /*write_offset*/,
struct fuse_file_info * /*fi*/, std::size_t & /*bytes_written*/) {
return api_error::not_implemented;
}
protected:
virtual void notify_fuse_args_parsed(const std::vector<std::string> & /*args*/) {}
virtual void notify_fuse_main_exit(int & /*ret*/) {}
virtual int parse_args(std::vector<std::string> &args);
#ifdef __APPLE__
api_error parse_xattr_parameters(const char *name, const uint32_t &position,
std::string &attribute_name, const std::string &api_path);
#else
api_error parse_xattr_parameters(const char *name, std::string &attribute_name,
const std::string &api_path);
#endif
#ifdef __APPLE__
api_error parse_xattr_parameters(const char *name, const char *value, size_t size,
const uint32_t &position, std::string &attribute_name,
const std::string &api_path);
#else
api_error parse_xattr_parameters(const char *name, const char *value, size_t size,
std::string &attribute_name, const std::string &api_path);
#endif
virtual int shutdown();
public:
static void display_options(int argc, char *argv[]);
static void display_version_information(int argc, char *argv[]);
api_error check_parent_access(const std::string &api_path, int mask) const override;
std::string get_mount_location() const { return mount_location_; }
int mount(std::vector<std::string> args);
};
} // namespace repertory
#endif // _WIN32
#endif // INCLUDE_DRIVES_FUSE_FUSE_BASE_HPP_

View File

@ -0,0 +1,217 @@
/*
Copyright <2018-2022> <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_DRIVES_FUSE_FUSE_DRIVE_HPP_
#define INCLUDE_DRIVES_FUSE_FUSE_DRIVE_HPP_
#ifndef _WIN32
#include "common.hpp"
#include "drives/fuse/fuse_base.hpp"
#include "drives/open_file_table.hpp"
namespace repertory {
class i_provider;
class app_config;
class console_consumer;
class directory_cache;
class download_manager;
class eviction;
class full_server;
class lock_data;
class logging_consumer;
namespace remote_fuse {
class remote_server;
}
class fuse_drive final : public fuse_base {
public:
fuse_drive(app_config &config, lock_data &lock_data, i_provider &provider);
~fuse_drive() override = default;
private:
lock_data &lock_data_;
i_provider &provider_;
std::shared_ptr<console_consumer> console_consumer_;
std::shared_ptr<directory_cache> directory_cache_;
std::shared_ptr<download_manager> download_manager_;
std::shared_ptr<eviction> eviction_;
std::shared_ptr<logging_consumer> logging_consumer_;
std::shared_ptr<open_file_table<open_file_data>> oft_;
std::shared_ptr<remote_fuse::remote_server> remote_server_;
std::shared_ptr<full_server> server_;
bool was_mounted_ = false;
protected:
#ifdef __APPLE__
api_error chflags_impl(std::string api_path, uint32_t flags) override;
#endif // __APPLE__
api_error chmod_impl(std::string api_path, mode_t mode) override;
api_error chown_impl(std::string api_path, uid_t uid, gid_t gid) override;
api_error create_impl(std::string api_path, mode_t mode, struct fuse_file_info *fi) override;
void destroy_impl(void *ptr) override;
api_error fallocate_impl(std::string api_path, int mode, off_t offset, off_t length,
struct fuse_file_info *fi) override;
api_error fgetattr_impl(std::string api_path, struct stat *st,
struct fuse_file_info *fi) override;
#ifdef __APPLE__
api_error fsetattr_x_impl(std::string api_path, struct setattr_x *attr,
struct fuse_file_info *fi) override;
#endif // __APPLE__
api_error fsync_impl(std::string api_path, int datasync, struct fuse_file_info *fi) override;
api_error ftruncate_impl(std::string api_path, off_t size, struct fuse_file_info *fi) override;
api_error getattr_impl(std::string api_path, struct stat *st) override;
#ifdef __APPLE__
api_error getxtimes_impl(std::string api_path, struct timespec *bkuptime,
struct timespec *crtime) override;
#endif // __APPLE__
void *init_impl(struct fuse_conn_info *conn) override;
api_error mkdir_impl(std::string api_path, mode_t mode) override;
api_error open_impl(std::string api_path, struct fuse_file_info *fi) override;
api_error opendir_impl(std::string api_path, struct fuse_file_info *fi) override;
api_error read_impl(std::string api_path, char *buffer, size_t read_size, off_t read_offset,
struct fuse_file_info *fi, std::size_t &bytes_read) override;
api_error readdir_impl(std::string api_path, void *buf, fuse_fill_dir_t fuse_fill_dir,
off_t offset, struct fuse_file_info *fi) override;
api_error release_impl(std::string api_path, struct fuse_file_info *fi) override;
api_error releasedir_impl(std::string api_path, struct fuse_file_info *fi) override;
api_error rename_impl(std::string from_api_path, std::string to_api_path) override;
api_error rmdir_impl(std::string api_path) override;
#ifdef HAS_SETXATTR
api_error getxattr_common(std::string api_path, const char *name, char *value, size_t size,
int &attribute_size, uint32_t *position);
#ifdef __APPLE__
api_error getxattr_impl(std::string api_path, const char *name, char *value, size_t size,
uint32_t position, int &attribute_size) override;
#else // __APPLE__
api_error getxattr_impl(std::string api_path, const char *name, char *value, size_t size,
int &attribute_size) override;
#endif // __APPLE__
api_error listxattr_impl(std::string api_path, char *buffer, size_t size, int &required_size,
bool &return_size) override;
api_error removexattr_impl(std::string api_path, const char *name) override;
#ifdef __APPLE__
api_error setxattr_impl(std::string api_path, const char *name, const char *value, size_t size,
int flags, uint32_t position) override;
#else // __APPLE__
api_error setxattr_impl(std::string api_path, const char *name, const char *value, size_t size,
int flags) override;
#endif // __APPLE__
#endif // HAS_SETXATTR
#ifdef __APPLE__
api_error setattr_x_impl(std::string api_path, struct setattr_x *attr) override;
api_error setbkuptime_impl(std::string api_path, const struct timespec *bkuptime) override;
api_error setchgtime_impl(std::string api_path, const struct timespec *chgtime) override;
api_error setcrtime_impl(std::string api_path, const struct timespec *crtime) override;
api_error setvolname_impl(const char *volname) override;
api_error statfs_x_impl(std::string api_path, struct statfs *stbuf) override;
#else // __APPLE__
api_error statfs_impl(std::string api_path, struct statvfs *stbuf) override;
#endif // __APPLE__
api_error truncate_impl(std::string api_path, off_t size) override;
api_error unlink_impl(std::string api_path) override;
api_error utimens_impl(std::string api_path, const struct timespec tv[2]) override;
api_error write_impl(std::string api_path, const char *buffer, size_t write_size,
off_t write_offset, struct fuse_file_info *fi,
std::size_t &bytes_written) override;
protected:
void notify_fuse_args_parsed(const std::vector<std::string> &args) override;
void notify_fuse_main_exit(int &ret) override;
int shutdown() override;
void update_accessed_time(const std::string &api_path);
public:
std::uint64_t get_directory_item_count(const std::string &api_path) const override;
directory_item_list get_directory_items(const std::string &api_path) const override;
std::uint64_t get_file_size(const std::string &api_path) const override;
api_error get_item_meta(const std::string &api_path, api_meta_map &meta) const override;
api_error get_item_meta(const std::string &api_path, const std::string &name,
std::string &value) const override;
std::uint64_t get_total_drive_space() const override;
std::uint64_t get_total_item_count() const override;
std::uint64_t get_used_drive_space() const override;
void get_volume_info(UINT64 &total_size, UINT64 &free_size,
std::string &volume_label) const override;
bool is_processing(const std::string &api_path) const override;
void populate_stat(const directory_item &di, struct stat &st) const override;
int rename_directory(const std::string &from_api_path, const std::string &to_api_path) override;
int rename_file(const std::string &from_api_path, const std::string &to_api_path,
const bool &overwrite) override;
void set_item_meta(const std::string &api_path, const std::string &key,
const std::string &value) override;
void update_directory_item(directory_item &di) const override;
};
} // namespace repertory
#endif // _WIN32
#endif // INCLUDE_DRIVES_FUSE_FUSE_DRIVE_HPP_

View File

@ -0,0 +1,71 @@
/*
Copyright <2018-2022> <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_DRIVES_FUSE_I_FUSE_DRIVE_HPP_
#define INCLUDE_DRIVES_FUSE_I_FUSE_DRIVE_HPP_
#ifndef _WIN32
#include "common.hpp"
#include "types/repertory.hpp"
namespace repertory {
class i_fuse_drive {
INTERFACE_SETUP(i_fuse_drive);
public:
virtual api_error check_parent_access(const std::string &api_path, int mask) const = 0;
virtual std::uint64_t get_directory_item_count(const std::string &api_path) const = 0;
virtual directory_item_list get_directory_items(const std::string &api_path) const = 0;
virtual std::uint64_t get_file_size(const std::string &api_path) const = 0;
virtual api_error get_item_meta(const std::string &api_path, api_meta_map &meta) const = 0;
virtual api_error get_item_meta(const std::string &api_path, const std::string &name,
std::string &value) const = 0;
virtual std::uint64_t get_total_drive_space() const = 0;
virtual std::uint64_t get_total_item_count() const = 0;
virtual std::uint64_t get_used_drive_space() const = 0;
virtual void get_volume_info(UINT64 &total_size, UINT64 &free_size,
std::string &volume_label) const = 0;
virtual bool is_processing(const std::string &api_path) const = 0;
virtual void populate_stat(const directory_item &di, struct stat &st) const = 0;
virtual int rename_directory(const std::string &from_api_path,
const std::string &to_api_path) = 0;
virtual int rename_file(const std::string &from_api_path, const std::string &to_api_path,
const bool &overwrite) = 0;
virtual void set_item_meta(const std::string &api_path, const std::string &key,
const std::string &value) = 0;
virtual void update_directory_item(directory_item &di) const = 0;
};
} // namespace repertory
#endif
#endif // INCLUDE_DRIVES_FUSE_I_FUSE_DRIVE_HPP_

View File

@ -0,0 +1,151 @@
/*
Copyright <2018-2022> <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_DRIVES_FUSE_REMOTEFUSE_I_REMOTE_INSTANCE_HPP_
#define INCLUDE_DRIVES_FUSE_REMOTEFUSE_I_REMOTE_INSTANCE_HPP_
#include "common.hpp"
#include "drives/remote/i_remote_json.hpp"
#include "types/remote.hpp"
namespace repertory::remote_fuse {
class i_remote_instance : public virtual i_remote_json {
INTERFACE_SETUP(i_remote_instance);
public:
virtual packet::error_type fuse_access(const char *path, const std::int32_t &mask) = 0;
virtual packet::error_type fuse_chflags(const char *path, const std::uint32_t &flags) = 0;
virtual packet::error_type fuse_chmod(const char *path, const remote::file_mode &mode) = 0;
virtual packet::error_type fuse_chown(const char *path, const remote::user_id &uid,
const remote::group_id &gid) = 0;
virtual packet::error_type fuse_create(const char *path, const remote::file_mode &mode,
const remote::open_flags &flags,
remote::file_handle &handle) = 0;
virtual packet::error_type fuse_destroy() = 0;
/*virtual packet::error_type fuse_fallocate(const char *path, const std::int32_t &mode,
const remote::file_offset &offset,
const remote::file_offset &length,
const remote::file_offset &length,
const remote::file_handle &handle) = 0;*/
virtual packet::error_type fuse_fgetattr(const char *path, remote::stat &st, bool &directory,
const remote::file_handle &handle) = 0;
virtual packet::error_type fuse_fsetattr_x(const char *path, const remote::setattr_x &attr,
const remote::file_handle &handle) = 0;
virtual packet::error_type fuse_fsync(const char *path, const std::int32_t &datasync,
const remote::file_handle &handle) = 0;
virtual packet::error_type fuse_ftruncate(const char *path, const remote::file_offset &size,
const remote::file_handle &handle) = 0;
virtual packet::error_type fuse_getattr(const char *path, remote::stat &st, bool &directory) = 0;
/*virtual packet::error_type fuse_getxattr(const char *path, const char *name, char *value,
const remote::file_size &size) = 0;
virtual packet::error_type fuse_getxattrOSX(const char *path, const char *name, char *value,
const remote::file_size &size,
const std::uint32_t &position) = 0;*/
virtual packet::error_type fuse_getxtimes(const char *path, remote::file_time &bkuptime,
remote::file_time &crtime) = 0;
virtual packet::error_type fuse_init() = 0;
/*virtual packet::error_type fuse_listxattr(const char *path, char *buffer,
const remote::file_size &size) = 0;*/
virtual packet::error_type fuse_mkdir(const char *path, const remote::file_mode &mode) = 0;
virtual packet::error_type fuse_open(const char *path, const remote::open_flags &flags,
remote::file_handle &handle) = 0;
virtual packet::error_type fuse_opendir(const char *path, remote::file_handle &handle) = 0;
virtual packet::error_type fuse_read(const char *path, char *buffer,
const remote::file_size &readSize,
const remote::file_offset &readOffset,
const remote::file_handle &handle) = 0;
virtual packet::error_type fuse_readdir(const char *path, const remote::file_offset &offset,
const remote::file_handle &handle, std::string &itemPath) = 0;
virtual packet::error_type fuse_release(const char *path, const remote::file_handle &handle) = 0;
virtual packet::error_type fuse_releasedir(const char *path, const remote::file_handle &handle) = 0;
// virtual packet::error_type fuse_removexattr(const char *path, const char *name) = 0;
virtual packet::error_type fuse_rename(const char *from, const char *to) = 0;
virtual packet::error_type fuse_rmdir(const char *path) = 0;
virtual packet::error_type fuse_setattr_x(const char *path, remote::setattr_x &attr) = 0;
virtual packet::error_type fuse_setbkuptime(const char *path, const remote::file_time &bkuptime) = 0;
virtual packet::error_type fuse_setchgtime(const char *path, const remote::file_time &chgtime) = 0;
virtual packet::error_type fuse_setcrtime(const char *path, const remote::file_time &crtime) = 0;
virtual packet::error_type fuse_setvolname(const char *volname) = 0;
/*virtual packet::error_type fuse_setxattr(const char *path, const char *name,
const char *value, const remote::file_size &size,
const std::int32_t &flags) = 0;
virtual packet::error_type fuse_setxattr_osx(const char *path, const char *name,
const char *value, const remote::file_size &size,
const std::int32_t &flags,
const std::uint32_t &position) = 0;*/
virtual packet::error_type fuse_statfs(const char *path, const std::uint64_t &frsize,
remote::statfs &st) = 0;
virtual packet::error_type fuse_statfs_x(const char *path, const std::uint64_t &bsize,
remote::statfs_x &st) = 0;
virtual packet::error_type fuse_truncate(const char *path, const remote::file_offset &size) = 0;
virtual packet::error_type fuse_unlink(const char *path) = 0;
virtual packet::error_type fuse_utimens(const char *path, const remote::file_time *tv,
const std::uint64_t &op0, const std::uint64_t &op1) = 0;
virtual packet::error_type fuse_write(const char *path, const char *buffer,
const remote::file_size &writeSize,
const remote::file_offset &writeOffset,
const remote::file_handle &handle) = 0;
virtual packet::error_type fuse_write_base64(const char *path, const char *buffer,
const remote::file_size &writeSize,
const remote::file_offset &writeOffset,
const remote::file_handle &handle) = 0;
virtual void set_fuse_uid_gid(const remote::user_id &uid, const remote::group_id &gid) = 0;
};
typedef std::function<std::unique_ptr<i_remote_instance>()> remote_instance_factory;
} // namespace repertory::remote_fuse
#endif // INCLUDE_DRIVES_FUSE_REMOTEFUSE_I_REMOTE_INSTANCE_HPP_

View File

@ -0,0 +1,172 @@
/*
Copyright <2018-2022> <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_DRIVES_FUSE_REMOTEFUSE_REMOTE_CLIENT_HPP_
#define INCLUDE_DRIVES_FUSE_REMOTEFUSE_REMOTE_CLIENT_HPP_
#include "common.hpp"
#include "comm/packet/packet_client.hpp"
#include "drives/fuse/remotefuse/i_remote_instance.hpp"
#include "events/event_system.hpp"
#include "types/remote.hpp"
namespace repertory {
class app_config;
namespace remote_fuse {
class remote_client final : public i_remote_instance {
public:
explicit remote_client(const app_config &config);
private:
const app_config &config_;
packet_client packet_client_;
remote::user_id uid_ = 0;
remote::group_id gid_ = 0;
public:
packet::error_type fuse_access(const char *path, const std::int32_t &mask) override;
packet::error_type fuse_chflags(const char *path, const std::uint32_t &flags) override;
packet::error_type fuse_chmod(const char *path, const remote::file_mode &mode) override;
packet::error_type fuse_chown(const char *path, const remote::user_id &uid,
const remote::group_id &gid) override;
packet::error_type fuse_destroy() override;
/*packet::error_type fuse_fallocate(const char *path, const std::int32_t &mode,
const remote::file_offset &offset,
const remote::file_offset &length,
const remote::file_handle &handle) override ;*/
packet::error_type fuse_fgetattr(const char *path, remote::stat &st, bool &directory,
const remote::file_handle &handle) override;
packet::error_type fuse_fsetattr_x(const char *path, const remote::setattr_x &attr,
const remote::file_handle &handle) override;
packet::error_type fuse_fsync(const char *path, const std::int32_t &datasync,
const remote::file_handle &handle) override;
packet::error_type fuse_ftruncate(const char *path, const remote::file_offset &size,
const remote::file_handle &handle) override;
packet::error_type fuse_getattr(const char *path, remote::stat &st, bool &directory) override;
/*packet::error_type fuse_getxattr(const char *path, const char *name, char *value,
const remote::file_size &size) override ;
packet::error_type fuse_getxattrOSX(const char *path, const char *name, char *value,
const remote::file_size &size,
const std::uint32_t &position) override ;*/
packet::error_type fuse_getxtimes(const char *path, remote::file_time &bkuptime,
remote::file_time &crtime) override;
packet::error_type fuse_init() override;
/*packet::error_type fuse_listxattr(const char *path, char *buffer,
const remote::file_size &size) override ;*/
packet::error_type fuse_mkdir(const char *path, const remote::file_mode &mode) override;
packet::error_type fuse_opendir(const char *path, remote::file_handle &handle) override;
packet::error_type fuse_create(const char *path, const remote::file_mode &mode,
const remote::open_flags &flags, remote::file_handle &handle) override;
packet::error_type fuse_open(const char *path, const remote::open_flags &flags,
remote::file_handle &handle) override;
packet::error_type fuse_read(const char *path, char *buffer, const remote::file_size &read_size,
const remote::file_offset &read_offset,
const remote::file_handle &handle) override;
packet::error_type fuse_rename(const char *from, const char *to) override;
packet::error_type fuse_readdir(const char *path, const remote::file_offset &offset,
const remote::file_handle &handle, std::string &item_path) override;
packet::error_type fuse_release(const char *path, const remote::file_handle &handle) override;
packet::error_type fuse_releasedir(const char *path, const remote::file_handle &handle) override;
/*packet::error_type fuse_removexattr(const char *path, const char *name) override ;*/
packet::error_type fuse_rmdir(const char *path) override;
packet::error_type fuse_setattr_x(const char *path, remote::setattr_x &attr) override;
packet::error_type fuse_setbkuptime(const char *path, const remote::file_time &bkuptime) override;
packet::error_type fuse_setchgtime(const char *path, const remote::file_time &chgtime) override;
packet::error_type fuse_setcrtime(const char *path, const remote::file_time &crtime) override;
packet::error_type fuse_setvolname(const char *volname) override;
/*packet::error_type fuse_setxattr(const char *path, const char *name, const char *value,
const remote::file_size &size,
const std::int32_t &flags) override ;
packet::error_type fuse_setxattr_osx(const char *path, const char *name, const char *value,
const remote::file_size &size, const std::int32_t &flags,
const std::uint32_t &position) override ;*/
packet::error_type fuse_statfs(const char *path, const std::uint64_t &frsize,
remote::statfs &st) override;
packet::error_type fuse_statfs_x(const char *path, const std::uint64_t &bsize,
remote::statfs_x &st) override;
packet::error_type fuse_truncate(const char *path, const remote::file_offset &size) override;
packet::error_type fuse_unlink(const char *path) override;
packet::error_type fuse_utimens(const char *path, const remote::file_time *tv,
const std::uint64_t &op0, const std::uint64_t &op1) override;
packet::error_type fuse_write(const char *path, const char *buffer,
const remote::file_size &write_size,
const remote::file_offset &write_offset,
const remote::file_handle &handle) override;
packet::error_type fuse_write_base64(const char *path, const char *buffer,
const remote::file_size &write_size,
const remote::file_offset &write_offset,
const remote::file_handle &handle) override;
packet::error_type json_create_directory_snapshot(const std::string &path,
json &json_data) override;
packet::error_type json_read_directory_snapshot(const std::string &path,
const remote::file_handle &handle,
const std::uint32_t &page,
json &json_data) override;
packet::error_type json_release_directory_snapshot(const std::string &path,
const remote::file_handle &handle) override;
void set_fuse_uid_gid(const remote::user_id &uid, const remote::group_id &gid) override;
};
} // namespace remote_fuse
} // namespace repertory
#endif // INCLUDE_DRIVES_FUSE_REMOTEFUSE_REMOTE_CLIENT_HPP_

View File

@ -0,0 +1,257 @@
/*
Copyright <2018-2022> <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_DRIVES_FUSE_REMOTEFUSE_REMOTE_FUSE_DRIVE_HPP_
#define INCLUDE_DRIVES_FUSE_REMOTEFUSE_REMOTE_FUSE_DRIVE_HPP_
#ifndef _WIN32
#include "common.hpp"
#include "drives/fuse/remotefuse/i_remote_instance.hpp"
#include "events/event_system.hpp"
namespace repertory {
class app_config;
class console_consumer;
class logging_consumer;
class lock_data;
class server;
namespace remote_fuse {
class remote_fuse_drive final {
E_CONSUMER();
public:
remote_fuse_drive(app_config &config, lock_data &lock, remote_instance_factory factory);
~remote_fuse_drive() { E_CONSUMER_RELEASE(); }
private:
app_config &config_;
lock_data &lock_;
remote_instance_factory factory_;
std::string mount_location_;
private:
static void shutdown(std::string mount_location);
private:
class remote_fuse_impl final {
public:
static app_config *config_;
static lock_data *lock_;
static std::string *mount_location_;
static remote_instance_factory *factory_;
static std::unique_ptr<console_consumer> console_consumer_;
static std::unique_ptr<logging_consumer> logging_consumer_;
static std::unique_ptr<i_remote_instance> remote_instance_;
static std::unique_ptr<server> server_;
static std::optional<gid_t> forced_gid_;
static std::optional<uid_t> forced_uid_;
static std::optional<mode_t> forced_umask_;
static bool console_enabled_;
static bool was_mounted_;
public:
static void tear_down(const int &ret);
private:
static void populate_stat(const remote::stat &r, const bool &directory, struct stat &st);
public:
static int repertory_access(const char *path, int mask);
#ifdef __APPLE__
static int repertory_chflags(const char *path, uint32_t flags);
#endif
static int repertory_chmod(const char *path, mode_t mode);
static int repertory_chown(const char *path, uid_t uid, gid_t gid);
static int repertory_create(const char *path, mode_t mode, struct fuse_file_info *fi);
static void repertory_destroy(void * /*ptr*/);
/*static int repertory_fallocate(const char *path, int mode, off_t offset, off_t length,
struct fuse_file_info *fi) ;*/
static int repertory_fgetattr(const char *path, struct stat *st, struct fuse_file_info *fi);
#ifdef __APPLE__
static int repertory_fsetattr_x(const char *path, struct setattr_x *attr,
struct fuse_file_info *fi);
#endif
static int repertory_fsync(const char *path, int datasync, struct fuse_file_info *fi);
static int repertory_ftruncate(const char *path, off_t size, struct fuse_file_info *fi);
static int repertory_getattr(const char *path, struct stat *st);
#ifdef __APPLE__
static int repertory_getxtimes(const char *path, struct timespec *bkuptime,
struct timespec *crtime);
#endif
static void *repertory_init(struct fuse_conn_info *conn);
static int repertory_mkdir(const char *path, mode_t mode);
static int repertory_open(const char *path, struct fuse_file_info *fi);
static int repertory_opendir(const char *path, struct fuse_file_info *fi);
static int repertory_read(const char *path, char *buffer, size_t readSize, off_t readOffset,
struct fuse_file_info *fi);
static int repertory_readdir(const char *path, void *buf, fuse_fill_dir_t fuseFillDir,
off_t offset, struct fuse_file_info *fi);
static int repertory_release(const char *path, struct fuse_file_info *fi);
static int repertory_releasedir(const char *path, struct fuse_file_info *fi);
static int repertory_rename(const char *from, const char *to);
static int repertory_rmdir(const char *path);
/*
#ifdef HAS_SETXATTR
#ifdef __APPLE__
static int repertory_getxattr(const char *path, const char *name, char *value, size_t size,
uint32_t position) ;
#else
static int repertory_getxattr(const char *path, const char *name, char *value, size_t size) ;
#endif
static int repertory_listxattr(const char *path, char *buffer, size_t size) ;
static int repertory_removexattr(const char *path, const char *name) ;
#ifdef __APPLE__
static int repertory_setxattr(const char *path, const char *name, const char *value,
size_t size, int flags, uint32_t position) ;
#else
static int repertory_setxattr(const char *path, const char *name, const char *value,
size_t size, int flags) ;
#endif
#endif
*/
#ifdef __APPLE__
static int repertory_setattr_x(const char *path, struct setattr_x *attr);
static int repertory_setbkuptime(const char *path, const struct timespec *bkuptime);
static int repertory_setchgtime(const char *path, const struct timespec *chgtime);
static int repertory_setcrtime(const char *path, const struct timespec *crtime);
static int repertory_setvolname(const char *volname);
static int repertory_statfs_x(const char *path, struct statfs *stbuf);
#else
static int repertory_statfs(const char *path, struct statvfs *stbuf);
#endif
static int repertory_truncate(const char *path, off_t size);
static int repertory_unlink(const char *path);
static int repertory_utimens(const char *path, const struct timespec tv[2]);
static int repertory_write(const char *path, const char *buffer, size_t writeSize,
off_t writeOffset, struct fuse_file_info *fi);
};
private:
// clang-format off
struct fuse_operations fuse_ops_ {
.getattr = remote_fuse_impl::repertory_getattr,
.readlink = nullptr, // int (*readlink) (const char *, char *, size_t);
.getdir = nullptr, // int (*getdir) (const char *, fuse_dirh_t, fuse_dirfil_t);
.mknod = nullptr, // int (*mknod) (const char *, mode_t, dev_t);
.mkdir = remote_fuse_impl::repertory_mkdir,
.unlink = remote_fuse_impl::repertory_unlink,
.rmdir = remote_fuse_impl::repertory_rmdir,
.symlink = nullptr, // int (*symlink) (const char *, const char *);
.rename = remote_fuse_impl::repertory_rename,
.link = nullptr, // int (*link) (const char *, const char *);
.chmod = remote_fuse_impl::repertory_chmod,
.chown = remote_fuse_impl::repertory_chown,
.truncate = remote_fuse_impl::repertory_truncate,
.utime = nullptr, // int (*utime) (const char *, struct utimbuf *);
.open = remote_fuse_impl::repertory_open,
.read = remote_fuse_impl::repertory_read,
.write = remote_fuse_impl::repertory_write,
#ifdef __APPLE__
.statfs = nullptr,
#else
.statfs = remote_fuse_impl::repertory_statfs,
#endif
.flush = nullptr, // int (*flush) (const char *, struct fuse_file_info *);
.release = remote_fuse_impl::repertory_release,
.fsync = remote_fuse_impl::repertory_fsync,
#if HAS_SETXATTR
.setxattr = nullptr, // remote_fuse_impl::repertory_setxattr,
.getxattr = nullptr, // remote_fuse_impl::repertory_getxattr,
.listxattr = nullptr, // remote_fuse_impl::repertory_listxattr,
.removexattr = nullptr, // remote_fuse_impl::repertory_removexattr,
#else
.setxattr = nullptr,
.getxattr = nullptr,
.listxattr = nullptr,
.removexattr = nullptr,
#endif
.opendir = remote_fuse_impl::repertory_opendir,
.readdir = remote_fuse_impl::repertory_readdir,
.releasedir = remote_fuse_impl::repertory_releasedir,
.fsyncdir = nullptr, // int (*fsyncdir) (const char *, int, struct fuse_file_info *);
.init = remote_fuse_impl::repertory_init,
.destroy = remote_fuse_impl::repertory_destroy,
.access = remote_fuse_impl::repertory_access,
.create = remote_fuse_impl::repertory_create,
.ftruncate = remote_fuse_impl::repertory_ftruncate,
.fgetattr = remote_fuse_impl::repertory_fgetattr,
.lock = nullptr, // int (*lock) (const char *, struct fuse_file_info *, int cmd, struct flock *);
.utimens = remote_fuse_impl::repertory_utimens,
.bmap = nullptr, // int (*bmap) (const char *, size_t blocksize, uint64_t *idx);
.flag_nullpath_ok = 0,
.flag_nopath = 0,
.flag_utime_omit_ok = 1,
.flag_reserved = 0,
.ioctl = nullptr, // int (*ioctl) (const char *, int cmd, void *arg, struct fuse_file_info *, unsigned int flags, void *data);
.poll = nullptr, // int (*poll) (const char *, struct fuse_file_info *, struct fuse_pollhandle *ph, unsigned *reventsp);
.write_buf = nullptr, // int (*write_buf) (const char *, struct fuse_bufvec *buf, off_t off, struct fuse_file_info *);
.read_buf = nullptr, // int (*read_buf) (const char *, struct fuse_bufvec **bufp, size_t size, off_t off, struct fuse_file_info *);
.flock = nullptr, // int (*flock) (const char *, struct fuse_file_info *, int op);
.fallocate = nullptr // remote_fuse_impl::repertory_fallocate,
};
// clang-format on
public:
int mount(std::vector<std::string> drive_args);
static void display_options(int argc, char *argv[]);
static void display_version_information(int argc, char *argv[]);
};
} // namespace remote_fuse
} // namespace repertory
#endif // _WIN32
#endif // INCLUDE_DRIVES_FUSE_REMOTEFUSE_REMOTE_FUSE_DRIVE_HPP_

View File

@ -0,0 +1,101 @@
/*
Copyright <2018-2022> <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_DRIVES_FUSE_REMOTEFUSE_REMOTE_FUSE_DRIVE2_HPP_
#define INCLUDE_DRIVES_FUSE_REMOTEFUSE_REMOTE_FUSE_DRIVE2_HPP_
#ifndef _WIN32
#if 0
#include "common.hpp"
#include "drives/fuse/fuse_base.hpp"
#include "drives/fuse/remotefuse/i_remote_instance.hpp"
#include "events/event_system.hpp"
namespace repertory {
class app_config;
class console_consumer;
class logging_consumer;
class lock_data;
class server;
namespace utils {
api_error to_api_error(packet::error_type e) { return api_error::success; }
} // namespace utils
namespace remote_fuse {
class remote_fuse_drive2 final : public fuse_base {
E_CONSUMER();
public:
~remote_fuse_drive2() override = default;
private:
std::unique_ptr<i_remote_instance> remote_instance_;
protected:
api_error access_impl(std::string api_path, int mask) override;
#ifdef __APPLE__
api_error chflags_impl(std::string api_path, uint32_t flags) override;
#endif // __APPLE__
api_error chmod_impl(std::string api_path, mode_t mode) override;
public:
api_error check_parent_access(const std::string &api_path, int mask) const override;
std::uint64_t get_directory_item_count(const std::string &api_path) const override;
directory_item_list get_directory_items(const std::string &api_path) const override;
std::uint64_t get_file_size(const std::string &api_path) const override;
api_error get_item_meta(const std::string &api_path, api_meta_map &meta) const override;
api_error get_item_meta(const std::string &api_path, const std::string &name,
std::string &value) const override;
std::uint64_t get_total_drive_space() const override;
std::uint64_t get_total_item_count() const override;
std::uint64_t get_used_drive_space() const override;
void get_volume_info(UINT64 &total_size, UINT64 &free_size,
std::string &volume_label) const override;
bool is_processing(const std::string &api_path) const override;
void populate_stat(const directory_item &di, struct stat &st) const override;
int rename_directory(const std::string &from_api_path, const std::string &to_api_path) override;
int rename_file(const std::string &from_api_path, const std::string &to_api_path,
const bool &overwrite) override;
void set_item_meta(const std::string &api_path, const std::string &key,
const std::string &value) override;
void update_directory_item(directory_item &di) const override;
};
} // namespace remote_fuse
} // namespace repertory
#endif // 0
#endif // _WIN32
#endif // INCLUDE_DRIVES_FUSE_REMOTEFUSE_REMOTE_FUSE_DRIVE2_HPP_

View File

@ -0,0 +1,253 @@
/*
Copyright <2018-2022> <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_DRIVES_FUSE_REMOTEFUSE_REMOTE_SERVER_HPP_
#define INCLUDE_DRIVES_FUSE_REMOTEFUSE_REMOTE_SERVER_HPP_
#ifndef _WIN32
#include "common.hpp"
#include "drives/directory_cache.hpp"
#include "drives/fuse/i_fuse_drive.hpp"
#include "drives/remote/remote_server_base.hpp"
namespace repertory {
class app_config;
namespace remote_fuse {
class remote_server final : public virtual remote_server_base<i_fuse_drive> {
public:
remote_server(app_config &config, i_fuse_drive &drive, const std::string &mount_location);
private:
directory_cache directory_cache_;
private:
std::string construct_path(std::string path);
std::string construct_path(const std::wstring &path);
static std::string empty_as_zero(const json &data);
packet::error_type populate_file_info(const std::string &api_path, remote::file_info &file_info);
void populate_file_info(const std::string &api_path, const UINT64 &file_size,
const UINT32 &attributes, remote::file_info &file_info);
static void populate_stat(const struct stat &st1, remote::stat &st);
json &update_to_windows_format(json &item);
protected:
void delete_open_directory(void *dir) override;
public:
// FUSE Layer
packet::error_type fuse_access(const char *path, const std::int32_t &mask) override;
packet::error_type fuse_chflags(const char *path, const std::uint32_t &flags) override;
packet::error_type fuse_chmod(const char *path, const remote::file_mode &mode) override;
packet::error_type fuse_chown(const char *path, const remote::user_id &uid,
const remote::group_id &gid) override;
packet::error_type fuse_create(const char *path, const remote::file_mode &mode,
const remote::open_flags &flags, remote::file_handle &handle) override;
packet::error_type fuse_destroy() override;
/*packet::error_type fuse_fallocate(const char *path, const std::int32_t &mode,
const remote::file_offset &offset,
const remote::file_offset &length,
const remote::file_handle &handle) override ;*/
packet::error_type fuse_fgetattr(const char *path, remote::stat &st, bool &directory,
const remote::file_handle &handle) override;
packet::error_type fuse_fsetattr_x(const char *path, const remote::setattr_x &attr,
const remote::file_handle &handle) override;
packet::error_type fuse_fsync(const char *path, const std::int32_t &datasync,
const remote::file_handle &handle) override;
packet::error_type fuse_ftruncate(const char *path, const remote::file_offset &size,
const remote::file_handle &handle) override;
packet::error_type fuse_getattr(const char *path, remote::stat &st, bool &directory) override;
/*packet::error_type fuse_getxattr(const char *path, const char *name, char *value,
const remote::file_size &size) override ;
packet::error_type fuse_getxattrOSX(const char *path, const char *name, char *value,
const remote::file_size &size,
const std::uint32_t &position) override ;*/
packet::error_type fuse_getxtimes(const char *path, remote::file_time &bkuptime,
remote::file_time &crtime) override;
packet::error_type fuse_init() override;
/*packet::error_type fuse_listxattr(const char *path, char *buffer,
const remote::file_size &size) override ;*/
packet::error_type fuse_mkdir(const char *path, const remote::file_mode &mode) override;
packet::error_type fuse_open(const char *path, const remote::open_flags &flags,
remote::file_handle &handle) override;
packet::error_type fuse_opendir(const char *path, remote::file_handle &handle) override;
packet::error_type fuse_read(const char *path, char *buffer, const remote::file_size &read_size,
const remote::file_offset &read_offset,
const remote::file_handle &handle) override;
packet::error_type fuse_rename(const char *from, const char *to) override;
packet::error_type fuse_readdir(const char *path, const remote::file_offset &offset,
const remote::file_handle &handle, std::string &item_path) override;
packet::error_type fuse_release(const char *path, const remote::file_handle &handle) override;
packet::error_type fuse_releasedir(const char *path, const remote::file_handle &handle) override;
/*packet::error_type fuse_removexattr(const char *path, const char *name) override ;*/
packet::error_type fuse_rmdir(const char *path) override;
packet::error_type fuse_setattr_x(const char *path, remote::setattr_x &attr) override;
packet::error_type fuse_setbkuptime(const char *path, const remote::file_time &bkuptime) override;
packet::error_type fuse_setchgtime(const char *path, const remote::file_time &chgtime) override;
packet::error_type fuse_setcrtime(const char *path, const remote::file_time &crtime) override;
packet::error_type fuse_setvolname(const char *volname) override;
/*packet::error_type fuse_setxattr(const char *path, const char *name, const char *value,
const remote::file_size &size,
const std::int32_t &flags) override ;
packet::error_type fuse_setxattr_osx(const char *path, const char *name, const char *value,
const remote::file_size &size, const std::int32_t &flags,
const std::uint32_t &position) override ;*/
packet::error_type fuse_statfs(const char *path, const std::uint64_t &frsize,
remote::statfs &st) override;
packet::error_type fuse_statfs_x(const char *path, const std::uint64_t &bsize,
remote::statfs_x &st) override;
packet::error_type fuse_truncate(const char *path, const remote::file_offset &size) override;
packet::error_type fuse_unlink(const char *path) override;
packet::error_type fuse_utimens(const char *path, const remote::file_time *tv,
const std::uint64_t &op0, const std::uint64_t &op1) override;
packet::error_type fuse_write(const char *path, const char *buffer,
const remote::file_size &write_size,
const remote::file_offset &write_offset,
const remote::file_handle &handle) override;
packet::error_type fuse_write_base64(const char *path, const char *buffer,
const remote::file_size &write_size,
const remote::file_offset &write_offset,
const remote::file_handle &handle) override;
void set_fuse_uid_gid(const remote::user_id &, const remote::group_id &) override {}
// JSON Layer
packet::error_type winfsp_get_dir_buffer(PVOID /*file_desc*/, PVOID *& /*ptr*/) override {
return STATUS_INVALID_HANDLE;
}
packet::error_type json_create_directory_snapshot(const std::string &path,
json &jsonData) override;
packet::error_type json_read_directory_snapshot(const std::string &path,
const remote::file_handle &handle,
const std::uint32_t &page,
json &jsonData) override;
packet::error_type json_release_directory_snapshot(const std::string &path,
const remote::file_handle &handle) override;
// WinFSP Layer
packet::error_type winfsp_can_delete(PVOID file_desc, PWSTR file_name) override;
packet::error_type winfsp_cleanup(PVOID file_desc, PWSTR file_name, UINT32 flags,
BOOLEAN &wasClosed) override;
packet::error_type winfsp_close(PVOID file_desc) override;
packet::error_type winfsp_create(PWSTR file_name, UINT32 create_options, UINT32 granted_access,
UINT32 attributes, UINT64 /*allocation_size*/, PVOID *file_desc,
remote::file_info *file_info, std::string &normalized_name,
BOOLEAN &exists) override;
packet::error_type winfsp_flush(PVOID file_desc, remote::file_info *file_info) override;
packet::error_type winfsp_get_file_info(PVOID file_desc, remote::file_info *file_info) override;
packet::error_type winfsp_get_security_by_name(PWSTR file_name, PUINT32 attributes,
std::uint64_t * /*securityDescriptorSize*/,
std::wstring & /*strDescriptor*/) override;
packet::error_type winfsp_get_volume_info(UINT64 &total_size, UINT64 &free_size,
std::string &volume_label) override;
packet::error_type winfsp_mounted(const std::wstring &location) override;
packet::error_type winfsp_open(PWSTR file_name, UINT32 create_options, UINT32 granted_access,
PVOID *file_desc, remote::file_info *file_info,
std::string &normalized_name) override;
packet::error_type winfsp_overwrite(PVOID file_desc, UINT32 attributes,
BOOLEAN replace_attributes, UINT64 /*allocation_size*/,
remote::file_info *file_info) override;
packet::error_type winfsp_read(PVOID file_desc, PVOID buffer, UINT64 offset, UINT32 length,
PUINT32 bytes_transferred) override;
packet::error_type winfsp_read_directory(PVOID file_desc, PWSTR /*pattern*/, PWSTR marker,
json &itemList) override;
packet::error_type winfsp_rename(PVOID /*file_desc*/, PWSTR file_name, PWSTR new_file_name,
BOOLEAN replace_if_exists) override;
packet::error_type 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) override;
packet::error_type winfsp_set_file_size(PVOID file_desc, UINT64 newSize,
BOOLEAN set_allocation_size,
remote::file_info *file_info) override;
packet::error_type winfsp_unmounted(const std::wstring &location) override;
packet::error_type winfsp_write(PVOID file_desc, PVOID buffer, UINT64 offset, UINT32 length,
BOOLEAN write_to_end, BOOLEAN constrained_io,
PUINT32 bytes_transferred, remote::file_info *file_info) override;
};
} // namespace remote_fuse
} // namespace repertory
#endif
#endif // INCLUDE_DRIVES_FUSE_REMOTEFUSE_REMOTE_SERVER_HPP_

View File

@ -0,0 +1,64 @@
/*
Copyright <2018-2022> <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_DRIVES_I_OPEN_FILE_TABLE_HPP_
#define INCLUDE_DRIVES_I_OPEN_FILE_TABLE_HPP_
#include "common.hpp"
#include "types/repertory.hpp"
namespace repertory {
class i_provider;
class i_open_file_table {
INTERFACE_SETUP(i_open_file_table);
public:
typedef std::function<bool(i_open_file_table &oft, i_provider &provider)>
locked_operation_callback;
public:
virtual void close(const std::uint64_t &handle) = 0;
virtual bool contains_restore(const std::string &api_path) const = 0;
virtual bool evict_file(const std::string &api_path) = 0;
virtual void force_schedule_upload(const filesystem_item &fsi) = 0;
virtual directory_item_list get_directory_items(const std::string &api_path) const = 0;
virtual std::uint64_t get_open_count(const std::string &api_path) const = 0;
virtual bool get_open_file(const std::string &api_path, filesystem_item *&fsi) = 0;
virtual std::unordered_map<std::string, std::size_t> get_open_files() const = 0;
virtual bool has_no_open_file_handles() const = 0;
virtual api_error open(const filesystem_item &fsi, std::uint64_t &handle) = 0;
virtual bool perform_locked_operation(locked_operation_callback locked_operation) = 0;
virtual api_error set_item_meta(const std::string &api_path, const std::string &key,
const std::string &value) = 0;
virtual void update_directory_item(directory_item &di) const = 0;
};
} // namespace repertory
#endif // INCLUDE_DRIVES_I_OPEN_FILE_TABLE_HPP_

View File

@ -0,0 +1,751 @@
/*
Copyright <2018-2022> <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_DRIVES_OPEN_FILE_TABLE_HPP_
#define INCLUDE_DRIVES_OPEN_FILE_TABLE_HPP_
#include "common.hpp"
#include "app_config.hpp"
#include "db/retry_db.hpp"
#include "download/i_download_manager.hpp"
#include "drives/i_open_file_table.hpp"
#include "providers/i_provider.hpp"
#include "types/repertory.hpp"
#include "utils/file_utils.hpp"
#include "utils/global_data.hpp"
#include "utils/native_file.hpp"
#include "utils/path_utils.hpp"
#include "utils/polling.hpp"
namespace repertory {
template <typename flags> class open_file_table final : public virtual i_open_file_table {
public:
open_file_table(i_provider &provider, const app_config &config, i_download_manager &dm)
: provider_(provider), config_(config), dm_(dm), retry_db_(config) {
// Set initial value for used cache space
global_data::instance().initialize_used_cache_space(
utils::file::calculate_used_space(config_.get_cache_directory(), false));
polling::instance().set_callback(
{"last_close_clear", false, [this] {
std::vector<std::string> keys;
unique_mutex_lock l(last_close_mutex_);
std::transform(last_close_lookup_.begin(), last_close_lookup_.end(),
std::back_inserter(keys), [](const auto &kv) { return kv.first; });
l.unlock();
for (const auto &key : keys) {
l.lock();
remove_if_expired(key, last_close_lookup_[key]);
l.unlock();
}
}});
}
~open_file_table() override { polling::instance().remove_callback("last_close_clear"); }
private:
struct open_file_info {
filesystem_item item;
api_meta_map meta;
};
private:
i_provider &provider_;
const app_config &config_;
i_download_manager &dm_;
retry_db retry_db_;
std::unordered_map<std::string, std::shared_ptr<open_file_info>> open_file_lookup_;
mutable std::recursive_mutex open_file_mutex_;
std::unordered_map<std::uint64_t, open_file_info *> open_handle_lookup_;
std::uint64_t next_handle_ = 1u;
bool stop_requested_ = false;
std::mutex retry_mutex_;
std::unique_ptr<std::thread> retry_thread_;
std::condition_variable retry_notify_;
std::mutex start_stop_mutex_;
std::mutex last_close_mutex_;
std::unordered_map<std::string, std::uint64_t> last_close_lookup_;
private:
api_error get_filesystem_item(const std::string &api_path, const bool &directory,
filesystem_item &fsi) {
auto ret = api_error::item_not_found;
const auto it = open_file_lookup_.find(api_path);
if (it != open_file_lookup_.end()) {
fsi = it->second->item;
ret = api_error::success;
} else {
ret = provider_.get_filesystem_item(api_path, directory, fsi);
}
return ret;
}
std::uint64_t get_next_handle() {
std::uint64_t ret = 0u;
while ((ret = next_handle_++) == 0u) {
}
return ret;
}
api_error handle_file_rename(const std::string &from_api_path, const std::string &to_api_path) {
auto ret = api_error::file_in_use;
if (dm_.pause_download(from_api_path)) {
if ((ret = provider_.rename_file(from_api_path, to_api_path)) == api_error::success) {
swap_renamed_items(from_api_path, to_api_path);
dm_.rename_download(from_api_path, to_api_path);
dm_.resume_download(to_api_path);
retry_db_.rename(from_api_path, to_api_path);
} else {
dm_.resume_download(from_api_path);
}
}
return ret;
}
void handle_file_upload(filesystem_item &fsi) {
fsi.changed = false;
handle_file_upload(&fsi);
}
void handle_file_upload(const filesystem_item *fsi) {
// Remove from retry queue, if present
retry_db_.remove(fsi->api_path);
// Upload file and add to retry queue on failure
auto nf = native_file::attach(fsi->handle);
nf->flush();
if (provider_.upload_file(fsi->api_path, fsi->source_path, fsi->encryption_token) !=
api_error::success) {
retry_db_.set(fsi->api_path);
event_system::instance().raise<failed_upload_queued>(fsi->api_path);
}
}
bool remove_if_expired(const std::string &api_path, const std::uint64_t &time) {
auto ret = false;
#ifdef _WIN32
const auto delay = std::chrono::minutes(config_.get_eviction_delay_mins());
const auto last_check = std::chrono::system_clock::from_time_t(time);
if ((ret = ((last_check + delay) <= std::chrono::system_clock::now())))
#else
if ((ret = ((time + ((config_.get_eviction_delay_mins() * 60L) * NANOS_PER_SECOND)) <=
utils::get_time_now())))
#endif
{
last_close_lookup_.erase(api_path);
}
return ret;
}
bool retry_delete_file(const std::string &file) {
auto deleted = false;
for (std::uint8_t i = 0u; not(deleted = utils::file::delete_file(file)) && (i < 100u); i++) {
std::this_thread::sleep_for(10ms);
}
return deleted;
}
void swap_renamed_items(std::string from_api_path, std::string to_api_path) {
const auto it = open_file_lookup_.find(from_api_path);
if (it != open_file_lookup_.end()) {
open_file_lookup_[to_api_path] = open_file_lookup_[from_api_path];
open_file_lookup_.erase(from_api_path);
auto &fsi = open_file_lookup_[to_api_path]->item;
fsi.api_path = to_api_path;
fsi.api_parent = utils::path::get_parent_api_path(to_api_path);
}
}
public:
bool has_no_open_file_handles() const override {
recur_mutex_lock l(open_file_mutex_);
return std::find_if(open_file_lookup_.cbegin(), open_file_lookup_.cend(), [](const auto &kv) {
return not kv.second->item.directory;
}) == open_file_lookup_.cend();
}
void close(const std::uint64_t &handle) override {
recur_mutex_lock l(open_file_mutex_);
const auto it = open_handle_lookup_.find(handle);
if (it != open_handle_lookup_.end()) {
auto *oi = it->second;
open_handle_lookup_.erase(handle);
auto &fsi = oi->item;
const auto was_changed = fsi.changed;
// Handle meta change
if (fsi.meta_changed) {
if (provider_.set_item_meta(fsi.api_path, oi->meta) == api_error::success) {
fsi.meta_changed = false;
} else {
event_system::instance().raise<repertory_exception>(
__FUNCTION__, "failed to set file meta: " + fsi.api_path);
}
}
// Handle source path change
if (not fsi.directory && fsi.source_path_changed) {
if (provider_.set_source_path(fsi.api_path, fsi.source_path) == api_error::success) {
fsi.source_path_changed = false;
} else {
event_system::instance().raise<repertory_exception>(
__FUNCTION__, "failed to set source path: " + fsi.api_path + "|" + fsi.source_path);
}
}
// Update last close time in lookup table
if (not fsi.directory) {
mutex_lock l2(last_close_mutex_);
last_close_lookup_[fsi.api_path] = utils::get_time_now();
}
// Handle file change
#ifdef __APPLE__
// Special handling for OS X - only upload if handle being closed is writable
if (not fsi.directory && was_changed && (fsi.open_data[handle] & O_ACCMODE))
#else
if (not fsi.directory && was_changed)
#endif
{
handle_file_upload(fsi);
}
// Close internal handle if no more open files
auto &od = fsi.open_data;
od.erase(handle);
event_system::instance().raise<filesystem_item_handle_closed>(
fsi.api_path, handle, fsi.source_path, fsi.directory, was_changed);
if (od.empty()) {
native_file::attach(fsi.handle)->close();
event_system::instance().raise<filesystem_item_closed>(fsi.api_path, fsi.source_path,
fsi.directory, was_changed);
open_file_lookup_.erase(fsi.api_path);
}
}
}
#ifdef _WIN32
void close_all(const std::string &api_path) {
recur_mutex_lock l(open_file_mutex_);
const auto it = open_file_lookup_.find(api_path);
if (it != open_file_lookup_.end()) {
auto *oi = it->second.get();
std::vector<std::uint64_t> handles;
for (const auto &kv : open_handle_lookup_) {
if (kv.second == oi) {
handles.emplace_back(kv.first);
}
}
while (!handles.empty()) {
close(handles.back());
handles.pop_back();
}
}
}
#endif // _WIN32
bool contains_restore(const std::string &api_path) const override {
return dm_.contains_restore(api_path);
}
api_error derive_file_size(const std::string &api_path, std::uint64_t &file_size) {
auto ret = api_error::success;
file_size = 0u;
if (provider_.is_file(api_path)) {
unique_recur_mutex_lock l(open_file_mutex_);
const auto it = open_file_lookup_.find(api_path);
if (it == open_file_lookup_.end()) {
l.unlock();
ret = provider_.get_file_size(api_path, file_size);
} else {
file_size = open_file_lookup_[api_path]->item.size;
}
}
return ret;
}
api_error derive_item_data(const std::string &api_path, api_meta_map &meta) {
auto ret = api_error::success;
meta.clear();
unique_recur_mutex_lock l(open_file_mutex_);
const auto it = open_file_lookup_.find(api_path);
if (it == open_file_lookup_.end()) {
l.unlock();
ret = provider_.get_item_meta(api_path, meta);
} else {
meta = open_file_lookup_[api_path]->meta;
}
return ret;
}
api_error derive_item_data(const directory_item &di, std::uint64_t &file_size,
api_meta_map &meta) {
return derive_item_data(di.api_path, di.directory, file_size, meta);
}
api_error derive_item_data(const std::string &api_path, const bool &directory,
std::uint64_t &file_size, api_meta_map &meta) {
auto ret = api_error::success;
meta.clear();
file_size = 0;
unique_recur_mutex_lock l(open_file_mutex_);
const auto it = open_file_lookup_.find(api_path);
if (it == open_file_lookup_.end()) {
l.unlock();
ret = provider_.get_item_meta(api_path, meta);
if ((ret == api_error::success) && not directory) {
ret = provider_.get_file_size(api_path, file_size);
}
} else {
meta = open_file_lookup_[api_path]->meta;
if (not directory) {
file_size = open_file_lookup_[api_path]->item.size;
}
}
return ret;
}
bool evict_file(const std::string &api_path) override {
auto ret = false;
auto allow_eviction = true;
// Ensure enough time has passed since file was closed
{
mutex_lock l(last_close_mutex_);
const auto it = last_close_lookup_.find(api_path);
if (it != last_close_lookup_.end()) {
allow_eviction = remove_if_expired(api_path, it->second);
}
}
if (allow_eviction) {
recur_mutex_lock l(open_file_mutex_);
// Ensure item is not in upload retry queue
if (not retry_db_.exists(api_path) && (get_open_count(api_path) == 0u)) {
// Ensure item is not currently downloading
if (not dm_.is_processing(api_path)) {
filesystem_item fsi{};
if (provider_.get_filesystem_item(api_path, false, fsi) == api_error::success) {
std::uint64_t file_size = 0u;
if ((ret = (utils::file::get_file_size(fsi.source_path, file_size) &&
retry_delete_file(fsi.source_path)))) {
global_data::instance().update_used_space(file_size, 0, true);
event_system::instance().raise<filesystem_item_evicted>(fsi.api_path,
fsi.source_path);
}
}
}
}
}
return ret;
}
void force_schedule_upload(const filesystem_item &fsi) override {
recur_mutex_lock l(open_file_mutex_);
filesystem_item *fsi_ptr = nullptr;
if (get_open_file(fsi.api_path, fsi_ptr)) {
handle_file_upload(*fsi_ptr);
} else {
handle_file_upload(&fsi);
}
}
directory_item_list get_directory_items(const std::string &api_path) const override {
directory_item_list list;
provider_.get_directory_items(api_path, list);
return list;
}
std::uint64_t get_open_count(const std::string &api_path) const override {
std::uint64_t ret = 0u;
recur_mutex_lock l(open_file_mutex_);
const auto it = open_file_lookup_.find(api_path);
if (it != open_file_lookup_.end()) {
ret = it->second->item.open_data.size();
}
return ret;
}
bool get_open_file(const std::string &api_path, filesystem_item *&fsi) override {
auto ret = false;
recur_mutex_lock l(open_file_mutex_);
const auto it = open_file_lookup_.find(api_path);
if (it != open_file_lookup_.end()) {
fsi = &it->second->item;
ret = true;
}
return ret;
}
bool get_open_file(const std::uint64_t &handle, filesystem_item *&fsi) {
auto ret = false;
recur_mutex_lock l(open_file_mutex_);
const auto it = open_handle_lookup_.find(handle);
if (it != open_handle_lookup_.end()) {
fsi = &it->second->item;
ret = true;
}
return ret;
}
std::unordered_map<std::string, std::size_t> get_open_files() const override {
std::unordered_map<std::string, std::size_t> ret;
unique_recur_mutex_lock l(open_file_mutex_);
for (const auto &kv : open_file_lookup_) {
ret.insert({kv.first, kv.second->item.open_data.size()});
}
l.unlock();
return ret;
}
api_error open(const filesystem_item &fsi, std::uint64_t &handle) override {
auto ret = api_error::success;
recur_mutex_lock l(open_file_mutex_);
if (open_file_lookup_.find(fsi.api_path) == open_file_lookup_.end()) {
api_meta_map meta;
if ((ret = provider_.get_item_meta(fsi.api_path, meta)) == api_error::success) {
auto oi = std::make_shared<open_file_info>();
oi->meta = meta;
oi->item = fsi;
oi->item.lock = std::make_shared<std::recursive_mutex>();
open_file_lookup_.insert({fsi.api_path, oi});
event_system::instance().raise<filesystem_item_opened>(
oi->item.api_path, oi->item.source_path, oi->item.directory);
}
}
if (ret == api_error::success) {
ret = Open(fsi.api_path, fsi.directory, utils::file::get_read_write_open_flags(), handle);
}
return ret;
}
api_error Open(const std::string &api_path, const bool &directory, const flags &f,
std::uint64_t &handle) {
auto ret = api_error::success;
recur_mutex_lock l(open_file_mutex_);
if (open_file_lookup_.find(api_path) == open_file_lookup_.end()) {
api_meta_map meta;
if ((ret = provider_.get_item_meta(api_path, meta)) == api_error::success) {
auto oi = std::make_shared<open_file_info>();
oi->meta = meta;
if ((ret = provider_.get_filesystem_item(api_path, directory, oi->item)) ==
api_error::success) {
open_file_lookup_.insert({api_path, oi});
event_system::instance().raise<filesystem_item_opened>(
oi->item.api_path, oi->item.source_path, oi->item.directory);
}
}
}
if (ret == api_error::success) {
auto *oi = open_file_lookup_[api_path].get();
auto &fsi = oi->item;
if (fsi.directory == directory) {
handle = get_next_handle();
fsi.open_data.insert({handle, f});
open_handle_lookup_.insert({handle, oi});
} else {
ret = directory ? api_error::file_exists : api_error::directory_exists;
}
}
return ret;
}
bool perform_locked_operation(locked_operation_callback locked_operation) override {
recur_mutex_lock l(open_file_mutex_);
return locked_operation(*this, provider_);
}
api_error remove_file(const std::string &api_path) {
recur_mutex_lock l(open_file_mutex_);
filesystem_item fsi{};
auto ret = api_error::file_in_use;
if ((get_open_count(api_path) == 0u) &&
((ret = provider_.get_filesystem_item(api_path, false, fsi)) == api_error::success) &&
((ret = provider_.remove_file(api_path)) == api_error::success)) {
std::uint64_t file_size = 0u;
utils::file::get_file_size(fsi.source_path, file_size);
if (retry_delete_file(fsi.source_path) && file_size) {
global_data::instance().update_used_space(file_size, 0, false);
}
}
return ret;
}
#ifdef HAS_SETXATTR
api_error remove_xattr_meta(const std::string &api_path, const std::string &name) {
auto ret = api_error::xattr_not_found;
if (utils::collection_excludes(META_USED_NAMES, name)) {
unique_recur_mutex_lock l(open_file_mutex_);
if (open_file_lookup_.find(api_path) == open_file_lookup_.end()) {
l.unlock();
ret = provider_.remove_item_meta(api_path, name);
} else if (open_file_lookup_[api_path]->meta.find(name) !=
open_file_lookup_[api_path]->meta.end()) {
open_file_lookup_[api_path]->item.meta_changed = true;
open_file_lookup_[api_path]->meta.erase(name);
ret = api_error::success;
}
}
return ret;
}
#endif
api_error rename_directory(const std::string &from_api_path, const std::string &to_api_path) {
unique_recur_mutex_lock l(open_file_mutex_);
auto ret = api_error::not_implemented;
if (provider_.is_rename_supported()) {
ret = api_error::directory_not_found;
// Ensure source directory exists
if (provider_.is_directory(from_api_path)) {
ret = api_error::directory_exists;
// Ensure destination directory does not exist
if (not provider_.is_directory(to_api_path)) {
ret = api_error::file_exists;
// Ensure destination is not a file
if (not provider_.is_file(from_api_path)) {
ret = api_error::directory_not_found;
// Ensure parent destination directory exists
directory_item_list list;
if (provider_.is_directory(utils::path::get_parent_api_path(to_api_path)) &&
((ret = provider_.create_directory_clone_source_meta(from_api_path, to_api_path)) ==
api_error::success) &&
((ret = provider_.get_directory_items(from_api_path, list)) ==
api_error::success)) {
// Rename all items - directories MUST BE returned first
for (std::size_t i = 0u; (ret == api_error::success) && (i < list.size()); i++) {
const auto &api_path = list[i].api_path;
if ((api_path != ".") && (api_path != "..")) {
const auto old_api_path = api_path;
const auto new_api_path = utils::path::create_api_path(utils::path::combine(
to_api_path, {old_api_path.substr(from_api_path.size())}));
if (list[i].directory) {
ret = rename_directory(old_api_path, new_api_path);
} else {
ret = rename_file(old_api_path, new_api_path);
}
}
}
if (ret == api_error::success) {
swap_renamed_items(from_api_path, to_api_path);
ret = provider_.remove_directory(from_api_path);
}
}
}
}
}
}
return ret;
}
api_error rename_file(const std::string &from_api_path, const std::string &to_api_path,
const bool &overwrite = true) {
auto ret = api_error::not_implemented;
if (provider_.is_rename_supported()) {
// Don't rename if paths are the same
if ((ret = (from_api_path == to_api_path) ? api_error::file_exists : api_error::success) ==
api_error::success) {
retry_db_.pause();
unique_recur_mutex_lock l(open_file_mutex_);
// Check allow overwrite if file exists
if (not overwrite && provider_.is_file(to_api_path)) {
l.unlock();
ret = api_error::file_exists;
} else {
// Don't rename if source does not exist
if ((ret = provider_.is_file(from_api_path)
? api_error::success
: api_error::item_not_found) == api_error::success) {
// Don't rename if destination file is downloading
if ((ret = dm_.is_processing(to_api_path) ? api_error::file_in_use
: api_error::success) == api_error::success) {
// Don't rename if destination file has open handles
ret = api_error::file_in_use;
if (get_open_count(to_api_path) == 0u) {
if (provider_.is_file(
to_api_path)) { // Handle destination file exists (should overwrite)
filesystem_item fsi{};
if ((ret = get_filesystem_item(to_api_path, false, fsi)) == api_error::success) {
ret = api_error::os_error;
std::uint64_t file_size = 0u;
if (utils::file::get_file_size(fsi.source_path, file_size)) {
ret = provider_.remove_file(to_api_path);
if ((ret == api_error::success) || (ret == api_error::item_not_found)) {
if (retry_delete_file(fsi.source_path) && file_size) {
global_data::instance().update_used_space(file_size, 0, false);
}
ret = handle_file_rename(from_api_path, to_api_path);
}
}
}
l.unlock();
} else if (provider_.is_directory(to_api_path)) { // Handle destination is directory
l.unlock();
ret = api_error::directory_exists;
} else if (provider_.is_directory(utils::path::get_parent_api_path(
to_api_path))) { // Handle rename if destination directory exists
ret = handle_file_rename(from_api_path, to_api_path);
l.unlock();
} else { // Destination directory not found
l.unlock();
ret = api_error::directory_not_found;
}
}
} else if (provider_.is_directory(from_api_path)) {
l.unlock();
ret = api_error::directory_exists;
}
}
}
retry_db_.resume();
}
}
return ret;
}
api_error set_item_meta(const std::string &api_path, const std::string &key,
const std::string &value) override {
unique_recur_mutex_lock l(open_file_mutex_);
if (open_file_lookup_.find(api_path) == open_file_lookup_.end()) {
l.unlock();
return provider_.set_item_meta(api_path, key, value);
}
if (open_file_lookup_[api_path]->meta[key] != value) {
open_file_lookup_[api_path]->item.meta_changed = true;
open_file_lookup_[api_path]->meta[key] = value;
}
return api_error::success;
}
api_error set_item_meta(const std::string &api_path, const api_meta_map &meta) {
auto ret = api_error::success;
auto it = meta.begin();
for (std::size_t i = 0u; (ret == api_error::success) && (i < meta.size()); i++) {
ret = set_item_meta(api_path, it->first, it->second);
it++;
}
return ret;
}
void start() {
mutex_lock start_stop_lock(start_stop_mutex_);
if (not retry_thread_) {
stop_requested_ = false;
retry_thread_ = std::make_unique<std::thread>([this] {
while (not stop_requested_) {
const auto processed = retry_db_.process_all([this](const std::string &api_path) -> bool {
auto success = false;
event_system::instance().raise<failed_upload_retry>(api_path);
unique_recur_mutex_lock open_file_lock(open_file_mutex_);
if (open_file_lookup_.find(api_path) == open_file_lookup_.end()) {
open_file_lock.unlock();
filesystem_item fsi{};
const auto res = provider_.get_filesystem_item(api_path, false, fsi);
if ((res == api_error::success) ||
((res == api_error::item_not_found) && provider_.is_file(api_path))) {
if (provider_.upload_file(api_path, fsi.source_path, fsi.encryption_token) ==
api_error::success) {
success = true;
}
}
// Remove deleted files
if (not success && not provider_.is_file(api_path)) {
success = true;
}
} else {
// File is open, so force re-upload on close
open_file_lookup_[api_path]->item.changed = true;
open_file_lock.unlock();
success = true;
}
return success;
});
if (not processed && not stop_requested_) {
unique_mutex_lock retryLock(retry_mutex_);
if (not stop_requested_) {
retry_notify_.wait_for(retryLock, 5s);
}
}
}
});
}
}
void stop() {
mutex_lock start_stop_lock(start_stop_mutex_);
if (retry_thread_) {
event_system::instance().raise<service_shutdown>("open_file_table");
stop_requested_ = true;
unique_mutex_lock retry_lock(retry_mutex_);
retry_notify_.notify_all();
retry_lock.unlock();
retry_thread_->join();
retry_thread_.reset();
}
}
void update_directory_item(directory_item &di) const override {
recur_mutex_lock l(open_file_mutex_);
const auto it = open_file_lookup_.find(di.api_path);
if (it != open_file_lookup_.end()) {
const auto &ofi = open_file_lookup_.at(di.api_path);
di.meta = ofi->meta;
if (not di.directory) {
di.size = ofi->item.size;
}
}
}
};
} // namespace repertory
#endif // INCLUDE_DRIVES_OPEN_FILE_TABLE_HPP_

View File

@ -0,0 +1,44 @@
/*
Copyright <2018-2022> <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_DRIVES_REMOTE_I_REMOTEJSON_HPP_
#define INCLUDE_DRIVES_REMOTE_I_REMOTEJSON_HPP_
#include "common.hpp"
#include "comm/packet/packet.hpp"
namespace repertory {
class i_remote_json {
INTERFACE_SETUP(i_remote_json);
public:
virtual packet::error_type json_create_directory_snapshot(const std::string &path,
json &json_data) = 0;
virtual packet::error_type json_read_directory_snapshot(const std::string &path,
const remote::file_handle &handle,
const std::uint32_t &page,
json &json_data) = 0;
virtual packet::error_type
json_release_directory_snapshot(const std::string &path,
const remote::file_handle &handle) = 0;
};
} // namespace repertory
#endif // INCLUDE_DRIVES_REMOTE_I_REMOTEJSON_HPP_

View File

@ -0,0 +1,95 @@
/*
Copyright <2018-2022> <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_DRIVES_REMOTE_REMOTE_OPEN_FILE_TABLE_HPP_
#define INCLUDE_DRIVES_REMOTE_REMOTE_OPEN_FILE_TABLE_HPP_
#include "common.hpp"
#include "types/remote.hpp"
#include "types/repertory.hpp"
namespace repertory {
class remote_open_file_table {
protected:
remote_open_file_table() = default;
virtual ~remote_open_file_table() = default;
protected:
struct compat_open_info {
std::size_t count = 0u;
std::string client_id = "";
};
struct open_info {
std::size_t count = 0u;
std::string client_id = "";
PVOID directory_buffer = nullptr;
std::string path;
};
private:
std::unordered_map<remote::file_handle, compat_open_info> compat_lookup_;
std::mutex compat_mutex_;
std::unordered_map<std::string, std::vector<void *>> directory_lookup_;
std::mutex directory_mutex_;
std::unordered_map<OSHandle, open_info> file_lookup_;
std::mutex file_mutex_;
protected:
void add_directory(const std::string &client_id, void *dir);
void close_all(const std::string &client_id);
virtual void delete_open_directory(void *dir) = 0;
#ifdef _WIN32
bool get_directory_buffer(const OSHandle &handle, PVOID *&buffer);
#endif
bool get_open_info(const OSHandle &handle, open_info &oi);
std::string get_open_file_path(const OSHandle &handle);
bool has_open_directory(const std::string &client_id, void *dir);
int has_compat_open_info(const remote::file_handle &handle, const int &error_return);
template <typename error_type>
error_type has_open_info(const OSHandle &handle, const error_type &error_return) {
mutex_lock file_lock(file_mutex_);
return ((file_lookup_.find(handle) == file_lookup_.end()) ? error_return : 0);
}
void remove_compat_open_info(const remote::file_handle &handle);
bool remove_directory(const std::string &client_id, void *dir);
void remove_open_info(const OSHandle &handle);
void set_client_id(const OSHandle &handle, const std::string &client_id);
void set_compat_client_id(const remote::file_handle &handle, const std::string &client_id);
void set_compat_open_info(const remote::file_handle &handle);
void set_open_info(const OSHandle &handle, open_info oi);
};
} // namespace repertory
#endif // INCLUDE_DRIVES_REMOTE_REMOTE_OPEN_FILE_TABLE_HPP_

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,61 @@
/*
Copyright <2018-2022> <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_DRIVES_WINFSP_I_WINFSP_DRIVE_HPP_
#define INCLUDE_DRIVES_WINFSP_I_WINFSP_DRIVE_HPP_
#ifdef _WIN32
#include "common.hpp"
#include "types/remote.hpp"
#include "types/repertory.hpp"
namespace repertory {
class i_winfsp_drive {
INTERFACE_SETUP(i_winfsp_drive);
public:
virtual std::uint64_t get_directory_item_count(const std::string &api_path) const = 0;
virtual directory_item_list get_directory_items(const std::string &api_path) const = 0;
virtual std::uint64_t get_file_size(const std::string &api_path) const = 0;
virtual api_error get_item_meta(const std::string &api_path, const std::string &name,
std::string &value) const = 0;
virtual api_error get_item_meta(const std::string &api_path, api_meta_map &meta) const = 0;
virtual NTSTATUS get_security_by_name(PWSTR file_name, PUINT32 attributes,
PSECURITY_DESCRIPTOR descriptor,
std::uint64_t *descriptor_size) = 0;
virtual std::uint64_t get_total_drive_space() const = 0;
virtual std::uint64_t get_total_item_count() const = 0;
virtual std::uint64_t get_used_drive_space() const = 0;
virtual void get_volume_info(UINT64 &total_size, UINT64 &free_size,
std::string &volume_label) const = 0;
virtual api_error populate_file_info(const std::string &api_path, remote::file_info &fi) = 0;
};
} // namespace repertory
#endif // _WIN32
#endif // INCLUDE_DRIVES_WINFSP_I_WINFSP_DRIVE_HPP_

View File

@ -0,0 +1,94 @@
/*
Copyright <2018-2022> <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_DRIVES_WINFSP_REMOTEWINFSP_I_REMOTE_INSTANCE_HPP_
#define INCLUDE_DRIVES_WINFSP_REMOTEWINFSP_I_REMOTE_INSTANCE_HPP_
#include "common.hpp"
#include "drives/remote/i_remote_json.hpp"
namespace repertory::remote_winfsp {
class i_remote_instance : public virtual i_remote_json {
INTERFACE_SETUP(i_remote_instance);
public:
virtual packet::error_type winfsp_can_delete(PVOID fileDesc, PWSTR fileName) = 0;
virtual packet::error_type winfsp_cleanup(PVOID fileDesc, PWSTR fileName, UINT32 flags,
BOOLEAN &wasClosed) = 0;
virtual packet::error_type winfsp_close(PVOID fileDesc) = 0;
virtual packet::error_type winfsp_create(PWSTR fileName, UINT32 createOptions,
UINT32 grantedAccess, UINT32 fileAttributes,
UINT64 allocationSize, PVOID *fileDesc,
remote::file_info *fileInfo, std::string &normalizedName,
BOOLEAN &exists) = 0;
virtual packet::error_type winfsp_flush(PVOID fileDesc, remote::file_info *fileInfo) = 0;
virtual packet::error_type winfsp_get_dir_buffer(PVOID fileDesc, PVOID *&ptr) = 0;
virtual packet::error_type winfsp_get_file_info(PVOID fileDesc, remote::file_info *fileInfo) = 0;
virtual packet::error_type winfsp_get_security_by_name(PWSTR fileName, PUINT32 fileAttributes,
std::uint64_t *securityDescriptorSize,
std::wstring &strDescriptor) = 0;
virtual packet::error_type winfsp_get_volume_info(UINT64 &totalSize, UINT64 &freeSize,
std::string &volumeLabel) = 0;
virtual packet::error_type winfsp_mounted(const std::wstring &location) = 0;
virtual packet::error_type winfsp_open(PWSTR fileName, UINT32 createOptions, UINT32 grantedAccess,
PVOID *fileDesc, remote::file_info *fileInfo,
std::string &normalizedName) = 0;
virtual packet::error_type winfsp_overwrite(PVOID fileDesc, UINT32 fileAttributes,
BOOLEAN replaceFileAttributes, UINT64 allocationSize,
remote::file_info *fileInfo) = 0;
virtual packet::error_type winfsp_read(PVOID fileDesc, PVOID buffer, UINT64 offset, UINT32 length,
PUINT32 bytesTransferred) = 0;
virtual packet::error_type winfsp_read_directory(PVOID fileDesc, PWSTR pattern, PWSTR marker,
json &itemList) = 0;
virtual packet::error_type winfsp_rename(PVOID fileDesc, PWSTR fileName, PWSTR newFileName,
BOOLEAN replaceIfExists) = 0;
virtual packet::error_type winfsp_set_basic_info(PVOID fileDesc, UINT32 fileAttributes,
UINT64 creationTime, UINT64 lastAccessTime,
UINT64 lastWriteTime, UINT64 changeTime,
remote::file_info *fileInfo) = 0;
virtual packet::error_type winfsp_set_file_size(PVOID fileDesc, UINT64 newSize,
BOOLEAN setAllocationSize,
remote::file_info *fileInfo) = 0;
virtual packet::error_type winfsp_unmounted(const std::wstring &location) = 0;
virtual packet::error_type winfsp_write(PVOID fileDesc, PVOID buffer, UINT64 offset,
UINT32 length, BOOLEAN writeToEndOfFile,
BOOLEAN constrainedIo, PUINT32 bytesTransferred,
remote::file_info *fileInfo) = 0;
};
typedef std::function<std::unique_ptr<i_remote_instance>()> remote_instance_factory;
} // namespace repertory::remote_winfsp
#endif // INCLUDE_DRIVES_WINFSP_REMOTEWINFSP_I_REMOTE_INSTANCE_HPP_

View File

@ -0,0 +1,125 @@
/*
Copyright <2018-2022> <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_DRIVES_WINFSP_REMOTEWINFSP_REMOTE_CLIENT_HPP_
#define INCLUDE_DRIVES_WINFSP_REMOTEWINFSP_REMOTE_CLIENT_HPP_
#include "common.hpp"
#include "comm/packet/packet.hpp"
#include "comm/packet/packet_client.hpp"
#include "drives/winfsp/remotewinfsp/i_remote_instance.hpp"
#include "drives/remote/remote_open_file_table.hpp"
namespace repertory {
class app_config;
namespace remote_winfsp {
class remote_client final : public remote_open_file_table, public virtual i_remote_instance {
public:
explicit remote_client(const app_config &config);
private:
const app_config &config_;
packet_client packet_client_;
private:
#ifdef _WIN32
#define to_handle(x) (x)
#else
static OSHandle to_handle(PVOID file_desc) {
return static_cast<OSHandle>(reinterpret_cast<std::uint64_t>(file_desc));
}
#endif
protected:
void delete_open_directory(void * /*dir*/) override {}
public:
packet::error_type json_create_directory_snapshot(const std::string &path,
json &json_data) override;
packet::error_type json_read_directory_snapshot(const std::string &path,
const remote::file_handle &handle,
const std::uint32_t &page,
json &json_data) override;
packet::error_type json_release_directory_snapshot(const std::string &path,
const remote::file_handle &handle) override;
packet::error_type winfsp_can_delete(PVOID file_desc, PWSTR file_name) override;
packet::error_type winfsp_cleanup(PVOID file_desc, PWSTR file_name, UINT32 flags,
BOOLEAN &was_closed) override;
packet::error_type winfsp_close(PVOID file_desc) override;
packet::error_type winfsp_create(PWSTR file_name, UINT32 create_options, UINT32 granted_access,
UINT32 attributes, UINT64 allocation_size, PVOID *file_desc,
remote::file_info *file_info, std::string &normalized_name,
BOOLEAN &exists) override;
packet::error_type winfsp_flush(PVOID file_desc, remote::file_info *file_info) override;
packet::error_type winfsp_get_dir_buffer(PVOID file_desc, PVOID *&ptr) override;
packet::error_type winfsp_get_file_info(PVOID file_desc, remote::file_info *file_info) override;
packet::error_type winfsp_get_security_by_name(PWSTR file_name, PUINT32 attributes,
std::uint64_t *descriptor_size,
std::wstring &string_descriptor) override;
packet::error_type winfsp_get_volume_info(UINT64 &total_size, UINT64 &free_size,
std::string &volume_label) override;
packet::error_type winfsp_mounted(const std::wstring &location) override;
packet::error_type winfsp_open(PWSTR file_name, UINT32 create_options, UINT32 granted_access,
PVOID *file_desc, remote::file_info *file_info,
std::string &normalized_name) override;
packet::error_type winfsp_overwrite(PVOID file_desc, UINT32 attributes,
BOOLEAN replace_attributes, UINT64 allocation_size,
remote::file_info *file_info) override;
packet::error_type winfsp_read(PVOID file_desc, PVOID buffer, UINT64 offset, UINT32 length,
PUINT32 bytes_transferred) override;
packet::error_type winfsp_read_directory(PVOID file_desc, PWSTR pattern, PWSTR marker,
json &itemList) override;
packet::error_type winfsp_rename(PVOID file_desc, PWSTR file_name, PWSTR new_file_name,
BOOLEAN replace_if_exists) override;
packet::error_type 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) override;
packet::error_type winfsp_set_file_size(PVOID file_desc, UINT64 new_size,
BOOLEAN set_allocation_size,
remote::file_info *file_info) override;
packet::error_type winfsp_unmounted(const std::wstring &location) override;
packet::error_type winfsp_write(PVOID file_desc, PVOID buffer, UINT64 offset, UINT32 length,
BOOLEAN write_to_end, BOOLEAN constrained_io,
PUINT32 bytes_transferred, remote::file_info *file_info) override;
};
} // namespace remote_winfsp
} // namespace repertory
#endif // INCLUDE_DRIVES_WINFSP_REMOTEWINFSP_REMOTE_CLIENT_HPP_

View File

@ -0,0 +1,241 @@
/*
Copyright <2018-2022> <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.
*/
// NOTE: Most of the WinFSP pass-through code has been modified from:
// https://github.com/billziss-gh/winfsp/blob/master/tst/passthrough-cpp/passthrough-cpp.cpp
#ifndef INCLUDE_DRIVES_WINFSP_REMOTEWINFSP_REMOTE_SERVER_HPP_
#define INCLUDE_DRIVES_WINFSP_REMOTEWINFSP_REMOTE_SERVER_HPP_
#ifdef _WIN32
#include "common.hpp"
#include "comm/packet/packet.hpp"
#include "drives/remote/remote_server_base.hpp"
#include "drives/winfsp/i_winfsp_drive.hpp"
namespace repertory {
class app_config;
namespace remote_winfsp {
class remote_server final : public virtual remote_server_base<i_winfsp_drive> {
public:
remote_server(app_config &config, i_winfsp_drive &drive, const std::string &mount_location)
: remote_server_base(config, drive, mount_location) {}
private:
std::string construct_path(std::string path);
packet::error_type populate_file_info(const std::string &api_path, remote::file_info &file_info);
void populate_stat(const char *path, const bool &directory, remote::stat &st,
const struct _stat64 &st1);
public:
// FUSE Layer
packet::error_type fuse_access(const char *path, const std::int32_t &mask) override;
packet::error_type fuse_chflags(const char *path, const std::uint32_t &flags) override;
packet::error_type fuse_chmod(const char *path, const remote::file_mode &mode) override;
packet::error_type fuse_chown(const char *path, const remote::user_id &uid,
const remote::group_id &gid) override;
packet::error_type fuse_destroy() override;
/*packet::error_type fuse_fallocate(const char *path, const std::int32_t &mode,
const remote::file_offset &offset,
const remote::file_offset &length,
const remote::file_handle &handle) override ;*/
packet::error_type fuse_fgetattr(const char *path, remote::stat &st, bool &directory,
const remote::file_handle &handle) override;
packet::error_type fuse_fsetattr_x(const char *path, const remote::setattr_x &attr,
const remote::file_handle &handle) override;
packet::error_type fuse_fsync(const char *path, const std::int32_t &datasync,
const remote::file_handle &handle) override;
packet::error_type fuse_ftruncate(const char *path, const remote::file_offset &size,
const remote::file_handle &handle) override;
packet::error_type fuse_getattr(const char *path, remote::stat &st, bool &directory) override;
/*packet::error_type fuse_getxattr(const char *path, const char *name, char *value,
const remote::file_size &size) override ;
packet::error_type fuse_getxattrOSX(const char *path, const char *name, char *value,
const remote::file_size &size,
const std::uint32_t &position) override ;*/
packet::error_type fuse_getxtimes(const char *path, remote::file_time &bkuptime,
remote::file_time &crtime) override;
packet::error_type fuse_init() override;
/*packet::error_type fuse_listxattr(const char *path, char *buffer,
const remote::file_size &size) override ;*/
packet::error_type fuse_mkdir(const char *path, const remote::file_mode &mode) override;
packet::error_type fuse_opendir(const char *path, remote::file_handle &handle) override;
packet::error_type fuse_create(const char *path, const remote::file_mode &mode,
const remote::open_flags &flags,
remote::file_handle &handle) override;
packet::error_type fuse_open(const char *path, const remote::open_flags &flags,
remote::file_handle &handle) override;
packet::error_type fuse_read(const char *path, char *buffer, const remote::file_size &read_size,
const remote::file_offset &read_offset,
const remote::file_handle &handle) override;
packet::error_type fuse_rename(const char *from, const char *to) override;
packet::error_type fuse_write(const char *path, const char *buffer,
const remote::file_size &write_size,
const remote::file_offset &write_offset,
const remote::file_handle &handle) override;
packet::error_type fuse_write_base64(const char *path, const char *buffer,
const remote::file_size &write_size,
const remote::file_offset &write_offset,
const remote::file_handle &handle) override;
packet::error_type fuse_readdir(const char *path, const remote::file_offset &offset,
const remote::file_handle &handle,
std::string &item_path) override;
packet::error_type fuse_release(const char *path, const remote::file_handle &handle) override;
packet::error_type fuse_releasedir(const char *path, const remote::file_handle &handle) override;
/*packet::error_type fuse_removexattr(const char *path, const char *name) override ;*/
packet::error_type fuse_rmdir(const char *path) override;
packet::error_type fuse_setattr_x(const char *path, remote::setattr_x &attr) override;
packet::error_type fuse_setbkuptime(const char *path, const remote::file_time &bkuptime) override;
packet::error_type fuse_setchgtime(const char *path, const remote::file_time &chgtime) override;
packet::error_type fuse_setcrtime(const char *path, const remote::file_time &crtime) override;
packet::error_type fuse_setvolname(const char *volname) override;
/*packet::error_type fuse_setxattr(const char *path, const char *name, const char *value,
const remote::file_size &size,
const std::int32_t &flags) override ;
packet::error_type fuse_setxattr_osx(const char *path, const char *name, const char *value,
const remote::file_size &size, const std::int32_t &flags,
const std::uint32_t &position) override ;*/
packet::error_type fuse_statfs(const char *path, const std::uint64_t &frsize,
remote::statfs &st) override;
packet::error_type fuse_statfs_x(const char *path, const std::uint64_t &bsize,
remote::statfs_x &st) override;
packet::error_type fuse_truncate(const char *path, const remote::file_offset &size) override;
packet::error_type fuse_unlink(const char *path) override;
packet::error_type fuse_utimens(const char *path, const remote::file_time *tv,
const std::uint64_t &op0, const std::uint64_t &op1) override;
void set_fuse_uid_gid(const remote::user_id &, const remote::group_id &) override {}
// JSON Layer
packet::error_type json_create_directory_snapshot(const std::string &path,
json &json_data) override;
packet::error_type json_read_directory_snapshot(const std::string &path,
const remote::file_handle &handle,
const std::uint32_t &page,
json &json_data) override;
packet::error_type json_release_directory_snapshot(const std::string &path,
const remote::file_handle &handle) override;
// WinFSP Layer
packet::error_type winfsp_can_delete(PVOID file_desc, PWSTR file_name) override;
packet::error_type winfsp_cleanup(PVOID file_desc, PWSTR file_name, UINT32 flags,
BOOLEAN &was_closed) override;
packet::error_type winfsp_close(PVOID file_desc) override;
packet::error_type winfsp_create(PWSTR file_name, UINT32 create_options, UINT32 granted_access,
UINT32 attributes, UINT64 allocation_size, PVOID *file_desc,
remote::file_info *file_info, std::string &normalized_name,
BOOLEAN &exists) override;
packet::error_type winfsp_flush(PVOID file_desc, remote::file_info *file_info) override;
packet::error_type winfsp_get_dir_buffer(PVOID file_desc, PVOID *&ptr) override;
packet::error_type winfsp_get_file_info(PVOID file_desc, remote::file_info *file_info) override;
packet::error_type winfsp_get_security_by_name(PWSTR file_name, PUINT32 attributes,
std::uint64_t *descriptor_size,
std::wstring &string_descriptor) override;
packet::error_type winfsp_get_volume_info(UINT64 &total_size, UINT64 &free_size,
std::string &volume_label) override;
packet::error_type winfsp_mounted(const std::wstring &location) override;
packet::error_type winfsp_open(PWSTR file_name, UINT32 create_options, UINT32 granted_access,
PVOID *file_desc, remote::file_info *file_info,
std::string &normalized_name) override;
packet::error_type winfsp_overwrite(PVOID file_desc, UINT32 attributes,
BOOLEAN replace_attributes, UINT64 allocation_size,
remote::file_info *file_info) override;
packet::error_type winfsp_read(PVOID file_desc, PVOID buffer, UINT64 offset, UINT32 length,
PUINT32 bytes_transferred) override;
packet::error_type winfsp_read_directory(PVOID file_desc, PWSTR pattern, PWSTR marker,
json &item_list) override;
packet::error_type winfsp_rename(PVOID file_desc, PWSTR file_name, PWSTR new_file_name,
BOOLEAN replace_if_exists) override;
packet::error_type 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) override;
packet::error_type winfsp_set_file_size(PVOID file_desc, UINT64 newSize,
BOOLEAN set_allocation_size,
remote::file_info *file_info) override;
packet::error_type winfsp_unmounted(const std::wstring &location) override;
packet::error_type winfsp_write(PVOID file_desc, PVOID buffer, UINT64 offset, UINT32 length,
BOOLEAN write_to_end, BOOLEAN constrained_io,
PUINT32 bytes_transferred, remote::file_info *file_info) override;
};
} // namespace remote_winfsp
} // namespace repertory
#endif // _WIN32
#endif // INCLUDE_DRIVES_WINFSP_REMOTEWINFSP_REMOTE_SERVER_HPP_

View File

@ -0,0 +1,140 @@
/*
Copyright <2018-2022> <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_DRIVES_WINFSP_REMOTEWINFSP_REMOTE_WINFSP_DRIVE_HPP_
#define INCLUDE_DRIVES_WINFSP_REMOTEWINFSP_REMOTE_WINFSP_DRIVE_HPP_
#ifdef _WIN32
#include "common.hpp"
#include "drives/winfsp/remotewinfsp/i_remote_instance.hpp"
#include "events/event_system.hpp"
namespace repertory {
class app_config;
class lock_data;
class server;
namespace remote_winfsp {
class remote_winfsp_drive final : public virtual FileSystemBase {
E_CONSUMER();
public:
remote_winfsp_drive(app_config &config, lock_data &lockData,
remote_instance_factory remoteInstanceFactory);
~remote_winfsp_drive() override { E_CONSUMER_RELEASE(); }
public:
class winfsp_service : virtual public Service {
public:
winfsp_service(lock_data &lock, remote_winfsp_drive &drive, std::vector<std::string> drive_args,
app_config &config);
~winfsp_service() override = default;
private:
app_config &config_;
lock_data &lock_;
remote_winfsp_drive &drive_;
const std::vector<std::string> drive_args_;
FileSystemHost host_;
protected:
NTSTATUS OnStart(ULONG, PWSTR *) override;
NTSTATUS OnStop() override;
};
private:
app_config &config_;
lock_data &lock_;
remote_instance_factory factory_;
std::unique_ptr<i_remote_instance> remote_instance_;
std::unique_ptr<server> server_;
std::string mount_location_;
private:
void PopulateFileInfo(const json &item, FSP_FSCTL_FILE_INFO &file_info);
static void SetFileInfo(FileInfo &dest, const remote::file_info &src);
public:
NTSTATUS CanDelete(PVOID file_node, PVOID file_desc, PWSTR file_name) override;
VOID Cleanup(PVOID file_node, PVOID file_desc, PWSTR file_name, ULONG flags) override;
VOID Close(PVOID file_node, PVOID file_desc) override;
NTSTATUS Create(PWSTR file_name, UINT32 create_options, UINT32 granted_access, UINT32 attributes,
PSECURITY_DESCRIPTOR descriptor, UINT64 allocation_size, PVOID *file_node,
PVOID *file_desc, OpenFileInfo *ofi) override;
NTSTATUS Flush(PVOID file_node, PVOID file_desc, FileInfo *file_info) override;
NTSTATUS GetFileInfo(PVOID file_node, PVOID file_desc, FileInfo *file_info) override;
NTSTATUS GetSecurityByName(PWSTR file_name, PUINT32 attributes, PSECURITY_DESCRIPTOR descriptor,
SIZE_T *descriptor_size) override;
NTSTATUS GetVolumeInfo(VolumeInfo *volume_info) override;
NTSTATUS Init(PVOID host) override;
int mount(const std::vector<std::string> &drive_args);
NTSTATUS Mounted(PVOID host) override;
NTSTATUS Open(PWSTR file_name, UINT32 create_options, UINT32 granted_access, PVOID *file_node,
PVOID *file_desc, OpenFileInfo *ofi) override;
NTSTATUS Overwrite(PVOID file_node, PVOID file_desc, UINT32 attributes,
BOOLEAN replace_attributes, UINT64 allocation_size,
FileInfo *file_info) override;
NTSTATUS Read(PVOID file_node, PVOID file_desc, PVOID buffer, UINT64 offset, ULONG length,
PULONG bytes_transferred) override;
NTSTATUS ReadDirectory(PVOID file_node, PVOID file_desc, PWSTR pattern, PWSTR marker,
PVOID buffer, ULONG buffer_length, PULONG bytes_transferred) override;
NTSTATUS Rename(PVOID file_node, PVOID file_desc, PWSTR file_name, PWSTR new_file_name,
BOOLEAN replace_if_exists) override;
NTSTATUS SetBasicInfo(PVOID file_node, PVOID file_desc, UINT32 attributes, UINT64 creation_time,
UINT64 last_access_time, UINT64 last_write_time, UINT64 change_time,
FileInfo *file_info) override;
NTSTATUS SetFileSize(PVOID file_node, PVOID file_desc, UINT64 new_size,
BOOLEAN set_allocation_size, FileInfo *file_info) override;
VOID Unmounted(PVOID host) override;
NTSTATUS Write(PVOID file_node, PVOID file_desc, PVOID buffer, UINT64 offset, ULONG length,
BOOLEAN write_to_end, BOOLEAN constrained_io, PULONG bytes_transferred,
FileInfo *file_info) override;
void shutdown() { ::GenerateConsoleCtrlEvent(CTRL_C_EVENT, 0); }
static void display_options(int argc, char *argv[]) {}
static void display_version_information(int argc, char *argv[]) {}
};
} // namespace remote_winfsp
} // namespace repertory
#endif // _WIN32
#endif // INCLUDE_DRIVES_WINFSP_REMOTEWINFSP_REMOTE_WINFSP_DRIVE_HPP_

View File

@ -0,0 +1,177 @@
/*
Copyright <2018-2022> <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_DRIVES_WINFSP_WINFSP_DRIVE_HPP_
#define INCLUDE_DRIVES_WINFSP_WINFSP_DRIVE_HPP_
#ifdef _WIN32
#include "common.hpp"
#include "download/download_manager.hpp"
#include "drives/eviction.hpp"
#include "drives/i_open_file_table.hpp"
#include "drives/open_file_table.hpp"
#include "drives/winfsp/i_winfsp_drive.hpp"
#include "drives/winfsp/remotewinfsp/remote_server.hpp"
#include "events/event_system.hpp"
#include "rpc/server/full_server.hpp"
namespace repertory {
class app_config;
class lock_data;
class i_provider;
class winfsp_drive final : public virtual i_winfsp_drive, public virtual FileSystemBase {
E_CONSUMER();
public:
winfsp_drive(app_config &config, lock_data &lockData, i_provider &provider);
~winfsp_drive() override { E_CONSUMER_RELEASE(); }
private:
class winfsp_service final : virtual public Service {
public:
winfsp_service(lock_data &lock, winfsp_drive &drive, std::vector<std::string> drive_args,
app_config &config);
~winfsp_service() override = default;
private:
lock_data &lock_;
winfsp_drive &drive_;
const std::vector<std::string> drive_args_;
FileSystemHost host_;
app_config &config_;
protected:
NTSTATUS OnStart(ULONG, PWSTR *) override;
NTSTATUS OnStop() override;
};
private:
i_provider &provider_;
app_config &config_;
lock_data &lock_;
std::unique_ptr<full_server> server_;
std::unique_ptr<open_file_table<open_file_data>> oft_;
std::unique_ptr<download_manager> download_manager_;
std::unique_ptr<eviction> eviction_;
std::unique_ptr<remote_winfsp::remote_server> remote_server_;
private:
static std::string parse_mount_location(const std::wstring &mount_location);
void populate_file_info(const std::string &api_path, const std::uint64_t &file_size,
const api_meta_map &meta, FSP_FSCTL_OPEN_FILE_INFO &ofi);
void populate_file_info(const std::uint64_t &file_size, api_meta_map meta,
FSP_FSCTL_FILE_INFO &fi);
static void set_file_info(remote::file_info &dest, const FSP_FSCTL_FILE_INFO &src);
public:
NTSTATUS CanDelete(PVOID file_node, PVOID file_desc, PWSTR file_name) override;
VOID Cleanup(PVOID file_node, PVOID file_desc, PWSTR file_name, ULONG flags) override;
VOID Close(PVOID file_node, PVOID file_desc) override;
NTSTATUS Create(PWSTR file_name, UINT32 create_options, UINT32 granted_access, UINT32 attributes,
PSECURITY_DESCRIPTOR descriptor, UINT64 allocation_size, PVOID *file_node,
PVOID *file_desc, OpenFileInfo *ofi) override;
NTSTATUS Flush(PVOID file_node, PVOID file_desc, FileInfo *file_info) override;
std::uint64_t get_directory_item_count(const std::string &api_path) const override;
directory_item_list get_directory_items(const std::string &api_path) const override;
NTSTATUS GetFileInfo(PVOID file_node, PVOID file_desc, FileInfo *file_info) override;
std::uint64_t get_file_size(const std::string &api_path) const override;
api_error get_item_meta(const std::string &api_path, api_meta_map &meta) const override;
api_error get_item_meta(const std::string &api_path, const std::string &name,
std::string &value) const override;
NTSTATUS get_security_by_name(PWSTR file_name, PUINT32 attributes,
PSECURITY_DESCRIPTOR descriptor,
std::uint64_t *descriptor_size) override;
NTSTATUS GetSecurityByName(PWSTR file_name, PUINT32 attributes, PSECURITY_DESCRIPTOR descriptor,
SIZE_T *descriptor_size) override;
std::uint64_t get_total_drive_space() const override;
std::uint64_t get_total_item_count() const override;
std::uint64_t get_used_drive_space() const override;
void get_volume_info(UINT64 &total_size, UINT64 &free_size,
std::string &volume_label) const override;
NTSTATUS GetVolumeInfo(VolumeInfo *volume_info) override;
NTSTATUS Init(PVOID host) override;
int mount(const std::vector<std::string> &drive_args);
NTSTATUS Mounted(PVOID host) override;
NTSTATUS Open(PWSTR file_name, UINT32 create_options, UINT32 granted_access, PVOID *file_node,
PVOID *file_desc, OpenFileInfo *ofi) override;
NTSTATUS Overwrite(PVOID file_node, PVOID file_desc, UINT32 attributes,
BOOLEAN replace_attributes, UINT64 allocation_size,
FileInfo *file_info) override;
api_error populate_file_info(const std::string &api_path, remote::file_info &file_info) override;
NTSTATUS Read(PVOID file_node, PVOID file_desc, PVOID buffer, UINT64 offset, ULONG length,
PULONG bytes_transferred) override;
NTSTATUS ReadDirectory(PVOID file_node, PVOID file_desc, PWSTR pattern, PWSTR marker,
PVOID buffer, ULONG bufferLength, PULONG bytes_transferred) override;
NTSTATUS Rename(PVOID file_node, PVOID file_desc, PWSTR file_name, PWSTR newFileName,
BOOLEAN replace_if_exists) override;
NTSTATUS SetBasicInfo(PVOID file_node, PVOID file_desc, UINT32 attributes, UINT64 creation_time,
UINT64 last_access_time, UINT64 last_write_time, UINT64 change_time,
FileInfo *file_info) override;
NTSTATUS SetFileSize(PVOID file_node, PVOID file_desc, UINT64 new_size,
BOOLEAN set_allocation_size, FileInfo *file_info) override;
VOID Unmounted(PVOID host) override;
NTSTATUS Write(PVOID file_node, PVOID file_desc, PVOID buffer, UINT64 offset, ULONG length,
BOOLEAN write_to_end, BOOLEAN constrained_io, PULONG bytes_transferred,
FileInfo *file_info) override;
void shutdown() { ::GenerateConsoleCtrlEvent(CTRL_C_EVENT, 0); }
static void display_options(int argc, char *argv[]) {}
static void display_version_information(int argc, char *argv[]) {}
};
} // namespace repertory
#endif // _WIN32
#endif // INCLUDE_DRIVES_WINFSP_WINFSP_DRIVE_HPP_

View File

@ -0,0 +1,51 @@
/*
Copyright <2018-2022> <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_EVENTS_CONSUMERS_CONSOLE_CONSUMER_HPP_
#define INCLUDE_EVENTS_CONSUMERS_CONSOLE_CONSUMER_HPP_
#include "common.hpp"
#include "events/event_system.hpp"
namespace repertory {
class console_consumer final {
E_CONSUMER();
public:
console_consumer() { E_SUBSCRIBE_ALL(process_event); }
public:
~console_consumer() { E_CONSUMER_RELEASE(); }
private:
void process_event(const event &e) {
#ifdef _WIN32
#ifdef _DEBUG
OutputDebugString((e.get_single_line() + "\n").c_str());
#endif
#endif
if (e.get_event_level() == event_level::error) {
std::cerr << e.get_single_line() << std::endl;
} else {
std::cout << e.get_single_line() << std::endl;
}
}
};
} // namespace repertory
#endif // INCLUDE_EVENTS_CONSUMERS_CONSOLE_CONSUMER_HPP_

View File

@ -0,0 +1,62 @@
/*
Copyright <2018-2022> <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_EVENTS_CONSUMERS_LOGGING_CONSUMER_HPP_
#define INCLUDE_EVENTS_CONSUMERS_LOGGING_CONSUMER_HPP_
#include "common.hpp"
#include "events/event_system.hpp"
namespace repertory {
class logging_consumer {
E_CONSUMER();
public:
logging_consumer(const std::string &log_directory, const event_level &level);
~logging_consumer();
private:
const std::uint8_t MAX_LOG_FILES = 5;
const std::uint64_t MAX_LOG_FILE_SIZE = (1024 * 1024 * 5);
private:
event_level event_level_ = event_level::normal;
const std::string log_directory_;
const std::string log_path_;
bool logging_active_ = true;
std::mutex log_mutex_;
std::condition_variable log_notify_;
std::deque<std::shared_ptr<event>> event_queue_;
std::unique_ptr<std::thread> logging_thread_;
FILE *log_file_ = nullptr;
private:
void check_log_roll(const size_t &count);
void close_log_file();
void logging_thread(const bool &drain = false);
void process_event(const event &event);
void reopen_log_file();
};
} // namespace repertory
#endif // INCLUDE_EVENTS_CONSUMERS_LOGGING_CONSUMER_HPP_

63
include/events/event.hpp Normal file
View File

@ -0,0 +1,63 @@
/*
Copyright <2018-2022> <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_EVENTS_EVENT_HPP_
#define INCLUDE_EVENTS_EVENT_HPP_
#include "common.hpp"
namespace repertory {
enum class event_level { error, warn, normal, debug, verbose };
event_level event_level_from_string(std::string level);
std::string event_level_to_string(const event_level &level);
class event {
protected:
explicit event(const bool &allow_async) : allow_async_(allow_async) {}
event(const std::stringstream &ss, json j, const bool &allow_async)
: allow_async_(allow_async), ss_(ss.str()), j_(std::move(j)) {}
public:
virtual ~event() = default;
private:
const bool allow_async_;
protected:
std::stringstream ss_;
json j_;
public:
virtual std::shared_ptr<event> clone() const = 0;
bool get_allow_async() const { return allow_async_; }
virtual event_level get_event_level() const = 0;
json get_json() const { return j_; }
virtual std::string get_name() const = 0;
virtual std::string get_single_line() const = 0;
};
} // namespace repertory
#endif // INCLUDE_EVENTS_EVENT_HPP_

View File

@ -0,0 +1,243 @@
/*
Copyright <2018-2022> <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_EVENTS_EVENT_SYSTEM_HPP_
#define INCLUDE_EVENTS_EVENT_SYSTEM_HPP_
#include "common.hpp"
#include "events/event.hpp"
#include "events/t_event_system.hpp"
#include "utils/string_utils.hpp"
namespace repertory {
typedef t_event_system<event> event_system;
typedef event_system::event_consumer event_consumer;
#define E_CAST(t) ((std::string)t)
#define E_DOUBLE(d) utils::string::from_double(d)
#define E_DOUBLE_PRECISE(d) \
([](const double &d) -> std::string { \
std::stringstream ss; \
ss << std::fixed << std::setprecision(2) << d; \
return ss.str(); \
})(d)
#define E_FROM_BOOL(t) utils::string::from_bool(t)
#define E_FROM_EXCEPTION(e) std::string(e.what() ? e.what() : "")
#define E_FROM_INT32(t) utils::string::from_int32(t)
#define E_FROM_INT64(t) utils::string::from_int64(t)
#define E_FROM_UINT16(t) utils::string::from_uint16(t)
#define E_FROM_STRING_ARRAY(a) \
([](const auto &array) -> std::string { \
std::stringstream ret; \
for (const auto &item : array) { \
ret << (std::string(item) + " "); \
} \
return std::string(ret).TrimRight(); \
})(a)
#define E_PERCENT(d) \
([](const double &d) -> std::string { \
std::stringstream ss; \
ss << std::fixed << std::setprecision(2) << d; \
ss << "%"; \
return ss; \
})(d)
#define E_STRING(t) t
#define E_FROM_UINT8(t) utils::string::from_uint8(t)
#define E_FROM_UINT32(t) utils::string::from_uint32(t)
#define E_FROM_UINT64(t) utils::string::from_uint64(t)
#define E_FROM_SIZE_T(t) std::to_string(t)
#define E_FROM_API_FILE_ERROR(e) api_error_to_string(e)
#define E_PROP(type, name, short_name, ts) \
private: \
void init_##short_name(const type &tv) { \
ss_ << "|" << #short_name << "|" << ts(tv); \
j_[#name] = ts(tv); \
} \
\
public: \
json get_##name() const { return j_[#name]; }
#define E_BEGIN(name, el) \
class name final : public virtual event { \
private: \
name(const std::stringstream &ss, const json &j, const bool &allow_async) \
: event(ss, j, allow_async) {} \
\
public: \
~name() override = default; \
\
public: \
static const event_level level = event_level::el; \
\
public: \
std::string get_name() const override { return #name; } \
\
event_level get_event_level() const override { return name::level; } \
\
std::string get_single_line() const override { \
const auto s = ss_.str(); \
return get_name() + (s.empty() ? "" : s); \
} \
\
std::shared_ptr<event> clone() const override { \
return std::shared_ptr<name>(new name(ss_, j_, get_allow_async())); \
}
#define E_END() }
#define E_SIMPLE(event_name, el, allow_async) \
E_BEGIN(event_name, el) \
public: \
event_name() : event(allow_async) {} \
E_END()
#define E_SIMPLE1(event_name, el, allow_async, type, name, short_name, tc) \
E_BEGIN(event_name, el) \
explicit event_name(const type &tv) : event(allow_async) { init_##short_name(tv); } \
E_PROP(type, name, short_name, tc) \
E_END()
#define E_SIMPLE2(event_name, el, allow_async, type, name, short_name, tc, type2, name2, \
short_name2, tc2) \
E_BEGIN(event_name, el) \
explicit event_name(const type &tv, const type2 &tv2) : event(allow_async) { \
init_##short_name(tv); \
init_##short_name2(tv2); \
} \
E_PROP(type, name, short_name, tc) \
E_PROP(type2, name2, short_name2, tc2) \
E_END()
#define E_SIMPLE3(event_name, el, allow_async, type, name, short_name, tc, type2, name2, \
short_name2, tc2, type3, name3, short_name3, tc3) \
E_BEGIN(event_name, el) \
explicit event_name(const type &tv, const type2 &tv2, const type3 &tv3) : event(allow_async) { \
init_##short_name(tv); \
init_##short_name2(tv2); \
init_##short_name3(tv3); \
} \
E_PROP(type, name, short_name, tc) \
E_PROP(type2, name2, short_name2, tc2) \
E_PROP(type3, name3, short_name3, tc3) \
E_END()
#define E_SIMPLE4(event_name, el, allow_async, type, name, short_name, tc, type2, name2, \
short_name2, tc2, type3, name3, short_name3, tc3, type4, name4, short_name4, \
tc4) \
E_BEGIN(event_name, el) \
explicit event_name(const type &tv, const type2 &tv2, const type3 &tv3, const type4 &tv4) \
: event(allow_async) { \
init_##short_name(tv); \
init_##short_name2(tv2); \
init_##short_name3(tv3); \
init_##short_name4(tv4); \
} \
E_PROP(type, name, short_name, tc) \
E_PROP(type2, name2, short_name2, tc2) \
E_PROP(type3, name3, short_name3, tc3) \
E_PROP(type4, name4, short_name4, tc4) \
E_END()
#define E_SIMPLE5(event_name, el, allow_async, type, name, short_name, tc, type2, name2, \
short_name2, tc2, type3, name3, short_name3, tc3, type4, name4, short_name4, \
tc4, type5, name5, short_name5, tc5) \
E_BEGIN(event_name, el) \
explicit event_name(const type &tv, const type2 &tv2, const type3 &tv3, const type4 &tv4, \
const type5 &tv5) \
: event(allow_async) { \
init_##short_name(tv); \
init_##short_name2(tv2); \
init_##short_name3(tv3); \
init_##short_name4(tv4); \
init_##short_name5(tv5); \
} \
E_PROP(type, name, short_name, tc) \
E_PROP(type2, name2, short_name2, tc2) \
E_PROP(type3, name3, short_name3, tc3) \
E_PROP(type4, name4, short_name4, tc4) \
E_PROP(type5, name5, short_name5, tc5) \
E_END()
#define E_SIMPLE6(event_name, el, allow_async, type, name, short_name, tc, type2, name2, \
short_name2, tc2, type3, name3, short_name3, tc3, type4, name4, short_name4, \
tc4, type5, name5, short_name5, tc5, type6, name6, short_name6, tc6) \
E_BEGIN(event_name, el) \
explicit event_name(const type &tv, const type2 &tv2, const type3 &tv3, const type4 &tv4, \
const type5 &tv5, const type6 &tv6) \
: event(allow_async) { \
init_##short_name(tv); \
init_##short_name2(tv2); \
init_##short_name3(tv3); \
init_##short_name4(tv4); \
init_##short_name5(tv5); \
init_##short_name6(tv6); \
} \
E_PROP(type, name, short_name, tc) \
E_PROP(type2, name2, short_name2, tc2) \
E_PROP(type3, name3, short_name3, tc3) \
E_PROP(type4, name4, short_name4, tc4) \
E_PROP(type5, name5, short_name5, tc5) \
E_PROP(type6, name6, short_name6, tc6) \
E_END()
#define E_SIMPLE7(event_name, el, allow_async, type, name, short_name, tc, type2, name2, \
short_name2, tc2, type3, name3, short_name3, tc3, type4, name4, short_name4, \
tc4, type5, name5, short_name5, tc5, type6, name6, short_name6, tc6, type7, \
name7, short_name7, tc7) \
E_BEGIN(event_name, el) \
explicit event_name(const type &tv, const type2 &tv2, const type3 &tv3, const type4 &tv4, \
const type5 &tv5, const type6 &tv6, const type7 &tv7) \
: event(allow_async) { \
init_##short_name(tv); \
init_##short_name2(tv2); \
init_##short_name3(tv3); \
init_##short_name4(tv4); \
init_##short_name5(tv5); \
init_##short_name6(tv6); \
init_##short_name7(tv7); \
} \
E_PROP(type, name, short_name, tc) \
E_PROP(type2, name2, short_name2, tc2) \
E_PROP(type3, name3, short_name3, tc3) \
E_PROP(type4, name4, short_name4, tc4) \
E_PROP(type5, name5, short_name5, tc5) \
E_PROP(type6, name6, short_name6, tc6) \
E_PROP(type7, name7, short_name7, tc7) \
E_END()
#define E_CONSUMER() \
private: \
std::vector<std::shared_ptr<repertory::event_consumer>> event_consumers_
#define E_CONSUMER_RELEASE() event_consumers_.clear()
#define E_SUBSCRIBE(name, callback) \
event_consumers_.emplace_back( \
std::make_shared<repertory::event_consumer>(#name, [this](const event &e) { callback(e); }))
#define E_SUBSCRIBE_EXACT(name, callback) \
event_consumers_.emplace_back(std::make_shared<repertory::event_consumer>( \
#name, [this](const event &e) { callback(dynamic_cast<const name &>(e)); }))
#define E_SUBSCRIBE_ALL(callback) \
event_consumers_.emplace_back( \
std::make_shared<repertory::event_consumer>([this](const event &e) { callback(e); }))
} // namespace repertory
#endif // INCLUDE_EVENTS_EVENT_SYSTEM_HPP_

417
include/events/events.hpp Normal file
View File

@ -0,0 +1,417 @@
/*
Copyright <2018-2022> <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_EVENTS_EVENTS_HPP_
#define INCLUDE_EVENTS_EVENTS_HPP_
#include "common.hpp"
#include "events/event_system.hpp"
#include "types/repertory.hpp"
#include "utils/utils.hpp"
namespace repertory {
// clang-format off
E_SIMPLE3(cache_file_processed, normal, true,
std::string, api_path, ap, E_STRING,
std::string, source, src, E_STRING,
api_error, result, res, E_FROM_API_FILE_ERROR
);
E_SIMPLE2(comm_auth_begin, normal, true,
std::string, url, url, E_STRING,
std::string, user, user, E_STRING
);
E_SIMPLE4(comm_auth_end, normal, true,
std::string, url, url, E_STRING,
std::string, user, user, E_STRING,
CURLcode, curl, curl, E_FROM_INT32,
int, http, http, E_FROM_INT32
);
E_SIMPLE2(comm_auth_logout_begin, normal, true,
std::string, url, url, E_STRING,
std::string, user, user, E_STRING
);
E_SIMPLE4(comm_auth_logout_end, normal, true,
std::string, url, url, E_STRING,
std::string, user, user, E_STRING,
CURLcode, curl, curl, E_FROM_INT32,
int, http, http, E_FROM_INT32
);
E_SIMPLE1(comm_get_begin, verbose, true,
std::string, url, url, E_STRING
);
E_SIMPLE4(comm_get_end, verbose, true,
std::string, url, url, E_STRING,
CURLcode, curl, curl, E_FROM_INT32,
int, http, http, E_FROM_INT32,
std::string, result, res, E_STRING
);
E_SIMPLE1(comm_get_range_begin, verbose, true,
std::string, url, url, E_STRING
);
E_SIMPLE4(comm_get_range_end, verbose, true,
std::string, url, url, E_STRING,
CURLcode, curl, curl, E_FROM_INT32,
int, http, http, E_FROM_INT32,
std::string, error, err, E_STRING
);
E_SIMPLE1(comm_get_raw_begin, verbose, true,
std::string, url, url, E_STRING
);
E_SIMPLE4(comm_get_raw_end, verbose, true,
std::string, url, url, E_STRING,
CURLcode, curl, curl, E_FROM_INT32,
int, http, http, E_FROM_INT32,
std::string, error, err, E_STRING
);
E_SIMPLE2(comm_post_begin, verbose, true,
std::string, url, url, E_STRING,
std::string, fields, fields, E_STRING
);
E_SIMPLE4(comm_post_end, verbose, true,
std::string, url, url, E_STRING,
CURLcode, curl, curl, E_FROM_INT32,
int, http, http, E_FROM_INT32,
std::string, result, res, E_STRING
);
E_SIMPLE2(comm_duration, normal, true,
std::string, url, url, E_STRING,
std::string, duration, duration, E_STRING
);
E_SIMPLE1(comm_post_file_begin, debug, true,
std::string, url, url, E_STRING
);
E_SIMPLE4(comm_post_file_end, debug, true,
std::string, url, url, E_STRING,
CURLcode, curl, curl, E_FROM_INT32,
int, http, http, E_FROM_INT32,
std::string, error, err, E_STRING
);
E_SIMPLE1(comm_post_multi_part_file_begin, debug, true,
std::string, url, url, E_STRING
);
E_SIMPLE4(comm_post_multi_part_file_end, debug, true,
std::string, url, url, E_STRING,
CURLcode, curl, curl, E_FROM_INT32,
int, http, http, E_FROM_INT32,
std::string, error, err, E_STRING
);
E_SIMPLE4(comm_tus_upload_begin, debug, true,
std::string, file_name, fn, E_STRING,
std::string, url, url, E_STRING,
std::uint64_t, remain, rem, E_FROM_UINT64,
std::uint64_t, offset, off, E_FROM_UINT64
);
E_SIMPLE6(comm_tus_upload_end, debug, true,
std::string, file_name, fn, E_STRING,
std::string, url, url, E_STRING,
std::uint64_t, remain, rem, E_FROM_UINT64,
std::uint64_t, offset, OFF, E_FROM_UINT64,
CURLcode, curl, curl, E_FROM_INT32,
int, http, http, E_FROM_INT32
);
E_SIMPLE2(comm_tus_upload_create_begin, debug, true,
std::string, file_name, fn, E_STRING,
std::string, url, url, E_STRING
);
E_SIMPLE4(comm_tus_upload_create_end, debug, true,
std::string, file_name, fn, E_STRING,
std::string, url, url, E_STRING,
CURLcode, curl, curl, E_FROM_INT32,
int, http, http, E_FROM_INT32
);
E_SIMPLE3(debug_log, debug, true,
std::string, function, func, E_STRING,
std::string, api_path, ap, E_STRING,
std::string, data, data, E_STRING
);
E_SIMPLE1(directory_removed, normal, true,
std::string, api_path, ap, E_STRING
);
E_SIMPLE2(directory_remove_failed, error, true,
std::string, api_path, ap, E_STRING,
std::string, error, err, E_STRING
);
E_SIMPLE2(drive_mount_failed, error, true,
std::string, location, loc, E_STRING,
std::string, result, res, E_STRING
);
E_SIMPLE1(drive_mounted, normal, true,
std::string, location, loc, E_STRING
);
E_SIMPLE1(drive_mount_result, normal, true,
std::string, result, res, E_STRING
);
E_SIMPLE1(drive_unmount_pending, normal, true,
std::string, location, loc, E_STRING
);
E_SIMPLE1(drive_unmounted, normal, true,
std::string, location, loc, E_STRING
);
E_SIMPLE1(event_level_changed, normal, true,
std::string, new_event_level, level, E_STRING
);
E_SIMPLE1(failed_upload_queued, error, true,
std::string, api_path, ap, E_STRING
);
E_SIMPLE1(failed_upload_removed, warn, true,
std::string, api_path, ap, E_STRING
);
E_SIMPLE1(failed_upload_retry, normal, true,
std::string, api_path, ap, E_STRING
);
E_SIMPLE2(file_get_failed, error, true,
std::string, api_path, ap, E_STRING,
std::string, error, err, E_STRING
);
E_SIMPLE1(file_get_api_list_failed, error, true,
std::string, error, err, E_STRING
);
E_SIMPLE1(file_pinned, normal, true,
std::string, api_path, ap, E_STRING
);
E_SIMPLE3(file_read_bytes_failed, error, true,
std::string, api_path, ap, E_STRING,
std::string, error, err, E_STRING,
std::size_t, retry, retry, E_FROM_SIZE_T
);
E_SIMPLE1(file_removed, normal, true,
std::string, api_path, ap, E_STRING
);
E_SIMPLE2(file_removed_externally, warn, true,
std::string, api_path, ap, E_STRING,
std::string, source, src, E_STRING
);
E_SIMPLE2(file_remove_failed, error, true,
std::string, api_path, ap, E_STRING,
std::string, error, err, E_STRING
);
E_SIMPLE3(file_rename_failed, error, true,
std::string, from_api_path, FROM, E_STRING,
std::string, to_api_path, TO, E_STRING,
std::string, error, err, E_STRING
);
E_SIMPLE2(file_get_size_failed, error, true,
std::string, api_path, ap, E_STRING,
std::string, error, err, E_STRING
);
E_SIMPLE3(filesystem_item_added, normal, true,
std::string, api_path, ap, E_STRING,
std::string, parent, parent, E_STRING,
bool, directory, dir, E_FROM_BOOL
);
E_SIMPLE4(filesystem_item_closed, verbose, true,
std::string, api_path, ap, E_STRING,
std::string, source, src, E_STRING,
bool, directory, dir, E_FROM_BOOL,
bool, changed, changed, E_FROM_BOOL
);
E_SIMPLE5(filesystem_item_handle_closed, verbose, true,
std::string, api_path, ap, E_STRING,
std::uint64_t, handle, handle, E_FROM_UINT64,
std::string, source, src, E_STRING,
bool, directory, dir, E_FROM_BOOL,
bool, changed, changed, E_FROM_BOOL
);
E_SIMPLE2(filesystem_item_evicted, normal, true,
std::string, api_path, ap, E_STRING,
std::string, source, src, E_STRING
);
E_SIMPLE2(filesystem_item_get_failed, error, true,
std::string, api_path, ap, E_STRING,
std::string, error, err, E_STRING
);
E_SIMPLE3(filesystem_item_opened, verbose, true,
std::string, api_path, ap, E_STRING,
std::string, source, src, E_STRING,
bool, directory, dir, E_FROM_BOOL
);
E_SIMPLE1(file_unpinned, normal, true,
std::string, api_path, ap, E_STRING
);
E_SIMPLE2(file_upload_begin, normal, true,
std::string, api_path, ap, E_STRING,
std::string, source, src, E_STRING
);
E_SIMPLE2(file_upload_completed, normal, true,
std::string, api_path, ap, E_STRING,
std::string, source, src, E_STRING
);
E_SIMPLE3(file_upload_end, normal, true,
std::string, api_path, ap, E_STRING,
std::string, source, src, E_STRING,
api_error, result, res, E_FROM_API_FILE_ERROR
);
E_SIMPLE3(file_upload_failed, error, true,
std::string, api_path, ap, E_STRING,
std::string, source, src, E_STRING,
std::string, error, err, E_STRING
);
E_SIMPLE2(file_upload_not_found, warn, true,
std::string, api_path, ap, E_STRING,
std::string, source, src, E_STRING
);
E_SIMPLE2(file_upload_queued, normal, true,
std::string, api_path, ap, E_STRING,
std::string, source, src, E_STRING
);
E_SIMPLE2(file_upload_removed, debug, true,
std::string, api_path, ap, E_STRING,
std::string, source, src, E_STRING
);
E_SIMPLE2(file_upload_retry, normal, true,
std::string, api_path, ap, E_STRING,
std::string, source, src, E_STRING
);
E_SIMPLE(item_scan_begin, normal, true);
E_SIMPLE(item_scan_end, normal, true);
E_SIMPLE1(orphaned_file_deleted, warn, true,
std::string, source, src, E_STRING
);
E_SIMPLE1(orphaned_file_detected, warn, true,
std::string, source, src, E_STRING
);
E_SIMPLE2(orphaned_file_processed, warn, true,
std::string, source, src, E_STRING,
std::string, dest, dest, E_STRING
);
E_SIMPLE3(orphaned_file_processing_failed, error, true,
std::string, source, src, E_STRING,
std::string, dest, dest, E_STRING,
std::string, result, res, E_STRING
);
E_SIMPLE1(polling_item_begin, debug, true,
std::string, item_name, item, E_STRING
);
E_SIMPLE1(polling_item_end, debug, true,
std::string, item_name, item, E_STRING
);
E_SIMPLE2(provider_offline, error, true,
std::string, host_name_or_ip, host, E_STRING,
std::uint16_t, port, port, E_FROM_UINT16
);
E_SIMPLE2(repertory_exception, error, true,
std::string, function, func, E_STRING,
std::string, message, msg, E_STRING
);
E_SIMPLE1(rpc_server_exception, error, true,
std::string, exception, exception, E_STRING
);
E_SIMPLE1(service_shutdown, debug, true,
std::string, service, svc, E_STRING
);
E_SIMPLE3(skynet_import_decryption_failed, error, true,
std::string, skylink, skylink, E_STRING,
std::string, sub_file, sf, E_STRING,
api_error, result, res, E_FROM_API_FILE_ERROR
);
E_SIMPLE3(skynet_import_directory_failed, error, true,
std::string, skylink, skylink, E_STRING,
std::string, sub_directory, sd, E_STRING,
api_error, result, res, E_FROM_API_FILE_ERROR
);
E_SIMPLE3(skynet_import_file_failed, error, true,
std::string, skylink, skylink, E_STRING,
std::string, sub_file, sf, E_STRING,
api_error, result, res, E_FROM_API_FILE_ERROR
);
E_SIMPLE(skynet_portal_list_changed, normal, true);
E_SIMPLE(unmount_requested, normal, true);
#ifndef _WIN32
E_SIMPLE2(unmount_result, normal, true,
std::string, location, loc, E_STRING,
std::string, result, res, E_STRING
);
#endif
// clang-format on
} // namespace repertory
#endif // INCLUDE_EVENTS_EVENTS_HPP_

View File

@ -0,0 +1,178 @@
/*
Copyright <2018-2022> <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_EVENTS_T_EVENT_SYSTEM_HPP_
#define INCLUDE_EVENTS_T_EVENT_SYSTEM_HPP_
#include "common.hpp"
#include "events/event.hpp"
#include "utils/utils.hpp"
namespace repertory {
template <typename event_type> class t_event_system final {
public:
t_event_system(const t_event_system &) = delete;
t_event_system(t_event_system &&) = delete;
t_event_system &operator=(const t_event_system &) = delete;
t_event_system &operator=(t_event_system &&) = delete;
protected:
t_event_system() = default;
~t_event_system() { stop(); }
public:
class event_consumer final {
public:
explicit event_consumer(std::function<void(const event &)> callback)
: callback_(std::move(callback)) {
t_event_system::instance().attach(this);
}
event_consumer(const std::string &event_name, std::function<void(const event &)> callback)
: callback_(std::move(callback)) {
t_event_system::instance().attach(event_name, this);
}
~event_consumer() { t_event_system::instance().release(this); }
private:
std::function<void(const event &)> callback_;
public:
void notify_event(const event &event) { callback_(event); }
};
private:
static t_event_system event_system_;
public:
static t_event_system &instance();
private:
std::unordered_map<std::string, std::deque<event_consumer *>> event_consumers_;
std::recursive_mutex consumer_mutex_;
std::vector<std::shared_ptr<event_type>> event_list_;
std::condition_variable event_notify_;
std::mutex event_mutex_;
std::unique_ptr<std::thread> event_thread_;
std::mutex run_mutex_;
bool stop_requested_ = false;
private:
void process_events() {
std::vector<std::shared_ptr<event_type>> events;
{
unique_mutex_lock l(event_mutex_);
if (not stop_requested_ && event_list_.empty()) {
event_notify_.wait_for(l, 5s);
}
if (not event_list_.empty()) {
events.insert(events.end(), event_list_.begin(), event_list_.end());
event_list_.clear();
}
}
const auto notify_events = [this](const std::string &name, const event_type &event) {
std::deque<std::future<void>> futures;
recur_mutex_lock l(consumer_mutex_);
if (event_consumers_.find(name) != event_consumers_.end()) {
for (auto *ec : event_consumers_[name]) {
if (event.get_allow_async()) {
futures.emplace_back(
std::async(std::launch::async, [ec, &event]() { ec->notify_event(event); }));
} else {
ec->notify_event(event);
}
}
}
while (not futures.empty()) {
futures.front().get();
futures.pop_front();
}
};
for (const auto &e : events) {
notify_events("", *e.get());
notify_events(e->get_name(), *e.get());
}
}
void queue_event(event_type *e) {
mutex_lock l(event_mutex_);
event_list_.emplace_back(std::shared_ptr<event_type>(e));
event_notify_.notify_all();
}
public:
void attach(event_consumer *ec) {
recur_mutex_lock l(consumer_mutex_);
event_consumers_[""].push_back(ec);
}
void attach(const std::string &event_name, event_consumer *ec) {
recur_mutex_lock l(consumer_mutex_);
event_consumers_[event_name].push_back(ec);
}
template <typename t, typename... args> void raise(args &&...a) {
queue_event(new t(std::forward<args>(a)...));
}
void release(event_consumer *ec) {
recur_mutex_lock l(consumer_mutex_);
auto it =
std::find_if(event_consumers_.begin(), event_consumers_.end(), [&](const auto &kv) -> bool {
return utils::collection_includes(kv.second, ec);
});
if (it != event_consumers_.end()) {
auto &q = (*it).second;
utils::remove_element_from(q, ec);
}
}
void start() {
mutex_lock l(run_mutex_);
if (not event_thread_) {
stop_requested_ = false;
event_thread_ = std::make_unique<std::thread>([this]() {
while (not stop_requested_) {
process_events();
}
});
}
}
void stop() {
mutex_lock l(run_mutex_);
if (event_thread_) {
stop_requested_ = true;
event_notify_.notify_all();
event_thread_->join();
event_thread_.reset();
process_events();
stop_requested_ = false;
}
}
};
} // namespace repertory
#endif // INCLUDE_EVENTS_T_EVENT_SYSTEM_HPP_

View File

@ -0,0 +1,25 @@
/*
Copyright <2018-2022> <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_PLATFORM_PLATFORM_HPP_
#define INCLUDE_PLATFORM_PLATFORM_HPP_
#include "platform/unix_platform.hpp"
#include "platform/win32_platform.hpp"
#endif // INCLUDE_PLATFORM_PLATFORM_HPP_

View File

@ -0,0 +1,62 @@
/*
Copyright <2018-2022> <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_PLATFORM_UNIXPLATFORM_HPP_
#define INCLUDE_PLATFORM_UNIXPLATFORM_HPP_
#ifndef _WIN32
#include "common.hpp"
#include "types/repertory.hpp"
namespace repertory {
class lock_data final {
public:
explicit lock_data(const provider_type &pt, std::string unique_id /*= ""*/);
lock_data();
~lock_data();
private:
const provider_type pt_;
const std::string unique_id_;
const std::string mutex_id_;
int lock_fd_;
int lock_status_ = EWOULDBLOCK;
private:
static std::string get_state_directory();
static std::string get_lock_data_file();
std::string get_lock_file();
private:
static int wait_for_lock(const int &fd, const std::uint8_t &retry_count = 30u);
public:
bool get_mount_state(json &mount_state);
lock_result grab_lock(const std::uint8_t &retry_count = 30u);
bool set_mount_state(const bool &active, const std::string &mount_location, const int &pid);
};
} // namespace repertory
#endif // _WIN32
#endif // INCLUDE_PLATFORM_UNIXPLATFORM_HPP_

View File

@ -0,0 +1,65 @@
/*
Copyright <2018-2022> <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_PLATFORM_WINPLATFORM_HPP_
#define INCLUDE_PLATFORM_WINPLATFORM_HPP_
#ifdef _WIN32
#include "common.hpp"
#include "app_config.hpp"
#include "types/repertory.hpp"
namespace repertory {
class lock_data final {
public:
explicit lock_data(const provider_type &pt, std::string unique_id /*= ""*/)
: pt_(pt), unique_id_(std::move(unique_id)),
mutex_id_("repertory_" + app_config::get_provider_name(pt) + "_" + unique_id_),
mutex_handle_(::CreateMutex(nullptr, FALSE, &mutex_id_[0u])) {}
lock_data()
: pt_(provider_type::sia), unique_id_(""), mutex_id_(""),
mutex_handle_(INVALID_HANDLE_VALUE) {}
~lock_data() { release(); }
private:
const provider_type pt_;
const std::string unique_id_;
const std::string mutex_id_;
HANDLE mutex_handle_;
DWORD mutex_state_ = WAIT_FAILED;
public:
bool get_mount_state(const provider_type &pt, json &mount_state);
bool get_mount_state(json &mount_state);
std::string get_unique_id() const { return unique_id_; }
lock_result grab_lock(const std::uint8_t &retryCount = 30);
void release();
bool set_mount_state(const bool &active, const std::string &mountLocation,
const std::int64_t &pid);
};
} // namespace repertory
#endif // _WIN32
#endif // INCLUDE_PLATFORM_WINPLATFORM_HPP_

View File

@ -0,0 +1,123 @@
/*
Copyright <2018-2022> <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_PROVIDERS_BASE_PROVIDER_HPP_
#define INCLUDE_PROVIDERS_BASE_PROVIDER_HPP_
#include "common.hpp"
#include "db/meta_db.hpp"
#include "providers/i_provider.hpp"
namespace repertory {
class app_config;
class base_provider : public i_provider {
public:
explicit base_provider(app_config &config);
~base_provider() override = default;
private:
app_config &config_;
protected:
api_item_added_callback api_item_added_;
meta_db meta_db_;
mutable std::recursive_mutex notify_added_mutex_;
i_open_file_table *oft_ = nullptr;
protected:
app_config &get_config() { return config_; }
app_config &get_config() const { return config_; }
virtual std::string format_api_path(std::string api_path) const { return api_path; }
virtual std::string &restore_api_path(std::string &api_path) const { return api_path; }
void notify_directory_added(const std::string &api_path, const std::string &api_parent) const {
const_cast<base_provider *>(this)->notify_directory_added(api_path, api_parent);
}
virtual void notify_directory_added(const std::string &api_path, const std::string &api_parent);
api_error notify_file_added(const std::string &api_path, const std::string &api_parent,
const std::uint64_t &size) const {
return const_cast<base_provider *>(this)->notify_file_added(api_path, api_parent, size);
}
virtual api_error notify_file_added(const std::string &api_path, const std::string &api_parent,
const std::uint64_t &size) = 0;
void remove_item_meta(const std::string &api_path) {
return meta_db_.remove_item_meta(format_api_path(api_path));
}
void update_filesystem_item(const bool &directory, const api_error &error,
const std::string &api_path, filesystem_item &fsi) const;
public:
api_error create_directory_clone_source_meta(const std::string &source_api_path,
const std::string &api_path) override;
api_error create_file(const std::string &api_path, api_meta_map &meta) override;
api_error get_api_path_from_source(const std::string &source_path,
std::string &api_path) const override;
api_error get_filesystem_item(const std::string &api_path, const bool &directory,
filesystem_item &fsi) const override;
api_error get_filesystem_item_and_file(const std::string &api_path, api_file &file,
filesystem_item &fsi) const override;
api_error get_filesystem_item_from_source_path(const std::string &source_path,
filesystem_item &fsi) const override;
api_error get_item_meta(const std::string &api_path, api_meta_map &meta) const override;
api_error get_item_meta(const std::string &api_path, const std::string &key,
std::string &value) const override;
std::vector<std::string> get_pinned_files() const override { return meta_db_.get_pinned_files(); }
std::uint64_t get_used_drive_space() const override;
bool is_file_writeable(const std::string &) const override { return true; }
api_error remove_item_meta(const std::string &api_path, const std::string &key) override {
return meta_db_.remove_item_meta(format_api_path(api_path), key);
}
api_error set_item_meta(const std::string &api_path, const std::string &key,
const std::string &value) override {
return meta_db_.set_item_meta(format_api_path(api_path), key, value);
}
api_error set_item_meta(const std::string &api_path, const api_meta_map &meta) override {
return meta_db_.set_item_meta(format_api_path(api_path), meta);
}
api_error set_source_path(const std::string &api_path, const std::string &source_path) override {
return meta_db_.set_source_path(format_api_path(api_path), source_path);
}
bool start(api_item_added_callback api_item_added, i_open_file_table *oft) override;
};
} // namespace repertory
#endif // INCLUDE_PROVIDERS_BASE_PROVIDER_HPP_

View File

@ -0,0 +1,115 @@
/*
Copyright <2018-2022> <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_PROVIDERS_I_PROVIDER_HPP_
#define INCLUDE_PROVIDERS_I_PROVIDER_HPP_
#include "common.hpp"
#include "types/repertory.hpp"
namespace repertory {
class i_open_file_table;
class i_provider {
INTERFACE_SETUP(i_provider);
public:
virtual api_error create_directory(const std::string &api_path, const api_meta_map &meta) = 0;
virtual api_error create_directory_clone_source_meta(const std::string &source_api_path,
const std::string &api_path) = 0;
virtual api_error create_file(const std::string &api_path, api_meta_map &meta) = 0;
virtual api_error get_api_path_from_source(const std::string &source_path,
std::string &api_path) const = 0;
virtual api_error get_file_list(api_file_list &list) const = 0;
virtual std::uint64_t get_directory_item_count(const std::string &api_path) const = 0;
virtual api_error get_directory_items(const std::string &api_path,
directory_item_list &list) const = 0;
virtual api_error get_file(const std::string &api_path, api_file &file) const = 0;
virtual api_error get_file_size(const std::string &api_path, std::uint64_t &file_size) const = 0;
virtual api_error get_filesystem_item(const std::string &api_path, const bool &directory,
filesystem_item &fsi) const = 0;
virtual api_error get_filesystem_item_and_file(const std::string &api_path, api_file &file,
filesystem_item &fsi) const = 0;
virtual api_error get_filesystem_item_from_source_path(const std::string &source_path,
filesystem_item &fsi) const = 0;
virtual std::vector<std::string> get_pinned_files() const = 0;
virtual api_error get_item_meta(const std::string &api_path, api_meta_map &meta) const = 0;
virtual api_error get_item_meta(const std::string &api_path, const std::string &key,
std::string &value) const = 0;
virtual std::uint64_t get_total_drive_space() const = 0;
virtual std::uint64_t get_total_item_count() const = 0;
virtual provider_type get_provider_type() const = 0;
virtual std::uint64_t get_used_drive_space() const = 0;
virtual bool is_directory(const std::string &api_path) const = 0;
virtual bool is_file(const std::string &api_path) const = 0;
virtual bool is_file_writeable(const std::string &api_path) const = 0;
virtual bool is_online() const = 0;
virtual bool is_rename_supported() const = 0;
virtual api_error read_file_bytes(const std::string &api_path, const std::size_t &size,
const std::uint64_t &offset, std::vector<char> &data,
const bool &stop_requested) = 0;
virtual api_error remove_directory(const std::string &api_path) = 0;
virtual api_error remove_file(const std::string &api_path) = 0;
virtual api_error remove_item_meta(const std::string &api_path, const std::string &key) = 0;
virtual api_error rename_file(const std::string &fromApiPath, const std::string &toApiPath) = 0;
virtual api_error set_item_meta(const std::string &api_path, const std::string &key,
const std::string &value) = 0;
virtual api_error set_item_meta(const std::string &api_path, const api_meta_map &meta) = 0;
virtual api_error set_source_path(const std::string &api_path,
const std::string &source_path) = 0;
virtual bool start(api_item_added_callback api_item_added, i_open_file_table *oft) = 0;
virtual void stop() = 0;
virtual api_error upload_file(const std::string &api_path, const std::string &source_path,
const std::string &encryption_token) = 0;
};
} // namespace repertory
#endif // INCLUDE_PROVIDERS_I_PROVIDER_HPP_

View File

@ -0,0 +1,115 @@
/*
Copyright <2018-2022> <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_PROVIDERS_PASSTHROUGH_PASSTHROUGHPROVIDER_HPP_
#define INCLUDE_PROVIDERS_PASSTHROUGH_PASSTHROUGHPROVIDER_HPP_
#if defined(REPERTORY_TESTING_NEW)
#include "common.hpp"
#include "providers/basebase_provider.hpp"
namespace repertory {
class app_config;
class CPassthroughProvider final : public base_provider {
public:
explicit CPassthroughProvider(app_config &config)
: base_provider(config), passthroughLocation_("" /*config.GetPassthroughConfig().Location*/) {
}
~CPassthroughProvider() override = default;
private:
const std::string passthroughLocation_;
private:
std::string ConstructFullPath(const std::string &api_path) const;
protected:
api_error notify_file_added(const std::string &api_path, const std::string &api_parent,
const std::uint64_t &size) override;
public:
api_error CreateDirectory(const std::string &api_path, const api_meta_map &metaMap) override;
api_error get_file_list(ApiFileList &fileList) const override;
std::uint64_t get_directory_item_count(const std::string &api_path) const override;
api_error get_directory_items(const std::string &api_path,
directory_item_list &list) const override;
api_error GetFile(const std::string &api_path, ApiFile &file) const override;
api_error GetFileSize(const std::string &api_path, std::uint64_t &fileSize) const override;
api_error get_filesystem_item(const std::string &api_path, const bool &directory,
FileSystemItem &fileSystemItem) const override;
api_error get_filesystem_item_from_source_path(const std::string &sourceFilePath,
FileSystemItem &fileSystemItem) const override;
api_error get_item_meta(const std::string &api_path, api_meta_map &meta) const override;
api_error get_item_meta(const std::string &api_path, const std::string &key,
std::string &value) const override;
provider_type get_provider_type() const override { return provider_type::passthrough; }
std::uint64_t get_total_drive_space() const override;
std::uint64_t get_total_item_count() const override;
std::uint64_t get_used_drive_space() const override;
bool IsDirectory(const std::string &api_path) const override;
bool IsFile(const std::string &api_path) const override;
bool IsOnline() const override { return true; }
bool is_rename_supported() const override { return true; }
api_error read_file_bytes(const std::string &apiFilepath, const std::size_t &size,
const std::uint64_t &offset, std::vector<char> &data,
const bool &stop_requested) override;
api_error RemoveDirectory(const std::string &api_path) override;
api_error RemoveFile(const std::string &api_path) override;
api_error RenameFile(const std::string &fromApiPath, const std::string &toApiPath) override;
api_error remove_item_meta(const std::string &api_path, const std::string &key) override;
api_error set_item_meta(const std::string &api_path, const std::string &key,
const std::string &value) override;
api_error set_item_meta(const std::string &api_path, const api_meta_map &meta) override;
api_error set_source_path(const std::string &api_path, const std::string &sourcePath) override;
bool Start(api_item_added_callback apiItemAdded, i_open_file_table *openFileTable) override;
void Stop() override;
api_error upload_file(const std::string &api_path, const std::string &sourcePath,
const std::string &encryptionToken) override;
};
} // namespace repertory
#endif // REPERTORY_TESTING_NEW
#endif // INCLUDE_PROVIDERS_PASSTHROUGH_PASSTHROUGHPROVIDER_HPP_

View File

@ -0,0 +1,31 @@
/*
Copyright <2018-2022> <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_PROVIDERS_PROVIDER_HPP_
#define INCLUDE_PROVIDERS_PROVIDER_HPP_
#include "common.hpp"
#include "types/repertory.hpp"
namespace repertory {
class app_config;
class i_provider;
std::unique_ptr<i_provider> create_provider(const provider_type &pt, app_config &config);
} // namespace repertory
#endif // INCLUDE_PROVIDERS_PROVIDER_HPP_

View File

@ -0,0 +1,114 @@
/*
Copyright <2018-2022> <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_PROVIDERS_S3_S3_PROVIDER_HPP_
#define INCLUDE_PROVIDERS_S3_S3_PROVIDER_HPP_
#if defined(REPERTORY_ENABLE_S3)
#include "common.hpp"
#include "db/directory_db.hpp"
#include "providers/base_provider.hpp"
#include "upload/upload_manager.hpp"
namespace repertory {
class app_config;
class i_s3_comm;
class s3_provider final : public base_provider {
public:
s3_provider(app_config &config, i_s3_comm &s3_comm);
private:
i_s3_comm &s3_comm_;
directory_db directory_db_;
upload_manager upload_manager_;
std::uint64_t total_item_count_ = 0u;
private:
void build_directories();
void update_item_meta(directory_item &di, const bool &format_path) const;
void upload_completed(const std::string &, const std::string &, const json &) {}
api_error upload_handler(const upload_manager::upload &upload, json &, json &);
protected:
std::string format_api_path(std::string api_path) const override;
void notify_directory_added(const std::string &api_path, const std::string &api_parent) override;
api_error notify_file_added(const std::string &api_path, const std::string &api_parent,
const std::uint64_t &size) override;
std::string &restore_api_path(std::string &api_path) const override;
public:
api_error create_directory(const std::string &api_path, const api_meta_map &meta) override;
api_error create_file(const std::string &api_path, api_meta_map &meta) override;
api_error get_file_list(api_file_list &list) const override;
std::uint64_t get_directory_item_count(const std::string &api_path) const override;
api_error get_directory_items(const std::string &api_path,
directory_item_list &list) const override;
api_error get_file(const std::string &api_path, api_file &file) const override;
api_error get_file_size(const std::string &api_path, std::uint64_t &file_size) const override;
provider_type get_provider_type() const override { return provider_type::s3; }
std::uint64_t get_total_drive_space() const override {
return std::numeric_limits<std::int64_t>::max() / std::int64_t(2);
}
std::uint64_t get_total_item_count() const override { return total_item_count_; }
bool is_directory(const std::string &api_path) const override;
bool is_file(const std::string &api_path) const override;
bool is_online() const override;
bool is_processing(const std::string &api_path) const;
bool is_rename_supported() const override { return false; }
api_error read_file_bytes(const std::string &api_path, const std::size_t &size,
const std::uint64_t &offset, std::vector<char> &data,
const bool &stop_requested) override;
api_error remove_directory(const std::string &api_path) override;
api_error remove_file(const std::string &api_path) override;
api_error rename_file(const std::string &from_api_path, const std::string &to_api_path) override;
bool start(api_item_added_callback api_item_added, i_open_file_table *oft) override;
void stop() override;
api_error upload_file(const std::string &api_path, const std::string &source_path,
const std::string &encryption_token) override;
};
} // namespace repertory
#endif // REPERTORY_ENABLE_S3
#endif // INCLUDE_PROVIDERS_S3_S3_PROVIDER_HPP_

View File

@ -0,0 +1,136 @@
/*
Copyright <2018-2022> <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_PROVIDERS_SIA_SIAPROVIDER_HPP_
#define INCLUDE_PROVIDERS_SIA_SIAPROVIDER_HPP_
#include "common.hpp"
#include "providers/base_provider.hpp"
namespace repertory {
class app_config;
class i_comm;
class sia_provider : public base_provider {
public:
sia_provider(app_config &config, i_comm &comm);
~sia_provider() override = default;
private:
i_comm &comm_;
std::uint64_t total_drive_space_ = 0u;
bool stop_requested_ = false;
std::mutex start_stop_mutex_;
std::condition_variable start_stop_notify_;
std::unique_ptr<std::thread> drive_space_thread_;
private:
api_item_added_callback &get_api_item_added() { return api_item_added_; }
i_comm &get_comm() { return comm_; }
i_comm &get_comm() const { return comm_; } // TODO Fix non-const reference return
private:
void calculate_total_drive_space();
api_error calculate_used_drive_space(std::uint64_t &used_space);
void drive_space_thread();
bool processed_orphaned_file(const std::string &source_path,
const std::string &api_path = "") const;
void remove_deleted_files();
void remove_expired_orphaned_files();
void remove_unknown_source_files();
protected:
api_error check_file_exists(const std::string &api_path) const;
bool check_directory_found(const json &error) const;
bool check_not_found(const json &error) const;
virtual void cleanup();
void create_api_file(const json &json_file, const std::string &path_name, api_file &file) const;
api_error get_directory(const std::string &api_path, json &result, json &error) const;
api_error notify_file_added(const std::string &api_path, const std::string &api_parent,
const std::uint64_t &size) override;
void set_api_file_dates(const json &file, api_file &apiFile) const;
public:
api_error create_directory(const std::string &api_path, const api_meta_map &meta) override;
std::uint64_t get_directory_item_count(const std::string &api_path) const override;
api_error get_directory_items(const std::string &api_path,
directory_item_list &list) const override;
api_error get_file(const std::string &api_path, api_file &file) const override;
api_error get_file_list(api_file_list &list) const override;
api_error get_file_size(const std::string &api_path, std::uint64_t &file_size) const override;
api_error get_filesystem_item(const std::string &api_path, const bool &directory,
filesystem_item &fsi) const override;
api_error get_filesystem_item_and_file(const std::string &api_path, api_file &apiFile,
filesystem_item &fsi) const override;
provider_type get_provider_type() const override { return provider_type::sia; }
std::uint64_t get_total_drive_space() const override { return total_drive_space_; }
std::uint64_t get_total_item_count() const override;
bool is_directory(const std::string &api_path) const override;
bool is_file(const std::string &api_path) const override;
bool is_online() const override;
bool is_rename_supported() const override { return true; }
api_error read_file_bytes(const std::string &api_path, const std::size_t &size,
const std::uint64_t &offset, std::vector<char> &buffer,
const bool &stop_requested) override;
api_error remove_directory(const std::string &api_path) override;
api_error remove_file(const std::string &api_path) override;
api_error rename_file(const std::string &from_api_path, const std::string &to_api_path) override;
bool start(api_item_added_callback api_item_added, i_open_file_table *oft) override;
void stop() override;
api_error upload_file(const std::string &api_path, const std::string &source_path,
const std::string &) override;
};
} // namespace repertory
#endif // INCLUDE_PROVIDERS_SIA_SIAPROVIDER_HPP_

View File

@ -0,0 +1,139 @@
/*
Copyright <2018-2022> <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_PROVIDERS_SKYNET_SKYNET_PROVIDER_HPP_
#define INCLUDE_PROVIDERS_SKYNET_SKYNET_PROVIDER_HPP_
#if defined(REPERTORY_ENABLE_SKYNET)
#include "common.hpp"
#include "db/directory_db.hpp"
#include "db/meta_db.hpp"
#include "events/event_system.hpp"
#include "providers/base_provider.hpp"
#include "upload/upload_manager.hpp"
namespace repertory {
class app_config;
class i_comm;
class skynet_provider final : public base_provider {
E_CONSUMER();
public:
skynet_provider(app_config &config, i_comm &comm);
~skynet_provider() override { E_CONSUMER_RELEASE(); }
private:
i_comm &comm_;
directory_db directory_db_;
upload_manager upload_manager_;
bool stop_requested_ = false;
std::atomic<std::size_t> next_download_index_;
std::atomic<std::size_t> next_upload_index_;
std::shared_ptr<std::vector<host_config>> download_list_;
std::shared_ptr<std::vector<host_config>> upload_list_;
mutable std::mutex portal_mutex_;
private:
std::size_t get_retry_count() const;
void populate_api_file(api_file &file) const;
void process_export(json &result, const std::string &api_path) const;
void upload_completed(const std::string &api_path, const std::string &, const json &data);
api_error upload_handler(const upload_manager::upload &upload, json &data, json &error);
protected:
void notify_directory_added(const std::string &api_path, const std::string &api_parent) override;
api_error notify_file_added(const std::string &, const std::string &,
const std::uint64_t &) override;
public:
api_error create_directory(const std::string &api_path, const api_meta_map &meta) override;
api_error create_file(const std::string &api_path, api_meta_map &meta) override;
json export_all() const;
json export_list(const std::vector<std::string> &api_path_list) const;
std::uint64_t get_directory_item_count(const std::string &api_path) const override;
api_error get_directory_items(const std::string &api_path,
directory_item_list &list) const override;
api_error get_file(const std::string &api_path, api_file &file) const override;
api_error get_file_list(api_file_list &list) const override;
api_error get_file_size(const std::string &api_path, std::uint64_t &file_size) const override;
host_config get_host_config(const bool &upload);
provider_type get_provider_type() const override { return provider_type::skynet; }
api_error get_skynet_metadata(const std::string &skylink, json &json_meta);
std::uint64_t get_total_drive_space() const override {
return std::numeric_limits<std::int64_t>::max() / std::int64_t(2);
}
std::uint64_t get_total_item_count() const override {
return directory_db_.get_total_item_count();
}
api_error import_skylink(const skylink_import &si);
bool is_directory(const std::string &api_path) const override;
bool is_file(const std::string &api_path) const override;
bool is_file_writeable(const std::string &api_path) const override;
bool is_online() const override { return true; }
bool is_processing(const std::string &api_path) const;
bool is_rename_supported() const override { return true; }
api_error read_file_bytes(const std::string &api_path, const std::size_t &size,
const std::uint64_t &offset, std::vector<char> &data,
const bool &stop_requested) override;
api_error remove_directory(const std::string &api_path) override;
api_error remove_file(const std::string &api_path) override;
api_error rename_file(const std::string &from_api_path, const std::string &to_api_path) override;
bool start(api_item_added_callback api_item_added, i_open_file_table *oft) override;
void stop() override;
bool update_portal_list();
api_error upload_file(const std::string &api_path, const std::string &source_path,
const std::string &encryption_token) override;
};
} // namespace repertory
#endif // REPERTORY_ENABLE_SKYNET
#endif // INCLUDE_PROVIDERS_SKYNET_SKYNET_PROVIDER_HPP_

View File

@ -0,0 +1,70 @@
/*
Copyright <2018-2022> <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_RPC_CLIENT_CLIENT_HPP_
#define INCLUDE_RPC_CLIENT_CLIENT_HPP_
#include "common.hpp"
#include "types/rpc.hpp"
#include "types/skynet.hpp"
namespace repertory {
class client {
public:
explicit client(rpc_host_info host_info);
private:
const rpc_host_info host_info_;
std::atomic<std::uint32_t> request_id_;
private:
rpc_response make_request(const std::string &command, const std::vector<json> &args,
std::uint32_t timeout_ms = 10000u);
public:
rpc_response export_list(const std::vector<std::string> &paths);
rpc_response export_all();
rpc_response get_drive_information();
rpc_response get_config();
rpc_response get_config_value_by_name(const std::string &name);
rpc_response get_directory_items(const std::string &api_path);
rpc_response get_open_files();
rpc_response get_pinned_files();
rpc_response import_skylink(const skylink_import_list &list);
rpc_response pin_file(const std::string &api_file);
rpc_response pinned_status(const std::string &api_file);
rpc_response set_config_value_by_name(const std::string &name, const std::string &value);
rpc_response unmount();
rpc_response unpin_file(const std::string &api_file);
};
} // namespace repertory
#endif // INCLUDE_RPC_CLIENT_CLIENT_HPP_

View File

@ -0,0 +1,44 @@
/*
Copyright <2018-2022> <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_RPC_SERVER_FULL_SERVER_HPP_
#define INCLUDE_RPC_SERVER_FULL_SERVER_HPP_
#include "common.hpp"
#include "rpc/server/server.hpp"
namespace repertory {
class i_open_file_table;
class i_provider;
class full_server final : public server {
public:
explicit full_server(app_config &config, i_provider &provider, i_open_file_table &oft);
~full_server() override = default;
private:
i_provider &provider_;
i_open_file_table &oft_;
protected:
bool handle_request(jsonrpcpp::request_ptr &request,
std::unique_ptr<jsonrpcpp::Response> &response) override;
};
} // namespace repertory
#endif // INCLUDE_RPC_SERVER_FULL_SERVER_HPP_

View File

@ -0,0 +1,99 @@
/*
Copyright <2018-2022> <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_RPC_SERVER_SERVER_HPP_
#define INCLUDE_RPC_SERVER_SERVER_HPP_
#include "common.hpp"
#include "types/rpc.hpp"
namespace repertory {
class app_config;
class server {
typedef std::map<std::string, std::string, httpserver::http::arg_comparator> query_map;
private:
class json_response final : public httpserver::http_response {
public:
json_response() = default;
explicit json_response(const json &content,
int response_code = httpserver::http::http_utils::http_ok,
const std::string &content_type = "application/json")
: http_response(response_code, content_type), content(content.dump(0)) {}
json_response(const json_response &other) = default;
json_response(json_response &&other) noexcept = default;
json_response &operator=(const json_response &b) = default;
json_response &operator=(json_response &&b) = default;
~json_response() override = default;
MHD_Response *get_raw_response() override {
const auto size = content.length();
return MHD_create_response_from_buffer(size, (void *)content.c_str(), MHD_RESPMEM_PERSISTENT);
}
private:
std::string content = "";
};
class rpc_resource final : public httpserver::http_resource {
public:
explicit rpc_resource(server &owner);
private:
server &owner_;
public:
const std::shared_ptr<httpserver::http_response>
render(const httpserver::http_request &request) override;
};
public:
explicit server(app_config &config);
virtual ~server() { stop(); }
private:
app_config &config_;
rpc_resource resource_;
std::unique_ptr<httpserver::webserver> ws_;
std::mutex start_stop_mutex_;
bool started_ = false;
private:
bool check_authorization(const httpserver::http_request &request);
protected:
app_config &get_config() { return config_; }
const app_config &get_config() const { return config_; }
virtual bool handle_request(jsonrpcpp::request_ptr &request,
std::unique_ptr<jsonrpcpp::Response> &response);
public:
void start();
void stop();
};
} // namespace repertory
#endif // INCLUDE_RPC_SERVER_SERVER_HPP_

147
include/types/remote.hpp Normal file
View File

@ -0,0 +1,147 @@
/*
Copyright <2018-2022> <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_TYPES_REMOTE_HPP_
#define INCLUDE_TYPES_REMOTE_HPP_
#include "common.hpp"
#define PACKET_SERVICE_FUSE std::uint32_t(1)
#define PACKET_SERVICE_WINFSP std::uint32_t(2)
#ifdef _WIN32
#define PACKET_SERVICE_FLAGS PACKET_SERVICE_WINFSP
#else
#define PACKET_SERVICE_FLAGS PACKET_SERVICE_FUSE
#endif
namespace repertory::remote {
typedef std::uint64_t block_count;
typedef std::uint32_t block_size;
typedef std::uint64_t file_handle;
typedef std::uint16_t file_mode;
typedef std::uint16_t file_nlink;
typedef std::uint64_t file_offset;
typedef std::uint64_t file_size;
typedef std::uint64_t file_time;
typedef std::uint32_t group_id;
typedef std::uint32_t user_id;
enum class open_flags : std::uint32_t {
read_only = 0u,
write_only = 1u,
read_write = 2u,
create = 4u,
excl = 8u,
no_ctty = 16u,
truncate = 32u,
append = 64u,
non_blocking = 128u,
sync = 256u,
async = 512u,
directory = 1024u,
no_follow = 2048u,
clo_exec = 4096u,
direct = 8192u,
no_atime = 16384u,
path = 32768u,
temp_file = 65536u,
dsync = 131072u,
};
static open_flags operator|(const open_flags &a, const open_flags &b) {
using t = std::underlying_type_t<open_flags>;
return static_cast<open_flags>(static_cast<t>(a) | static_cast<t>(b));
}
static open_flags &operator|=(open_flags &a, const open_flags &b) {
a = a | b;
return a;
}
static open_flags operator&(const open_flags &a, const open_flags &b) {
using t = std::underlying_type_t<open_flags>;
return static_cast<open_flags>(static_cast<t>(a) & static_cast<t>(b));
}
#pragma pack(1)
struct file_info {
UINT32 FileAttributes;
UINT32 ReparseTag;
UINT64 AllocationSize;
UINT64 FileSize;
UINT64 CreationTime;
UINT64 LastAccessTime;
UINT64 LastWriteTime;
UINT64 ChangeTime;
UINT64 IndexNumber;
UINT32 HardLinks;
UINT32 EaSize;
};
struct setattr_x {
std::int32_t valid;
file_mode mode;
user_id uid;
group_id gid;
file_size size;
file_time acctime;
file_time modtime;
file_time crtime;
file_time chgtime;
file_time bkuptime;
std::uint32_t flags;
};
struct stat {
file_mode st_mode;
file_nlink st_nlink;
user_id st_uid;
group_id st_gid;
file_time st_atimespec;
file_time st_mtimespec;
file_time st_ctimespec;
file_time st_birthtimespec;
file_size st_size;
block_count st_blocks;
block_size st_blksize;
std::uint32_t st_flags;
};
struct statfs {
std::uint64_t f_bavail;
std::uint64_t f_bfree;
std::uint64_t f_blocks;
std::uint64_t f_favail;
std::uint64_t f_ffree;
std::uint64_t f_files;
};
struct statfs_x : public statfs {
char f_mntfromname[1024];
};
#pragma pack()
#ifndef _WIN32
open_flags create_open_flags(const std::uint32_t &flags);
std::uint32_t create_os_open_flags(const open_flags &flags);
#endif
} // namespace repertory::remote
#endif // INCLUDE_TYPES_REMOTE_HPP_

310
include/types/repertory.hpp Normal file
View File

@ -0,0 +1,310 @@
/*
Copyright <2018-2022> <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_TYPES_REPERTORY_HPP_
#define INCLUDE_TYPES_REPERTORY_HPP_
#include "common.hpp"
namespace repertory {
#define META_ACCESSED "accessed"
#define META_ATTRIBUTES "attributes"
#define META_BACKUP "backup"
#define META_CHANGED "changed"
#define META_CREATION "creation"
#define META_ENCRYPTION_TOKEN "token2"
#define META_GID "gid"
#define META_ID "id"
#define META_KEY "key"
#define META_MODE "mode"
#define META_MODIFIED "modified"
#define META_OSXFLAGS "flags"
#define META_PINNED "pinned"
#define META_SIZE "size"
#define META_SOURCE "source"
#define META_UID "uid"
#define META_WRITTEN "written"
const std::vector<std::string> META_USED_NAMES = {
META_ACCESSED, META_ATTRIBUTES, META_BACKUP, META_CHANGED, META_CREATION, META_ENCRYPTION_TOKEN,
META_GID, META_ID, META_KEY, META_MODE, META_MODIFIED, META_OSXFLAGS,
META_PINNED, META_SIZE, META_SOURCE, META_UID, META_WRITTEN,
};
typedef std::unordered_map<std::string, std::string> api_meta_map;
enum class api_error {
success = 0,
access_denied,
bad_address,
buffer_overflow,
buffer_too_small,
comm_error,
decryption_error,
directory_end_of_files,
directory_exists,
directory_not_empty,
directory_not_found,
download_failed,
download_incomplete,
download_stopped,
download_timeout,
empty_ring_buffer_chunk_size,
empty_ring_buffer_size,
error,
file_exists,
file_in_use,
incompatible_version,
invalid_handle,
invalid_operation,
invalid_ring_buffer_multiple,
invalid_ring_buffer_size,
invalid_version,
item_is_file,
item_not_found,
not_implemented,
not_supported,
os_error,
permission_denied,
upload_failed,
upload_stopped,
xattr_buffer_small,
xattr_exists,
xattr_invalid_namespace,
xattr_not_found,
xattr_osx_invalid,
xattr_too_big,
ERROR_COUNT
};
const std::string &api_error_to_string(const api_error &error);
enum class download_type { direct, fallback, ring_buffer };
enum class exit_code {
success,
communication_error = -1,
file_creation_failed = -2,
incompatible_version = -3,
invalid_syntax = -4,
lock_failed = -5,
mount_active = -6,
mount_result = -7,
not_mounted = -8,
startup_exception = -9,
failed_to_get_mount_state = -10,
export_failed = -11,
import_failed = -12,
option_not_found = -13,
invalid_provider_type = -14,
set_option_not_found = -15,
pin_failed = -16,
unpin_failed = -17,
};
enum class lock_result {
success,
locked,
failure,
};
enum class provider_type {
sia,
remote,
s3,
skynet,
passthrough,
unknown,
};
#ifdef _WIN32
struct open_file_data {
void *directory_buffer = nullptr;
};
#else
typedef int open_file_data;
#endif
struct api_file {
std::string api_path{};
std::string api_parent{};
std::uint64_t accessed_date = 0u;
std::uint64_t changed_date = 0u;
std::uint64_t created_date = 0u;
std::string encryption_token{};
std::uint64_t file_size = 0u;
std::uint64_t modified_date = 0u;
bool recoverable = false;
double redundancy = 0.0;
std::string source_path{};
};
struct directory_item {
std::string api_path{};
std::string api_parent{};
bool directory = false;
std::uint64_t size = 0u;
api_meta_map meta{};
bool resolved = false;
static directory_item from_json(const json &item) {
directory_item ret{};
ret.api_path = item["path"].get<std::string>();
ret.api_parent = item["parent"].get<std::string>();
ret.directory = item["directory"].get<bool>();
ret.size = item["size"].get<std::uint64_t>();
ret.meta = item["meta"].get<std::unordered_map<std::string, std::string>>();
return ret;
}
json to_json() const {
return {{"path", api_path},
{"parent", api_parent},
{"size", size},
{"directory", directory},
{"meta", meta}};
}
};
struct filesystem_item {
std::string api_path{};
std::string api_parent{};
bool changed = false;
bool directory = false;
std::string encryption_token{};
OSHandle handle = REPERTORY_INVALID_HANDLE;
std::shared_ptr<std::recursive_mutex> lock;
bool meta_changed = false;
std::unordered_map<std::uint64_t, open_file_data> open_data;
std::uint64_t size = 0u;
std::string source_path{};
bool source_path_changed = false;
bool is_encrypted() const { return not encryption_token.empty(); }
};
struct host_config {
std::string agent_string{};
std::string api_password{};
std::uint16_t api_port = 0u;
std::string host_name_or_ip = "localhost";
std::string path{};
std::string protocol = "http";
std::uint32_t timeout_ms = 60000u;
std::string auth_url{};
std::string auth_user{};
std::string auth_password{};
bool operator==(const host_config &hc) const noexcept {
if (&hc != this) {
return agent_string == hc.agent_string && api_password == hc.api_password &&
api_port == hc.api_port && host_name_or_ip == hc.host_name_or_ip && path == hc.path &&
protocol == hc.protocol && timeout_ms == hc.timeout_ms && auth_url == hc.auth_url &&
auth_user == hc.auth_user && auth_password == hc.auth_password;
}
return true;
}
bool operator!=(const host_config &hc) const noexcept {
if (&hc != this) {
return not(hc == *this);
}
return false;
}
};
static void to_json(json &j, const host_config &hc) {
j = json{{"AgentString", hc.agent_string},
{"ApiPassword", hc.api_password},
{"ApiPort", hc.api_port},
{"AuthPassword", hc.auth_password},
{"AuthURL", hc.auth_url},
{"AuthUser", hc.auth_user},
{"HostNameOrIp", hc.host_name_or_ip},
{"Path", hc.path},
{"Protocol", hc.protocol},
{"TimeoutMs", hc.timeout_ms}};
}
static void from_json(const json &j, host_config &hc) {
j.at("AgentString").get_to(hc.agent_string);
j.at("ApiPassword").get_to(hc.api_password);
j.at("ApiPort").get_to(hc.api_port);
j.at("AuthPassword").get_to(hc.auth_password);
j.at("AuthURL").get_to(hc.auth_url);
j.at("AuthUser").get_to(hc.auth_user);
j.at("HostNameOrIp").get_to(hc.host_name_or_ip);
j.at("Path").get_to(hc.path);
j.at("Protocol").get_to(hc.protocol);
j.at("TimeoutMs").get_to(hc.timeout_ms);
}
struct http_range {
std::uint64_t begin = 0u;
std::uint64_t end = 0u;
};
#if 0
struct PassthroughConfig {
std::string Location{};
std::string Name{};
};
#endif
struct s3_config {
std::string access_key{};
std::string bucket{};
std::uint16_t cache_timeout_secs = 60u;
std::string encryption_token{};
std::string region = "any";
std::string secret_key{};
std::uint32_t timeout_ms = 60000u;
std::string url;
};
typedef ttmath::Big<1, 30> api_currency;
typedef std::vector<api_file> api_file_list;
typedef std::vector<directory_item> directory_item_list;
typedef ttmath::UInt<64> hastings;
typedef std::unordered_map<std::string, std::string> http_headers;
typedef std::unordered_map<std::string, std::string> http_parameters;
typedef std::vector<http_range> http_ranges;
typedef std::lock_guard<std::mutex> mutex_lock;
typedef std::lock_guard<std::recursive_mutex> recur_mutex_lock;
typedef std::unique_lock<std::mutex> unique_mutex_lock;
typedef std::unique_lock<std::recursive_mutex> unique_recur_mutex_lock;
typedef std::function<void(api_file &file)> api_file_provider_callback;
typedef std::function<void(const std::string &api_path, const std::string &api_parent,
const std::string &source, const bool &directory,
const std::uint64_t &create_date, const std::uint64_t &access_date,
const std::uint64_t &modified_date, const std::uint64_t &changed_date)>
api_item_added_callback;
typedef std::function<api_error(const std::string &path, const std::size_t &size,
const std::uint64_t &offset, std::vector<char> &data,
const bool &stop_requested)>
api_reader_callback;
typedef std::function<void(directory_item &di, const bool &format_path)> meta_provider_callback;
} // namespace repertory
#endif // INCLUDE_TYPES_REPERTORY_HPP_

56
include/types/rpc.hpp Normal file
View File

@ -0,0 +1,56 @@
/*
Copyright <2018-2022> <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_TYPES_RPC_HPP_
#define INCLUDE_TYPES_RPC_HPP_
#include "common.hpp"
namespace repertory {
struct rpc_host_info {
std::string host;
std::string password;
std::uint16_t port;
std::string user;
};
enum class rpc_response_type { success, config_value_not_found, curl_error, http_error };
struct rpc_response {
rpc_response_type response_type;
json data;
};
namespace rpc_method {
const std::string export_links = "export";
const std::string get_config = "get_config";
const std::string get_config_value_by_name = "get_config_value_by_name";
const std::string set_config_value_by_name = "set_config_value_by_name";
const std::string get_directory_items = "get_directory_items";
const std::string get_drive_information = "get_drive_information";
const std::string get_open_files = "get_open_files";
const std::string get_pinned_files = "get_pinned_files";
const std::string import = "import";
const std::string unmount = "unmount";
const std::string pin_file = "pin_file";
const std::string pinned_status = "pinned_status";
const std::string unpin_file = "unpin_file";
} // namespace rpc_method
} // namespace repertory
#endif // INCLUDE_TYPES_RPC_HPP_

60
include/types/skynet.hpp Normal file
View File

@ -0,0 +1,60 @@
/*
Copyright <2018-2022> <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_TYPES_SKYNET_HPP_
#define INCLUDE_TYPES_SKYNET_HPP_
#include "common.hpp"
#include "types/repertory.hpp"
namespace repertory {
static const std::array<std::string, 2u> DEFAULT_SKYNET_URLS = {
"siasky.net",
"https://account.siasky.net",
};
struct skynet_config {
std::string encryption_token;
std::vector<host_config> portal_list = {
{"", "", 443, DEFAULT_SKYNET_URLS[0u], "", "https", 60000, DEFAULT_SKYNET_URLS[1u], "", ""},
};
static std::vector<host_config> from_string(const std::string &list);
std::string to_string() const { return to_string(portal_list); }
static std::string to_string(const std::vector<host_config> &list);
};
struct skylink_import {
std::string directory;
std::string file_name; // Ignored - informational only
std::string skylink;
std::string token;
static skylink_import from_json(const json &j);
static skylink_import from_string(const std::string &str);
json to_json() const;
};
typedef std::vector<skylink_import> skylink_import_list;
} // namespace repertory
#endif // INCLUDE_TYPES_SKYNET_HPP_

View File

@ -0,0 +1,31 @@
/*
Copyright <2018-2022> <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_TYPES_STARTUP_EXCEPTION_HPP_
#define INCLUDE_TYPES_STARTUP_EXCEPTION_HPP_
#include "common.hpp"
namespace repertory {
class startup_exception : public virtual std::runtime_error {
public:
explicit startup_exception(const std::string &msg) : std::runtime_error(msg) {}
};
} // namespace repertory
#endif // INCLUDE_TYPES_STARTUP_EXCEPTION_HPP_

View File

@ -0,0 +1,97 @@
/*
Copyright <2018-2022> <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_UPLOAD_UPLOAD_MANAGER_HPP_
#define INCLUDE_UPLOAD_UPLOAD_MANAGER_HPP_
#include "common.hpp"
#include "types/repertory.hpp"
namespace repertory {
class app_config;
class upload_manager final {
public:
struct upload {
std::string api_path;
bool cancel = false;
std::string encryption_token;
std::string source_path;
std::unique_ptr<std::thread> thread;
bool completed = true;
bool retry = false;
void wait() {
while (not completed) {
std::this_thread::sleep_for(1ms);
}
}
};
typedef std::function<bool(const std::string &api_path)> api_file_exists_callback;
typedef std::function<host_config(const bool &upload)> get_host_config_callback;
typedef std::function<void(const std::string &api_path, const std::string &source_path,
const json &data)>
upload_completed_callback;
typedef std::function<api_error(const upload &upload, json &data, json &error)>
upload_handler_callback;
public:
upload_manager(const app_config &config, api_file_exists_callback api_file_exists,
upload_handler_callback upload_handler,
upload_completed_callback upload_completed);
~upload_manager();
private:
const app_config &config_;
const api_file_exists_callback api_file_exists_;
upload_handler_callback upload_handler_;
const upload_completed_callback upload_completed_;
std::unique_ptr<rocksdb::DB> upload_db_;
std::unordered_map<std::string, std::shared_ptr<upload>> upload_lookup_;
std::deque<upload *> upload_queue_;
std::deque<upload *> active_uploads_;
const std::string ROCKS_DB_NAME = "upload_db";
bool stop_requested_ = false;
mutable std::mutex upload_mutex_;
std::condition_variable upload_notify_;
std::unique_ptr<std::thread> upload_thread_;
private:
void upload_thread();
public:
bool execute_if_not_processing(const std::vector<std::string> &api_paths,
const std::function<void()> &action) const;
std::size_t get_count() const { return upload_lookup_.size(); }
bool is_processing(const std::string &api_path) const;
api_error queue_upload(const std::string &api_path, const std::string &source_path,
const std::string &encryption_token);
api_error remove_upload(const std::string &api_path);
void start();
void stop();
};
} // namespace repertory
#endif // INCLUDE_UPLOAD_UPLOAD_MANAGER_HPP_

123
include/utils/Base64.hpp Normal file
View File

@ -0,0 +1,123 @@
#ifndef _MACARON_BASE64_H_
#define _MACARON_BASE64_H_
/**
* The MIT License (MIT)
* Copyright (c) 2016 tomykaira
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
* LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
* OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
#include <string>
#include <vector>
namespace macaron {
namespace Base64 {
static std::string Encode(const char *data, const size_t &len) {
static constexpr char sEncodingTable[] = {
'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P',
'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', 'a', 'b', 'c', 'd', 'e', 'f',
'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v',
'w', 'x', 'y', 'z', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '+', '/'};
size_t in_len = len;
std::string ret;
if (in_len > 0) {
size_t out_len = 4 * ((in_len + 2) / 3);
ret = std::string(out_len, '\0');
size_t i;
char *p = const_cast<char *>(ret.c_str());
for (i = 0; i < in_len - 2; i += 3) {
*p++ = sEncodingTable[(data[i] >> 2) & 0x3F];
*p++ = sEncodingTable[((data[i] & 0x3) << 4) | ((int)(data[i + 1] & 0xF0) >> 4)];
*p++ = sEncodingTable[((data[i + 1] & 0xF) << 2) | ((int)(data[i + 2] & 0xC0) >> 6)];
*p++ = sEncodingTable[data[i + 2] & 0x3F];
}
if (i < in_len) {
*p++ = sEncodingTable[(data[i] >> 2) & 0x3F];
if (i == (in_len - 1)) {
*p++ = sEncodingTable[((data[i] & 0x3) << 4)];
*p++ = '=';
} else {
*p++ = sEncodingTable[((data[i] & 0x3) << 4) | ((int)(data[i + 1] & 0xF0) >> 4)];
*p++ = sEncodingTable[((data[i + 1] & 0xF) << 2)];
}
*p++ = '=';
}
}
return ret;
}
static std::string Encode(const std::string &data) { return Encode(&data[0], data.size()); }
static std::vector<char> Decode(const std::string &input) {
static constexpr unsigned char kDecodingTable[] = {
64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 62,
64, 64, 64, 63, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 64, 64, 64, 64, 64, 64, 64, 0,
1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22,
23, 24, 25, 64, 64, 64, 64, 64, 64, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38,
39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 64, 64, 64, 64, 64, 64, 64, 64, 64,
64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64};
std::vector<char> out;
if (not input.empty()) {
size_t in_len = input.size();
if (in_len % 4 != 0)
throw std::runtime_error("Input data size is not a multiple of 4");
size_t out_len = in_len / 4 * 3;
if (input[in_len - 1] == '=')
out_len--;
if (input[in_len - 2] == '=')
out_len--;
out.resize(out_len);
for (size_t i = 0, j = 0; i < in_len;) {
uint32_t a = input[i] == '=' ? 0 & i++ : kDecodingTable[static_cast<int>(input[i++])];
uint32_t b = input[i] == '=' ? 0 & i++ : kDecodingTable[static_cast<int>(input[i++])];
uint32_t c = input[i] == '=' ? 0 & i++ : kDecodingTable[static_cast<int>(input[i++])];
uint32_t d = input[i] == '=' ? 0 & i++ : kDecodingTable[static_cast<int>(input[i++])];
uint32_t triple = (a << 3 * 6) + (b << 2 * 6) + (c << 1 * 6) + (d << 0 * 6);
if (j < out_len)
out[j++] = (triple >> 2 * 8) & 0xFF;
if (j < out_len)
out[j++] = (triple >> 1 * 8) & 0xFF;
if (j < out_len)
out[j++] = (triple >> 0 * 8) & 0xFF;
}
}
return out;
}
} // namespace Base64
} // namespace macaron
#endif /* _MACARON_BASE64_H_ */

119
include/utils/cli_utils.hpp Normal file
View File

@ -0,0 +1,119 @@
/*
Copyright <2018-2022> <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_CLI_UTILS_HPP_
#define INCLUDE_UTILS_CLI_UTILS_HPP_
#include "common.hpp"
#include "types/repertory.hpp"
namespace repertory::utils::cli {
typedef std::array<std::string, 2> option;
namespace options {
static const option check_version_option = {"-cv", "--check_version"};
static const option display_config_option = {"-dc", "--display_config"};
static const option data_directory_option = {"-dd", "--data_directory"};
static const option drive_information_option = {"-di", "--drive_information"};
static const option export_option = {"-ex", "--export"};
static const option export_all_option = {"-ea", "--export_all"};
#if defined(REPERTORY_ENABLE_S3)
static const option s3_option = {"-s3", "--s3"};
static const option name_option = {"-na", "--name"};
#endif // defined(REPERTORY_ENABLE_S3)
static const option generate_config_option = {"-gc", "--generate_config"};
static const option get_option = {"-get", "--get"};
static const option get_directory_items_option = {"-gdi", "--get_directory_items"};
static const option get_pinned_files_option = {"-gpf", "--get_pinned_files"};
static const option help_option = {"-h", "--help"};
static const option hidden_option = {"-hidden", "--hidden"};
static const option import_option = {"-im", "--import"};
static const option import_json_option = {"-ij", "--import_json"};
static const option open_files_option = {"-of", "--open_files"};
static const option pin_file_option = {"-pf", "--pin_file"};
static const option pinned_status_option = {"-ps", "--pinned_status"};
static const option password_option = {"-pw", "--password"};
#if defined(REPERTORY_ENABLE_SKYNET)
static const option skynet_option = {"-sk", "--skynet"};
static const option test_skynet_auth_option = {"-tsa", "--test_skynet_auth"};
#endif // defined(REPERTORY_ENABLE_SKYNET)
static const option remote_mount_option = {"-rm", "--remote_mount"};
static const option set_option = {"-set", "--set"};
static const option status_option = {"-status", "--status"};
static const option unmount_option = {"-unmount", "--unmount"};
static const option unpin_file_option = {"-uf", "--unpin_file"};
static const option user_option = {"-us", "--user"};
static const option version_option = {"-V", "--version"};
static const std::vector<option> option_list = {
check_version_option,
display_config_option,
data_directory_option,
drive_information_option,
export_option,
export_all_option,
#if defined(REPERTORY_ENABLE_S3)
s3_option,
name_option,
#endif // defined(REPERTORY_ENABLE_S3)
generate_config_option,
get_option,
get_directory_items_option,
get_pinned_files_option,
help_option,
hidden_option,
import_option,
import_json_option,
open_files_option,
password_option,
pin_file_option,
pinned_status_option,
#if defined(REPERTORY_ENABLE_SKYNET)
skynet_option,
test_skynet_auth_option,
#endif // defined(REPERTORY_ENABLE_SKYNET)
remote_mount_option,
set_option,
status_option,
unmount_option,
unpin_file_option,
user_option,
version_option,
};
} // namespace options
// Prototypes
void get_api_authentication_data(std::string &user, std::string &password, std::uint16_t &port,
const provider_type &pt, const std::string &data_directory);
provider_type get_provider_type_from_args(const int &argc, char *argv[]);
bool has_option(const int &argc, char *argv[], const std::string &option_name);
bool has_option(const int &argc, char *argv[], const option &opt);
std::vector<std::string> parse_option(const int &argc, char *argv[], const std::string &option_name,
std::uint8_t count);
exit_code parse_string_option(const int &argc, char **argv, const option &opt, std::string &value);
std::vector<std::string> parse_drive_options(const int &argc, char **argv, provider_type &pt,
std::string &data_directory);
} // namespace repertory::utils::cli
#endif // INCLUDE_UTILS_CLI_UTILS_HPP_

View File

@ -0,0 +1,42 @@
/*
Copyright <2018-2022> <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_COM_INIT_WRAPPER_HPP_
#define INCLUDE_UTILS_COM_INIT_WRAPPER_HPP_
#ifdef _WIN32
#include "common.hpp"
namespace repertory {
class com_init_wrapper {
public:
com_init_wrapper() : uninit_(SUCCEEDED(::CoInitializeEx(nullptr, COINIT_APARTMENTTHREADED))) {}
~com_init_wrapper() {
if (uninit_) {
::CoUninitialize();
}
}
private:
const BOOL uninit_;
};
} // namespace repertory
#endif // _WIN32
#endif // INCLUDE_UTILS_COM_INIT_WRAPPER_HPP_

View File

@ -0,0 +1,87 @@
/*
Copyright <2018-2022> <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_ENCRYPTING_READER_HPP_
#define INCLUDE_UTILS_ENCRYPTING_READER_HPP_
#include "common.hpp"
#include "utils/file_utils.hpp"
namespace repertory::utils::encryption {
class encrypting_reader final {
public:
encrypting_reader(const std::string &file_name, const std::string &source_path,
const bool &stop_requested, const std::string &token,
const size_t error_return = 0);
encrypting_reader(const encrypting_reader &r);
~encrypting_reader();
public:
typedef std::basic_iostream<char, std::char_traits<char>> iostream;
typedef std::basic_streambuf<char, std::char_traits<char>> streambuf;
private:
const CryptoPP::SecByteBlock key_;
const bool &stop_requested_;
const size_t error_return_;
std::unordered_map<std::size_t, std::vector<char>> chunk_buffers_;
std::string encrypted_file_name_;
std::size_t last_data_chunk_ = 0u;
std::size_t last_data_chunk_size_ = 0u;
std::uint64_t read_offset_ = 0u;
native_file_ptr source_file_;
std::uint64_t total_size_ = 0u;
private:
static const std::size_t header_size_;
static const std::size_t data_chunk_size_;
static const std::size_t encrypted_chunk_size_;
private:
size_t reader_function(char *buffer, size_t size, size_t nitems);
public:
static std::uint64_t calculate_decrypted_size(const std::uint64_t &total_size);
std::shared_ptr<iostream> create_iostream() const;
static constexpr const std::size_t &get_encrypted_chunk_size() { return encrypted_chunk_size_; }
static constexpr const std::size_t &get_data_chunk_size() { return data_chunk_size_; }
std::string get_encrypted_file_name() const { return encrypted_file_name_; }
std::size_t get_error_return() const { return error_return_; }
static constexpr const std::size_t &get_header_size() { return header_size_; }
const bool &get_stop_requested() const { return stop_requested_; }
std::uint64_t get_total_size() const { return total_size_; }
static size_t reader_function(char *buffer, size_t size, size_t nitems, void *instream) {
return reinterpret_cast<encrypting_reader *>(instream)->reader_function(buffer, size, nitems);
}
void set_read_position(const std::uint64_t &position) { read_offset_ = position; }
};
} // namespace repertory::utils::encryption
#endif // INCLUDE_UTILS_ENCRYPTING_READER_HPP_

Some files were not shown because too many files have changed in this diff Show More