renamed project
This commit is contained in:
		
							
								
								
									
										456
									
								
								repertory/librepertory/include/app_config.hpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										456
									
								
								repertory/librepertory/include/app_config.hpp
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,456 @@ | ||||
| /* | ||||
|   Copyright <2018-2024> <scott.e.graves@protonmail.com> | ||||
|  | ||||
|   Permission is hereby granted, free of charge, to any person obtaining a copy | ||||
|   of this software and associated documentation files (the "Software"), to deal | ||||
|   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 "events/event_system.hpp" | ||||
| #include "events/events.hpp" | ||||
| #include "types/repertory.hpp" | ||||
| #include "utils/error_utils.hpp" | ||||
|  | ||||
| namespace repertory { | ||||
| class app_config final { | ||||
| public: | ||||
|   [[nodiscard]] static auto default_agent_name(const provider_type &prov) | ||||
|       -> std::string; | ||||
|  | ||||
|   [[nodiscard]] static auto default_api_port(const provider_type &prov) | ||||
|       -> std::uint16_t; | ||||
|  | ||||
|   [[nodiscard]] static auto default_data_directory(const provider_type &prov) | ||||
|       -> std::string; | ||||
|  | ||||
|   [[nodiscard]] static auto default_remote_port(const provider_type &prov) | ||||
|       -> std::uint16_t; | ||||
|  | ||||
|   [[nodiscard]] static auto default_rpc_port(const provider_type &prov) | ||||
|       -> std::uint16_t; | ||||
|  | ||||
|   [[nodiscard]] static auto get_provider_api_password(const provider_type &prov) | ||||
|       -> std::string; | ||||
|  | ||||
|   [[nodiscard]] static auto get_provider_display_name(const provider_type &prov) | ||||
|       -> std::string; | ||||
|  | ||||
|   [[nodiscard]] static auto get_provider_name(const provider_type &prov) | ||||
|       -> std::string; | ||||
|  | ||||
| public: | ||||
|   app_config(const provider_type &prov, const std::string &data_directory = ""); | ||||
|  | ||||
|   ~app_config() { save(); } | ||||
|  | ||||
| private: | ||||
|   provider_type prov_; | ||||
|   std::string api_auth_; | ||||
|   std::uint16_t api_port_; | ||||
|   std::string api_user_; | ||||
|   bool config_changed_; | ||||
|   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_; | ||||
|   encrypt_config encrypt_config_; | ||||
|   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_; | ||||
|   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_; | ||||
|   std::string cache_directory_; | ||||
|   host_config hc_; | ||||
|   s3_config s3_config_; | ||||
|   std::uint64_t version_ = REPERTORY_CONFIG_VERSION; | ||||
|   std::string log_directory_; | ||||
|   mutable std::recursive_mutex read_write_mutex_; | ||||
|   mutable std::recursive_mutex remote_mount_mutex_; | ||||
|  | ||||
| private: | ||||
|   [[nodiscard]] auto load() -> bool; | ||||
|  | ||||
|   template <typename dest> | ||||
|   auto get_value(const json &json_document, const std::string &name, dest &dst, | ||||
|                  bool &success_flag) -> bool { | ||||
|     constexpr const auto *function_name = | ||||
|         static_cast<const char *>(__FUNCTION__); | ||||
|  | ||||
|     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) { | ||||
|       utils::error::raise_error(function_name, ex, "exception occurred"); | ||||
|       success_flag = false; | ||||
|       ret = false; | ||||
|     } | ||||
|  | ||||
|     return ret; | ||||
|   } | ||||
|  | ||||
|   template <typename dest, typename source> | ||||
|   auto set_value(dest &dst, const source &src) -> bool { | ||||
|     auto ret = false; | ||||
|     recur_mutex_lock lock(read_write_mutex_); | ||||
|     if (dst != src) { | ||||
|       dst = src; | ||||
|       config_changed_ = true; | ||||
|       save(); | ||||
|       ret = true; | ||||
|     } | ||||
|  | ||||
|     return ret; | ||||
|   } | ||||
|  | ||||
| public: | ||||
|   [[nodiscard]] auto get_api_auth() const -> std::string { return api_auth_; } | ||||
|  | ||||
|   [[nodiscard]] auto get_api_port() const -> std::uint16_t { return api_port_; } | ||||
|  | ||||
|   [[nodiscard]] auto get_api_user() const -> std::string { return api_user_; } | ||||
|  | ||||
|   [[nodiscard]] auto get_cache_directory() const -> std::string { | ||||
|     return cache_directory_; | ||||
|   } | ||||
|  | ||||
|   [[nodiscard]] auto get_chunk_downloader_timeout_secs() const -> std::uint8_t { | ||||
|     return std::max(min_download_timeout_secs_, download_timeout_secs_); | ||||
|   } | ||||
|  | ||||
|   [[nodiscard]] auto get_config_file_path() const -> std::string; | ||||
|  | ||||
|   [[nodiscard]] auto get_data_directory() const -> std::string { | ||||
|     return data_directory_; | ||||
|   } | ||||
|  | ||||
|   [[nodiscard]] auto get_enable_chunk_download_timeout() const -> bool { | ||||
|     return enable_chunk_downloader_timeout_; | ||||
|   } | ||||
|  | ||||
|   [[nodiscard]] auto get_enable_comm_duration_events() const -> bool { | ||||
|     return enable_comm_duration_events_; | ||||
|   } | ||||
|  | ||||
|   [[nodiscard]] auto get_enable_drive_events() const -> bool { | ||||
|     return enable_drive_events_; | ||||
|   } | ||||
|  | ||||
|   [[nodiscard]] auto get_encrypt_config() const -> encrypt_config { | ||||
|     return encrypt_config_; | ||||
|   } | ||||
|  | ||||
| #ifdef _WIN32 | ||||
|   [[nodiscard]] auto get_enable_mount_manager() const -> bool { | ||||
|     return enable_mount_manager_; | ||||
|   } | ||||
| #endif | ||||
|  | ||||
|   [[nodiscard]] auto get_enable_max_cache_size() const -> bool { | ||||
|     return enable_max_cache_size_; | ||||
|   } | ||||
|  | ||||
|   [[nodiscard]] auto get_enable_remote_mount() const -> bool { | ||||
|     return enable_remote_mount_; | ||||
|   } | ||||
|  | ||||
|   [[nodiscard]] auto get_event_level() const -> event_level { | ||||
|     return event_level_; | ||||
|   } | ||||
|  | ||||
|   [[nodiscard]] auto get_eviction_delay_mins() const -> std::uint32_t { | ||||
|     return eviction_delay_mins_; | ||||
|   } | ||||
|  | ||||
|   [[nodiscard]] auto get_eviction_uses_accessed_time() const -> bool { | ||||
|     return eviction_uses_accessed_time_; | ||||
|   } | ||||
|  | ||||
|   [[nodiscard]] auto get_high_frequency_interval_secs() const -> std::uint8_t { | ||||
|     return std::max(static_cast<std::uint8_t>(1U), high_freq_interval_secs_); | ||||
|   } | ||||
|  | ||||
|   [[nodiscard]] auto get_host_config() const -> host_config { return hc_; } | ||||
|  | ||||
|   [[nodiscard]] auto get_is_remote_mount() const -> bool { | ||||
|     return is_remote_mount_; | ||||
|   } | ||||
|  | ||||
|   [[nodiscard]] auto get_json() const -> json; | ||||
|  | ||||
|   [[nodiscard]] auto get_log_directory() const -> std::string { | ||||
|     return log_directory_; | ||||
|   } | ||||
|  | ||||
|   [[nodiscard]] auto get_low_frequency_interval_secs() const -> std::uint32_t { | ||||
|     return std::max(1U, low_freq_interval_secs_); | ||||
|   } | ||||
|  | ||||
|   [[nodiscard]] auto get_max_cache_size_bytes() const -> std::uint64_t; | ||||
|  | ||||
|   [[nodiscard]] auto get_max_upload_count() const -> std::uint8_t { | ||||
|     return std::max(std::uint8_t(1U), max_upload_count_); | ||||
|   } | ||||
|  | ||||
|   [[nodiscard]] auto get_online_check_retry_secs() const -> std::uint16_t { | ||||
|     return std::max(std::uint16_t(15U), online_check_retry_secs_); | ||||
|   } | ||||
|  | ||||
|   [[nodiscard]] auto get_orphaned_file_retention_days() const -> std::uint16_t { | ||||
|     return std::min(static_cast<std::uint16_t>(31U), | ||||
|                     std::max(static_cast<std::uint16_t>(1U), | ||||
|                              orphaned_file_retention_days_)); | ||||
|   } | ||||
|  | ||||
|   [[nodiscard]] auto get_preferred_download_type() const -> download_type { | ||||
|     return utils::download_type_from_string(preferred_download_type_, | ||||
|                                             download_type::fallback); | ||||
|   } | ||||
|  | ||||
|   [[nodiscard]] auto get_provider_type() const -> provider_type { | ||||
|     return prov_; | ||||
|   } | ||||
|  | ||||
|   [[nodiscard]] auto get_read_ahead_count() const -> std::uint8_t { | ||||
|     return std::max(static_cast<std::uint8_t>(1U), read_ahead_count_); | ||||
|   } | ||||
|  | ||||
|   [[nodiscard]] auto get_remote_client_pool_size() const -> std::uint8_t { | ||||
|     return std::max(static_cast<std::uint8_t>(5U), remote_client_pool_size_); | ||||
|   } | ||||
|  | ||||
|   [[nodiscard]] auto get_remote_host_name_or_ip() const -> std::string { | ||||
|     return remote_host_name_or_ip_; | ||||
|   } | ||||
|  | ||||
|   [[nodiscard]] auto get_remote_max_connections() const -> std::uint8_t { | ||||
|     return std::max(static_cast<std::uint8_t>(1U), remote_max_connections_); | ||||
|   } | ||||
|  | ||||
|   [[nodiscard]] auto get_remote_port() const -> std::uint16_t { | ||||
|     return remote_port_; | ||||
|   } | ||||
|  | ||||
|   [[nodiscard]] auto get_remote_receive_timeout_secs() const -> std::uint16_t { | ||||
|     return remote_receive_timeout_secs_; | ||||
|   } | ||||
|  | ||||
|   [[nodiscard]] auto get_remote_send_timeout_secs() const -> std::uint16_t { | ||||
|     return remote_send_timeout_secs_; | ||||
|   } | ||||
|  | ||||
|   [[nodiscard]] auto get_remote_token() const -> std::string { | ||||
|     return remote_token_; | ||||
|   } | ||||
|  | ||||
|   [[nodiscard]] auto get_retry_read_count() const -> std::uint16_t { | ||||
|     return std::max(std::uint16_t(2), retry_read_count_); | ||||
|   } | ||||
|  | ||||
|   [[nodiscard]] auto get_ring_buffer_file_size() const -> std::uint16_t { | ||||
|     return std::max( | ||||
|         static_cast<std::uint16_t>(64U), | ||||
|         std::min(static_cast<std::uint16_t>(1024U), ring_buffer_file_size_)); | ||||
|   } | ||||
|  | ||||
|   [[nodiscard]] auto get_s3_config() const -> s3_config { return s3_config_; } | ||||
|  | ||||
|   [[nodiscard]] auto get_value_by_name(const std::string &name) -> std::string; | ||||
|  | ||||
|   [[nodiscard]] auto get_version() const -> std::uint64_t { return version_; } | ||||
|  | ||||
|   void save(); | ||||
|  | ||||
|   void set_api_auth(const std::string &api_auth) { | ||||
|     set_value(api_auth_, api_auth); | ||||
|   } | ||||
|  | ||||
|   void set_api_port(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( | ||||
|       std::uint8_t chunk_downloader_timeout_secs) { | ||||
|     set_value(download_timeout_secs_, chunk_downloader_timeout_secs); | ||||
|   } | ||||
|  | ||||
|   void | ||||
|   set_enable_chunk_downloader_timeout(bool enable_chunk_downloader_timeout) { | ||||
|     set_value(enable_chunk_downloader_timeout_, | ||||
|               enable_chunk_downloader_timeout); | ||||
|   } | ||||
|  | ||||
|   void set_enable_comm_duration_events(bool enable_comm_duration_events) { | ||||
|     set_value(enable_comm_duration_events_, enable_comm_duration_events); | ||||
|   } | ||||
|  | ||||
|   void set_enable_drive_events(bool enable_drive_events) { | ||||
|     set_value(enable_drive_events_, enable_drive_events); | ||||
|   } | ||||
|  | ||||
|   void set_enable_max_cache_size(bool enable_max_cache_size) { | ||||
|     set_value(enable_max_cache_size_, enable_max_cache_size); | ||||
|   } | ||||
|  | ||||
| #ifdef _WIN32 | ||||
|   void set_enable_mount_manager(bool enable_mount_manager) { | ||||
|     set_value(enable_mount_manager_, enable_mount_manager); | ||||
|   } | ||||
| #endif | ||||
|  | ||||
|   void set_enable_remote_mount(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(std::uint32_t eviction_delay_mins) { | ||||
|     set_value(eviction_delay_mins_, eviction_delay_mins); | ||||
|   } | ||||
|  | ||||
|   void set_eviction_uses_accessed_time(bool eviction_uses_accessed_time) { | ||||
|     set_value(eviction_uses_accessed_time_, eviction_uses_accessed_time); | ||||
|   } | ||||
|  | ||||
|   void | ||||
|   set_high_frequency_interval_secs(std::uint8_t high_frequency_interval_secs) { | ||||
|     set_value(high_freq_interval_secs_, high_frequency_interval_secs); | ||||
|   } | ||||
|  | ||||
| #ifdef PROJECT_TESTING | ||||
|   void set_host_config(host_config hc) { | ||||
|     config_changed_ = true; | ||||
|     hc_ = std::move(hc); | ||||
|     save(); | ||||
|   } | ||||
|  | ||||
|   void set_s3_config(s3_config s3) { | ||||
|     config_changed_ = true; | ||||
|     s3_config_ = std::move(s3); | ||||
|     save(); | ||||
|   } | ||||
| #endif | ||||
|  | ||||
|   void set_is_remote_mount(bool is_remote_mount); | ||||
|  | ||||
|   void | ||||
|   set_low_frequency_interval_secs(std::uint32_t low_frequency_interval_secs) { | ||||
|     set_value(low_freq_interval_secs_, low_frequency_interval_secs); | ||||
|   } | ||||
|  | ||||
|   void set_max_cache_size_bytes(std::uint64_t max_cache_size_bytes) { | ||||
|     set_value(max_cache_size_bytes_, max_cache_size_bytes); | ||||
|   } | ||||
|  | ||||
|   void set_max_upload_count(std::uint8_t max_upload_count) { | ||||
|     set_value(max_upload_count_, max_upload_count); | ||||
|   } | ||||
|  | ||||
|   void set_online_check_retry_secs(std::uint16_t online_check_retry_secs) { | ||||
|     set_value(online_check_retry_secs_, online_check_retry_secs); | ||||
|   } | ||||
|  | ||||
|   void | ||||
|   set_orphaned_file_retention_days(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(std::uint8_t read_ahead_count) { | ||||
|     set_value(read_ahead_count_, read_ahead_count); | ||||
|   } | ||||
|  | ||||
|   void set_remote_client_pool_size(std::uint8_t remote_client_pool_size) { | ||||
|     set_value(remote_client_pool_size_, remote_client_pool_size); | ||||
|   } | ||||
|  | ||||
|   void set_ring_buffer_file_size(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(std::uint8_t remote_max_connections) { | ||||
|     set_value(remote_max_connections_, remote_max_connections); | ||||
|   } | ||||
|  | ||||
|   void set_remote_port(std::uint16_t remote_port) { | ||||
|     set_value(remote_port_, remote_port); | ||||
|   } | ||||
|  | ||||
|   void | ||||
|   set_remote_receive_timeout_secs(std::uint16_t remote_receive_timeout_secs) { | ||||
|     set_value(remote_receive_timeout_secs_, remote_receive_timeout_secs); | ||||
|   } | ||||
|  | ||||
|   void set_remote_send_timeout_secs(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(std::uint16_t retry_read_count) { | ||||
|     set_value(retry_read_count_, retry_read_count); | ||||
|   } | ||||
|  | ||||
|   [[nodiscard]] auto set_value_by_name(const std::string &name, | ||||
|                                        const std::string &value) -> std::string; | ||||
| }; | ||||
| } // namespace repertory | ||||
|  | ||||
| #endif // INCLUDE_APP_CONFIG_HPP_ | ||||
							
								
								
									
										242
									
								
								repertory/librepertory/include/comm/curl/curl_comm.hpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										242
									
								
								repertory/librepertory/include/comm/curl/curl_comm.hpp
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,242 @@ | ||||
| /* | ||||
|   Copyright <2018-2024> <scott.e.graves@protonmail.com> | ||||
|  | ||||
|   Permission is hereby granted, free of charge, to any person obtaining a copy | ||||
|   of this software and associated documentation files (the "Software"), to deal | ||||
|   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 "comm/curl/multi_request.hpp" | ||||
| #include "comm/i_http_comm.hpp" | ||||
| #include "events/event_system.hpp" | ||||
| #include "events/events.hpp" | ||||
| #include "utils/encryption.hpp" | ||||
| #include "utils/utils.hpp" | ||||
|  | ||||
| namespace repertory { | ||||
| class curl_comm final : public i_http_comm { | ||||
| public: | ||||
|   curl_comm() = delete; | ||||
|  | ||||
|   explicit curl_comm(host_config cfg); | ||||
|  | ||||
|   explicit curl_comm(s3_config cfg); | ||||
|  | ||||
| private: | ||||
|   using write_callback = size_t (*)(char *, size_t, size_t, void *); | ||||
|  | ||||
|   struct read_write_info final { | ||||
|     repertory::data_buffer data{}; | ||||
|     repertory::stop_type &stop_requested; | ||||
|   }; | ||||
|  | ||||
|   static const write_callback write_data; | ||||
|   static const write_callback write_headers; | ||||
|  | ||||
| private: | ||||
|   std::optional<host_config> host_config_; | ||||
|   std::optional<s3_config> s3_config_; | ||||
|  | ||||
| private: | ||||
|   bool use_s3_path_style_{false}; | ||||
|  | ||||
| public: | ||||
|   [[nodiscard]] static auto construct_url(CURL *curl, | ||||
|                                           const std::string &relative_path, | ||||
|                                           const host_config &cfg) | ||||
|       -> std::string; | ||||
|  | ||||
|   [[nodiscard]] static auto create_host_config(const s3_config &cfg, | ||||
|                                                bool use_s3_path_style) | ||||
|       -> host_config; | ||||
|  | ||||
|   [[nodiscard]] static auto url_encode(CURL *curl, const std::string &data, | ||||
|                                        bool allow_slash) -> std::string; | ||||
|  | ||||
|   template <typename request_type> | ||||
|   [[nodiscard]] static auto | ||||
|   make_encrypted_request(const host_config &cfg, const request_type &request, | ||||
|                          long &response_code, stop_type &stop_requested) | ||||
|       -> bool { | ||||
|     response_code = 0; | ||||
|  | ||||
|     if (not request.decryption_token.has_value() || | ||||
|         request.decryption_token.value().empty()) { | ||||
|       return false; | ||||
|     } | ||||
|  | ||||
|     if (not request.range.has_value()) { | ||||
|       return false; | ||||
|     } | ||||
|  | ||||
|     if (not request.total_size.has_value()) { | ||||
|       return false; | ||||
|     } | ||||
|  | ||||
|     data_buffer data{}; | ||||
|     const auto key = | ||||
|         utils::encryption::generate_key(request.decryption_token.value()); | ||||
|     const auto result = utils::encryption::read_encrypted_range( | ||||
|         request.range.value(), key, | ||||
|         [&](std::vector<char> &ct, std::uint64_t start_offset, | ||||
|             std::uint64_t end_offset) -> api_error { | ||||
|           auto encrypted_request = request; | ||||
|           encrypted_request.decryption_token = std::nullopt; | ||||
|           encrypted_request.range = {{start_offset, end_offset}}; | ||||
|           encrypted_request.response_handler = [&ct](const auto &encrypted_data, | ||||
|                                                      long /*response_code*/) { | ||||
|             ct = encrypted_data; | ||||
|           }; | ||||
|           encrypted_request.total_size = std::nullopt; | ||||
|  | ||||
|           if (not make_request(cfg, encrypted_request, response_code, | ||||
|                                stop_requested)) { | ||||
|             return api_error::comm_error; | ||||
|           } | ||||
|  | ||||
|           if (response_code != 200) { | ||||
|             return api_error::comm_error; | ||||
|           } | ||||
|  | ||||
|           return api_error::success; | ||||
|         }, | ||||
|         request.total_size.value(), data); | ||||
|     if (result != api_error::success) { | ||||
|       return false; | ||||
|     } | ||||
|  | ||||
|     if (request.response_handler.has_value()) { | ||||
|       request.response_handler.value()(data, response_code); | ||||
|     } | ||||
|  | ||||
|     return true; | ||||
|   } | ||||
|  | ||||
|   template <typename request_type> | ||||
|   [[nodiscard]] static auto | ||||
|   make_request(const host_config &cfg, const request_type &request, | ||||
|                long &response_code, stop_type &stop_requested) -> bool { | ||||
|     if (request.decryption_token.has_value() && | ||||
|         not request.decryption_token.value().empty()) { | ||||
|       return make_encrypted_request(cfg, request, response_code, | ||||
|                                     stop_requested); | ||||
|     } | ||||
|  | ||||
|     response_code = 0; | ||||
|  | ||||
|     auto *curl = utils::create_curl(); | ||||
|     if (not request.set_method(curl, stop_requested)) { | ||||
|       return false; | ||||
|     } | ||||
|  | ||||
|     if (not cfg.agent_string.empty()) { | ||||
|       curl_easy_setopt(curl, CURLOPT_USERAGENT, cfg.agent_string.c_str()); | ||||
|     } | ||||
|  | ||||
|     if (request.allow_timeout && cfg.timeout_ms) { | ||||
|       curl_easy_setopt(curl, CURLOPT_TIMEOUT_MS, cfg.timeout_ms); | ||||
|     } | ||||
|  | ||||
|     std::string range_list{}; | ||||
|     if (request.range.has_value()) { | ||||
|       range_list = std::to_string(request.range.value().begin) + '-' + | ||||
|                    std::to_string(request.range.value().end); | ||||
|       curl_easy_setopt(curl, CURLOPT_RANGE, range_list.c_str()); | ||||
|     } | ||||
|  | ||||
|     if (request.response_headers.has_value()) { | ||||
|       curl_easy_setopt(curl, CURLOPT_HEADERDATA, | ||||
|                        &request.response_headers.value()); | ||||
|       curl_easy_setopt(curl, CURLOPT_HEADERFUNCTION, write_headers); | ||||
|     } | ||||
|  | ||||
|     read_write_info write_info{{}, stop_requested}; | ||||
|     if (request.response_handler.has_value()) { | ||||
|       curl_easy_setopt(curl, CURLOPT_WRITEDATA, &write_info); | ||||
|       curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, write_data); | ||||
|     } | ||||
|  | ||||
|     std::string parameters{}; | ||||
|     for (const auto ¶m : request.query) { | ||||
|       parameters += (parameters.empty() ? '?' : '&') + param.first + '=' + | ||||
|                     url_encode(curl, param.second, false); | ||||
|     } | ||||
|  | ||||
|     if (not cfg.api_password.empty()) { | ||||
|       curl_easy_setopt(curl, CURLOPT_USERNAME, cfg.api_user.c_str()); | ||||
|       curl_easy_setopt(curl, CURLOPT_PASSWORD, cfg.api_password.c_str()); | ||||
|     } else if (not cfg.api_user.empty()) { | ||||
|       curl_easy_setopt(curl, CURLOPT_USERNAME, cfg.api_user.c_str()); | ||||
|     } | ||||
|  | ||||
|     if (request.aws_service.has_value()) { | ||||
|       curl_easy_setopt(curl, CURLOPT_AWS_SIGV4, | ||||
|                        request.aws_service.value().c_str()); | ||||
|     } | ||||
|  | ||||
|     auto url = construct_url(curl, request.get_path(), cfg) + parameters; | ||||
|     curl_easy_setopt(curl, CURLOPT_URL, url.c_str()); | ||||
|  | ||||
|     multi_request curl_request(curl, stop_requested); | ||||
|  | ||||
|     CURLcode curl_code{}; | ||||
|     curl_request.get_result(curl_code, response_code); | ||||
|     if (curl_code != CURLE_OK) { | ||||
|       event_system::instance().raise<curl_error>(url, curl_code); | ||||
|       return false; | ||||
|     } | ||||
|  | ||||
|     if (request.response_handler.has_value()) { | ||||
|       request.response_handler.value()(write_info.data, response_code); | ||||
|     } | ||||
|  | ||||
|     return true; | ||||
|   } | ||||
|  | ||||
| public: | ||||
|   void enable_s3_path_style(bool enable) override; | ||||
|  | ||||
|   [[nodiscard]] auto make_request(const curl::requests::http_delete &del, | ||||
|                                   long &response_code, | ||||
|                                   stop_type &stop_requested) const | ||||
|       -> bool override; | ||||
|  | ||||
|   [[nodiscard]] auto make_request(const curl::requests::http_get &get, | ||||
|                                   long &response_code, | ||||
|                                   stop_type &stop_requested) const | ||||
|       -> bool override; | ||||
|  | ||||
|   [[nodiscard]] auto make_request(const curl::requests::http_head &head, | ||||
|                                   long &response_code, | ||||
|                                   stop_type &stop_requested) const | ||||
|       -> bool override; | ||||
|  | ||||
|   [[nodiscard]] auto make_request(const curl::requests::http_post &post_file, | ||||
|                                   long &response_code, | ||||
|                                   stop_type &stop_requested) const | ||||
|       -> bool override; | ||||
|  | ||||
|   [[nodiscard]] auto make_request(const curl::requests::http_put_file &put_file, | ||||
|                                   long &response_code, | ||||
|                                   stop_type &stop_requested) const | ||||
|       -> bool override; | ||||
| }; | ||||
| } // namespace repertory | ||||
|  | ||||
| #endif // INCLUDE_COMM_CURL_CURL_COMM_HPP_ | ||||
							
								
								
									
										44
									
								
								repertory/librepertory/include/comm/curl/multi_request.hpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										44
									
								
								repertory/librepertory/include/comm/curl/multi_request.hpp
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,44 @@ | ||||
| /* | ||||
|   Copyright <2018-2024> <scott.e.graves@protonmail.com> | ||||
|  | ||||
|   Permission is hereby granted, free of charge, to any person obtaining a copy | ||||
|   of this software and associated documentation files (the "Software"), to deal | ||||
|   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 "types/repertory.hpp" | ||||
|  | ||||
| namespace repertory { | ||||
| class multi_request final { | ||||
| public: | ||||
|   multi_request(CURL *curl_handle, stop_type &stop_requested); | ||||
|  | ||||
|   ~multi_request(); | ||||
|  | ||||
| private: | ||||
|   CURL *curl_handle_; | ||||
|   stop_type &stop_requested_; | ||||
|   CURLM *multi_handle_; | ||||
|  | ||||
| public: | ||||
|   void get_result(CURLcode &curl_code, long &http_code); | ||||
| }; | ||||
| } // namespace repertory | ||||
|  | ||||
| #endif // INCLUDE_COMM_CURL_MULTI_REQUEST_HPP_ | ||||
| @@ -0,0 +1,40 @@ | ||||
| /* | ||||
|   Copyright <2018-2024> <scott.e.graves@protonmail.com> | ||||
|  | ||||
|   Permission is hereby granted, free of charge, to any person obtaining a copy | ||||
|   of this software and associated documentation files (the "Software"), to deal | ||||
|   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_REQUESTS_HTTP_DELETE_HPP_ | ||||
| #define INCLUDE_COMM_CURL_CURL_REQUESTS_HTTP_DELETE_HPP_ | ||||
|  | ||||
| #include "comm/curl/requests/http_request_base.hpp" | ||||
|  | ||||
| namespace repertory::curl::requests { | ||||
| struct http_delete final : http_request_base { | ||||
|   ~http_delete() override = default; | ||||
|  | ||||
|   [[nodiscard]] auto set_method(CURL *curl, | ||||
|                                 stop_type & /* stop_requested */) const | ||||
|       -> bool override { | ||||
|     curl_easy_setopt(curl, CURLOPT_CUSTOMREQUEST, "DELETE"); | ||||
|     return true; | ||||
|   } | ||||
| }; | ||||
| } // namespace repertory::curl::requests | ||||
|  | ||||
| #endif // INCLUDE_COMM_CURL_CURL_REQUESTS_HTTP_DELETE_HPP_ | ||||
| @@ -0,0 +1,45 @@ | ||||
| /* | ||||
|   Copyright <2018-2024> <scott.e.graves@protonmail.com> | ||||
|  | ||||
|   Permission is hereby granted, free of charge, to any person obtaining a copy | ||||
|   of this software and associated documentation files (the "Software"), to deal | ||||
|   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_REQUESTS_HTTP_GET_HPP_ | ||||
| #define INCLUDE_COMM_CURL_CURL_REQUESTS_HTTP_GET_HPP_ | ||||
|  | ||||
| #include "comm/curl/requests/http_request_base.hpp" | ||||
|  | ||||
| namespace repertory::curl::requests { | ||||
| struct http_get final : http_request_base { | ||||
|   http_get() = default; | ||||
|   http_get(const http_get &) = default; | ||||
|   http_get(http_get &&) = default; | ||||
|   auto operator=(const http_get &) -> http_get & = default; | ||||
|   auto operator=(http_get &&) -> http_get & = default; | ||||
|   ~http_get() override = default; | ||||
|  | ||||
|   [[nodiscard]] auto set_method(CURL *curl, | ||||
|                                 stop_type & /*stop_requested*/) const | ||||
|       -> bool override { | ||||
|     curl_easy_setopt(curl, CURLOPT_HTTPGET, 1L); | ||||
|     return true; | ||||
|   } | ||||
| }; | ||||
| } // namespace repertory::curl::requests | ||||
|  | ||||
| #endif // INCLUDE_COMM_CURL_CURL_REQUESTS_HTTP_GET_HPP_ | ||||
| @@ -0,0 +1,41 @@ | ||||
| /* | ||||
|   Copyright <2018-2024> <scott.e.graves@protonmail.com> | ||||
|  | ||||
|   Permission is hereby granted, free of charge, to any person obtaining a copy | ||||
|   of this software and associated documentation files (the "Software"), to deal | ||||
|   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_REQUESTS_HTTP_HEAD_HPP_ | ||||
| #define INCLUDE_COMM_CURL_CURL_REQUESTS_HTTP_HEAD_HPP_ | ||||
|  | ||||
| #include "comm/curl/requests/http_request_base.hpp" | ||||
|  | ||||
| namespace repertory::curl::requests { | ||||
| struct http_head final : http_request_base { | ||||
|   ~http_head() override = default; | ||||
|  | ||||
|   [[nodiscard]] auto set_method(CURL *curl, | ||||
|                                 stop_type & /* stop_requested */) const | ||||
|       -> bool override { | ||||
|     curl_easy_setopt(curl, CURLOPT_CUSTOMREQUEST, "HEAD"); | ||||
|     curl_easy_setopt(curl, CURLOPT_NOBODY, 1L); | ||||
|     return true; | ||||
|   } | ||||
| }; | ||||
| } // namespace repertory::curl::requests | ||||
|  | ||||
| #endif // INCLUDE_COMM_CURL_CURL_REQUESTS_HTTP_HEAD_HPP_ | ||||
| @@ -0,0 +1,49 @@ | ||||
| /* | ||||
|   Copyright <2018-2024> <scott.e.graves@protonmail.com> | ||||
|  | ||||
|   Permission is hereby granted, free of charge, to any person obtaining a copy | ||||
|   of this software and associated documentation files (the "Software"), to deal | ||||
|   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_REQUESTS_HTTP_POST_HPP_ | ||||
| #define INCLUDE_COMM_CURL_CURL_REQUESTS_HTTP_POST_HPP_ | ||||
|  | ||||
| #include "comm/curl/requests/http_request_base.hpp" | ||||
|  | ||||
| namespace repertory::curl::requests { | ||||
| struct http_post final : http_request_base { | ||||
|   http_post() = default; | ||||
|   http_post(const http_post &) = default; | ||||
|   http_post(http_post &&) = default; | ||||
|   auto operator=(const http_post &) -> http_post & = default; | ||||
|   auto operator=(http_post &&) -> http_post & = default; | ||||
|  | ||||
|   ~http_post() override; | ||||
|  | ||||
|   std::optional<nlohmann::json> json; | ||||
|  | ||||
|   [[nodiscard]] auto set_method(CURL *curl, | ||||
|                                 stop_type & /*stop_requested*/) const | ||||
|       -> bool override; | ||||
|  | ||||
| private: | ||||
|   mutable curl_slist *headers{nullptr}; | ||||
|   mutable std::optional<std::string> json_str; | ||||
| }; | ||||
| } // namespace repertory::curl::requests | ||||
|  | ||||
| #endif // INCLUDE_COMM_CURL_CURL_REQUESTS_HTTP_POST_HPP_ | ||||
| @@ -0,0 +1,50 @@ | ||||
| /* | ||||
|   Copyright <2018-2024> <scott.e.graves@protonmail.com> | ||||
|  | ||||
|   Permission is hereby granted, free of charge, to any person obtaining a copy | ||||
|   of this software and associated documentation files (the "Software"), to deal | ||||
|   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_REQUESTS_HTTP_PUT_FILE_HPP_ | ||||
| #define INCLUDE_COMM_CURL_CURL_REQUESTS_HTTP_PUT_FILE_HPP_ | ||||
|  | ||||
| #include "comm/curl/requests/http_request_base.hpp" | ||||
| #include "utils/encrypting_reader.hpp" | ||||
|  | ||||
| namespace repertory::curl::requests { | ||||
| struct http_put_file final : http_request_base { | ||||
|   http_put_file() = default; | ||||
|   http_put_file(const http_put_file &) = default; | ||||
|   http_put_file(http_put_file &&) = default; | ||||
|  | ||||
|   auto operator=(const http_put_file &) -> http_put_file & = default; | ||||
|   auto operator=(http_put_file &&) -> http_put_file & = default; | ||||
|  | ||||
|   ~http_put_file() override = default; | ||||
|  | ||||
|   std::shared_ptr<utils::encryption::encrypting_reader> reader; | ||||
|   std::string source_path; | ||||
|  | ||||
|   [[nodiscard]] auto set_method(CURL *curl, stop_type &stop_requested) const | ||||
|       -> bool override; | ||||
|  | ||||
| private: | ||||
|   mutable std::shared_ptr<read_file_info> read_info{}; | ||||
| }; | ||||
| } // namespace repertory::curl::requests | ||||
|  | ||||
| #endif // INCLUDE_COMM_CURL_CURL_REQUESTS_HTTP_PUT_FILE_HPP_ | ||||
| @@ -0,0 +1,82 @@ | ||||
| /* | ||||
|   Copyright <2018-2024> <scott.e.graves@protonmail.com> | ||||
|  | ||||
|   Permission is hereby granted, free of charge, to any person obtaining a copy | ||||
|   of this software and associated documentation files (the "Software"), to deal | ||||
|   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_REQUESTS_HTTP_REQUEST_BASE_HPP_ | ||||
| #define INCLUDE_COMM_CURL_CURL_REQUESTS_HTTP_REQUEST_BASE_HPP_ | ||||
|  | ||||
| #include "types/repertory.hpp" | ||||
| #include "utils/native_file.hpp" | ||||
|  | ||||
| namespace repertory::curl::requests { | ||||
| using read_callback = size_t (*)(char *, size_t, size_t, void *); | ||||
|  | ||||
| using response_callback = | ||||
|     std::function<void(const data_buffer &data, long response_code)>; | ||||
|  | ||||
| struct read_file_info final { | ||||
|   stop_type &stop_requested; | ||||
|   native_file::native_file_ptr nf{}; | ||||
|   std::uint64_t offset{}; | ||||
| }; | ||||
|  | ||||
| inline const auto read_file_data = static_cast<read_callback>( | ||||
|     [](char *buffer, size_t size, size_t nitems, void *instream) -> size_t { | ||||
|       auto *read_info = reinterpret_cast<read_file_info *>(instream); | ||||
|       std::size_t bytes_read{}; | ||||
|       auto ret = read_info->nf->read_bytes(buffer, size * nitems, | ||||
|                                            read_info->offset, bytes_read); | ||||
|       if (ret) { | ||||
|         read_info->offset += bytes_read; | ||||
|       } | ||||
|       return ret && not read_info->stop_requested ? bytes_read | ||||
|                                                   : CURL_READFUNC_ABORT; | ||||
|     }); | ||||
|  | ||||
| struct http_request_base { | ||||
|   http_request_base() = default; | ||||
|   http_request_base(const http_request_base &) = default; | ||||
|   http_request_base(http_request_base &&) = default; | ||||
|  | ||||
|   auto operator=(const http_request_base &) -> http_request_base & = default; | ||||
|   auto operator=(http_request_base &&) -> http_request_base & = default; | ||||
|  | ||||
|   virtual ~http_request_base() = default; | ||||
|  | ||||
|   bool allow_timeout{}; | ||||
|   std::optional<std::string> aws_service; | ||||
|   std::optional<std::string> decryption_token{}; | ||||
|   http_headers headers{}; | ||||
|   std::string path{}; | ||||
|   query_parameters query{}; | ||||
|   std::optional<http_range> range{}; | ||||
|   std::optional<response_callback> response_handler; | ||||
|   std::optional<http_headers> response_headers; | ||||
|   std::optional<std::uint64_t> total_size{}; | ||||
|  | ||||
|   [[nodiscard]] virtual auto get_path() const -> std::string { return path; } | ||||
|  | ||||
|   [[nodiscard]] virtual auto set_method(CURL *curl, | ||||
|                                         stop_type &stop_requested) const | ||||
|       -> bool = 0; | ||||
| }; | ||||
| } // namespace repertory::curl::requests | ||||
|  | ||||
| #endif // INCLUDE_COMM_CURL_CURL_REQUESTS_HTTP_REQUEST_BASE_HPP_ | ||||
							
								
								
									
										65
									
								
								repertory/librepertory/include/comm/i_http_comm.hpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										65
									
								
								repertory/librepertory/include/comm/i_http_comm.hpp
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,65 @@ | ||||
| /* | ||||
|   Copyright <2018-2024> <scott.e.graves@protonmail.com> | ||||
|  | ||||
|   Permission is hereby granted, free of charge, to any person obtaining a copy | ||||
|   of this software and associated documentation files (the "Software"), to deal | ||||
|   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_HTTP_COMM_HPP_ | ||||
| #define INCLUDE_COMM_I_HTTP_COMM_HPP_ | ||||
|  | ||||
| #include "comm/curl/requests/http_delete.hpp" | ||||
| #include "comm/curl/requests/http_get.hpp" | ||||
| #include "comm/curl/requests/http_head.hpp" | ||||
| #include "comm/curl/requests/http_post.hpp" | ||||
| #include "comm/curl/requests/http_put_file.hpp" | ||||
| #include "types/repertory.hpp" | ||||
|  | ||||
| namespace repertory { | ||||
| struct i_http_comm { | ||||
|   INTERFACE_SETUP(i_http_comm); | ||||
|  | ||||
| public: | ||||
|   virtual void enable_s3_path_style(bool enable) = 0; | ||||
|  | ||||
|   [[nodiscard]] virtual auto | ||||
|   make_request(const curl::requests::http_delete &del, long &response_code, | ||||
|                stop_type &stop_requested) const -> bool = 0; | ||||
|  | ||||
|   [[nodiscard]] virtual auto make_request(const curl::requests::http_get &get, | ||||
|                                           long &response_code, | ||||
|                                           stop_type &stop_requested) const | ||||
|       -> bool = 0; | ||||
|  | ||||
|   [[nodiscard]] virtual auto make_request(const curl::requests::http_head &head, | ||||
|                                           long &response_code, | ||||
|                                           stop_type &stop_requested) const | ||||
|       -> bool = 0; | ||||
|  | ||||
|   [[nodiscard]] virtual auto make_request(const curl::requests::http_post &post, | ||||
|                                           long &response_code, | ||||
|                                           stop_type &stop_requested) const | ||||
|       -> bool = 0; | ||||
|  | ||||
|   [[nodiscard]] virtual auto | ||||
|   make_request(const curl::requests::http_put_file &put_file, | ||||
|                long &response_code, stop_type &stop_requested) const | ||||
|       -> bool = 0; | ||||
| }; | ||||
| } // namespace repertory | ||||
|  | ||||
| #endif // INCLUDE_COMM_I_HTTP_COMM_HPP_ | ||||
							
								
								
									
										110
									
								
								repertory/librepertory/include/comm/packet/client_pool.hpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										110
									
								
								repertory/librepertory/include/comm/packet/client_pool.hpp
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,110 @@ | ||||
| /* | ||||
|   Copyright <2018-2024> <scott.e.graves@protonmail.com> | ||||
|  | ||||
|   Permission is hereby granted, free of charge, to any person obtaining a copy | ||||
|   of this software and associated documentation files (the "Software"), to deal | ||||
|   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 "comm/packet/packet.hpp" | ||||
| #include "types/repertory.hpp" | ||||
|  | ||||
| namespace repertory { | ||||
| class client_pool final { | ||||
| public: | ||||
|   using worker_callback = std::function<packet::error_type()>; | ||||
|   using worker_complete_callback = | ||||
|       std::function<void(const packet::error_type &)>; | ||||
|  | ||||
| private: | ||||
|   class pool final { | ||||
|   private: | ||||
|     struct work_item final { | ||||
|       work_item(worker_callback worker, | ||||
|                 worker_complete_callback worker_complete) | ||||
|           : work(std::move(worker)), | ||||
|             work_complete(std::move(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(std::uint8_t pool_size); | ||||
|  | ||||
|     ~pool() { shutdown(); } | ||||
|  | ||||
|   public: | ||||
|     pool(const pool &) = delete; | ||||
|     pool(pool &&) = delete; | ||||
|     auto operator=(const pool &) -> pool & = delete; | ||||
|     auto operator=(pool &&) -> pool & = delete; | ||||
|  | ||||
|   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(std::uint64_t thread_id, const worker_callback &worker, | ||||
|                  const worker_complete_callback &worker_complete); | ||||
|  | ||||
|     void shutdown(); | ||||
|   }; | ||||
|  | ||||
| public: | ||||
|   explicit client_pool(std::uint8_t pool_size = min_pool_size) | ||||
|       : pool_size_(pool_size == 0U ? min_pool_size : pool_size) {} | ||||
|  | ||||
|   ~client_pool() { shutdown(); } | ||||
|  | ||||
| public: | ||||
|   client_pool(const client_pool &) = delete; | ||||
|   client_pool(client_pool &&) = delete; | ||||
|   auto operator=(const client_pool &) -> client_pool & = delete; | ||||
|   auto operator=(client_pool &&) -> client_pool & = delete; | ||||
|  | ||||
| private: | ||||
|   std::uint8_t pool_size_; | ||||
|   std::unordered_map<std::string, std::shared_ptr<pool>> pool_lookup_; | ||||
|   std::mutex pool_mutex_; | ||||
|   bool shutdown_ = false; | ||||
|  | ||||
| private: | ||||
|   static constexpr const auto min_pool_size = 10U; | ||||
|  | ||||
| public: | ||||
|   void execute(const std::string &client_id, 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_ | ||||
							
								
								
									
										232
									
								
								repertory/librepertory/include/comm/packet/packet.hpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										232
									
								
								repertory/librepertory/include/comm/packet/packet.hpp
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,232 @@ | ||||
| /* | ||||
|   Copyright <2018-2024> <scott.e.graves@protonmail.com> | ||||
|  | ||||
|   Permission is hereby granted, free of charge, to any person obtaining a copy | ||||
|   of this software and associated documentation files (the "Software"), to deal | ||||
|   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 "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: | ||||
|   using error_type = std::int32_t; | ||||
|  | ||||
| public: | ||||
|   packet() = default; | ||||
|  | ||||
|   explicit packet(data_buffer buffer) : buffer_(std::move(buffer)) {} | ||||
|  | ||||
|   explicit packet(data_buffer &&buffer) : buffer_(std::move(buffer)) {} | ||||
|  | ||||
|   packet(const packet &pkt) noexcept = default; | ||||
|  | ||||
|   packet(packet &&pkt) noexcept | ||||
|       : buffer_(std::move(pkt.buffer_)), decode_offset_(pkt.decode_offset_) {} | ||||
|  | ||||
|   ~packet() = default; | ||||
|  | ||||
| private: | ||||
|   data_buffer buffer_; | ||||
|   std::size_t decode_offset_ = 0U; | ||||
|  | ||||
| public: | ||||
|   [[nodiscard]] static auto decode_json(packet &response, json &json_data) | ||||
|       -> int; | ||||
|  | ||||
| public: | ||||
|   void clear(); | ||||
|  | ||||
|   [[nodiscard]] auto current_pointer() -> char * { | ||||
|     return (decode_offset_ < buffer_.size()) ? &buffer_[decode_offset_] | ||||
|                                              : nullptr; | ||||
|   } | ||||
|  | ||||
|   [[nodiscard]] auto current_pointer() const -> const char * { | ||||
|     return (decode_offset_ < buffer_.size()) ? &buffer_[decode_offset_] | ||||
|                                              : nullptr; | ||||
|   } | ||||
|  | ||||
|   [[nodiscard]] auto decode(std::string &data) -> error_type; | ||||
|  | ||||
|   [[nodiscard]] auto decode(std::wstring &data) -> error_type; | ||||
|  | ||||
|   [[nodiscard]] auto decode(void *buffer, std::size_t size) -> error_type; | ||||
|  | ||||
|   [[nodiscard]] auto decode(void *&ptr) -> error_type; | ||||
|  | ||||
|   [[nodiscard]] auto decode(std::int8_t &val) -> error_type; | ||||
|  | ||||
|   [[nodiscard]] auto decode(std::uint8_t &val) -> error_type; | ||||
|  | ||||
|   [[nodiscard]] auto decode(std::int16_t &val) -> error_type; | ||||
|  | ||||
|   [[nodiscard]] auto decode(std::uint16_t &val) -> error_type; | ||||
|  | ||||
|   [[nodiscard]] auto decode(std::int32_t &val) -> error_type; | ||||
|  | ||||
|   [[nodiscard]] auto decode(std::uint32_t &val) -> error_type; | ||||
|  | ||||
|   [[nodiscard]] auto decode(std::int64_t &val) -> error_type; | ||||
|  | ||||
|   [[nodiscard]] auto decode(std::uint64_t &val) -> error_type; | ||||
|  | ||||
|   [[nodiscard]] auto decode(remote::open_flags &val) -> error_type { | ||||
|     return decode(reinterpret_cast<std::uint32_t &>(val)); | ||||
|   } | ||||
|  | ||||
|   [[nodiscard]] auto decode(remote::setattr_x &val) -> error_type; | ||||
|  | ||||
|   [[nodiscard]] auto decode(remote::stat &val) -> error_type; | ||||
|  | ||||
|   [[nodiscard]] auto decode(remote::statfs &val) -> error_type; | ||||
|  | ||||
|   [[nodiscard]] auto decode(remote::statfs_x &val) -> error_type; | ||||
|  | ||||
|   [[nodiscard]] auto decode(remote::file_info &val) -> error_type; | ||||
|  | ||||
|   [[nodiscard]] auto decrypt(const std::string &token) -> error_type; | ||||
|  | ||||
|   void encode(const void *buffer, std::size_t size, bool should_reserve = true); | ||||
|  | ||||
|   void encode(const char *str) { | ||||
|     encode(std::string(str == nullptr ? "" : str)); | ||||
|   } | ||||
|  | ||||
|   void encode(const std::string &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 val); | ||||
|  | ||||
|   void encode(std::uint8_t val); | ||||
|  | ||||
|   void encode(std::int16_t val); | ||||
|  | ||||
|   void encode(std::uint16_t val); | ||||
|  | ||||
|   void encode(std::int32_t val); | ||||
|  | ||||
|   void encode(std::uint32_t val); | ||||
|  | ||||
|   void encode(std::int64_t val); | ||||
|  | ||||
|   void encode(std::uint64_t val); | ||||
|  | ||||
|   void encode(remote::open_flags val) { | ||||
|     encode(static_cast<std::uint32_t>(val)); | ||||
|   } | ||||
|  | ||||
|   void encode(remote::setattr_x val); | ||||
|  | ||||
|   void encode(remote::stat val); | ||||
|  | ||||
|   void encode(remote::statfs val, bool should_reserve = true); | ||||
|  | ||||
|   void encode(remote::statfs_x val); | ||||
|  | ||||
|   void encode(remote::file_info val); | ||||
|  | ||||
|   void encode_top(const void *buffer, 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 val); | ||||
|  | ||||
|   void encode_top(std::uint8_t val); | ||||
|  | ||||
|   void encode_top(std::int16_t val); | ||||
|  | ||||
|   void encode_top(std::uint16_t val); | ||||
|  | ||||
|   void encode_top(std::int32_t val); | ||||
|  | ||||
|   void encode_top(std::uint32_t val); | ||||
|  | ||||
|   void encode_top(std::int64_t val); | ||||
|  | ||||
|   void encode_top(std::uint64_t val); | ||||
|  | ||||
|   void encode_top(remote::open_flags val) { | ||||
|     encode_top(static_cast<std::uint32_t>(val)); | ||||
|   } | ||||
|  | ||||
|   void encode_top(remote::setattr_x val); | ||||
|  | ||||
|   void encode_top(remote::stat val); | ||||
|  | ||||
|   void encode_top(remote::statfs val, bool should_reserve = true); | ||||
|  | ||||
|   void encode_top(remote::statfs_x val); | ||||
|  | ||||
|   void encode_top(remote::file_info val); | ||||
|  | ||||
|   void encrypt(const std::string &token); | ||||
|  | ||||
|   [[nodiscard]] auto get_size() const -> std::uint32_t { | ||||
|     return static_cast<std::uint32_t>(buffer_.size()); | ||||
|   } | ||||
|  | ||||
|   void transfer_into(data_buffer &buffer); | ||||
|  | ||||
| public: | ||||
|   auto operator=(const data_buffer &buffer) noexcept -> packet &; | ||||
|  | ||||
|   auto operator=(data_buffer &&buffer) noexcept -> packet &; | ||||
|  | ||||
|   auto operator=(const packet &pkt) noexcept -> packet &; | ||||
|  | ||||
|   auto operator=(packet &&pkt) noexcept -> packet &; | ||||
|  | ||||
|   [[nodiscard]] auto operator[](std::size_t index) -> char & { | ||||
|     return buffer_[index]; | ||||
|   } | ||||
|  | ||||
|   [[nodiscard]] auto operator[](std::size_t index) const -> const char & { | ||||
|     return buffer_.at(index); | ||||
|   } | ||||
| }; | ||||
|  | ||||
| using packet = packet; | ||||
| } // namespace repertory | ||||
|  | ||||
| #endif // INCLUDE_COMM_PACKET_PACKET_HPP_ | ||||
							
								
								
									
										96
									
								
								repertory/librepertory/include/comm/packet/packet_client.hpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										96
									
								
								repertory/librepertory/include/comm/packet/packet_client.hpp
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,96 @@ | ||||
| /* | ||||
|   Copyright <2018-2024> <scott.e.graves@protonmail.com> | ||||
|  | ||||
|   Permission is hereby granted, free of charge, to any person obtaining a copy | ||||
|   of this software and associated documentation files (the "Software"), to deal | ||||
|   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 "comm/packet/packet.hpp" | ||||
|  | ||||
| using boost::asio::ip::tcp; | ||||
|  | ||||
| namespace repertory { | ||||
| class packet_client final { | ||||
| private: | ||||
|   struct client final { | ||||
|     explicit client(boost::asio::io_context &ctx) : socket(ctx) {} | ||||
|     std::string nonce; | ||||
|     tcp::socket socket; | ||||
|   }; | ||||
|  | ||||
| public: | ||||
|   packet_client(std::string host_name_or_ip, std::uint8_t max_connections, | ||||
|                 std::uint16_t port, std::uint16_t receive_timeout, | ||||
|                 std::uint16_t send_timeout, std::string encryption_token); | ||||
|  | ||||
|   ~packet_client(); | ||||
|  | ||||
|   packet_client(const packet_client &) = delete; | ||||
|   packet_client(packet_client &&) = delete; | ||||
|   auto operator=(const packet_client &) -> packet_client & = delete; | ||||
|   auto operator=(packet_client &&) -> packet_client & = delete; | ||||
|  | ||||
| private: | ||||
|   boost::asio::io_context io_context_; | ||||
|   std::string host_name_or_ip_; | ||||
|   std::uint8_t max_connections_; | ||||
|   std::uint16_t port_; | ||||
|   std::uint16_t receive_timeout_; | ||||
|   std::uint16_t send_timeout_; | ||||
|   std::string encryption_token_; | ||||
|   std::string unique_id_; | ||||
|  | ||||
| private: | ||||
|   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: | ||||
|   static void close(client &cli); | ||||
|  | ||||
|   void close_all(); | ||||
|  | ||||
|   void connect(client &cli); | ||||
|  | ||||
|   [[nodiscard]] auto get_client() -> std::shared_ptr<client>; | ||||
|  | ||||
|   void put_client(std::shared_ptr<client> &cli); | ||||
|  | ||||
|   [[nodiscard]] auto read_packet(client &cli, packet &response) | ||||
|       -> packet::error_type; | ||||
|  | ||||
|   void resolve(); | ||||
|  | ||||
| public: | ||||
|   [[nodiscard]] auto send(const std::string &method, | ||||
|                           std::uint32_t &service_flags) -> packet::error_type; | ||||
|  | ||||
|   [[nodiscard]] auto send(const std::string &method, packet &request, | ||||
|                           std::uint32_t &service_flags) -> packet::error_type; | ||||
|  | ||||
|   [[nodiscard]] auto send(const std::string &method, packet &request, | ||||
|                           packet &response, std::uint32_t &service_flags) | ||||
|       -> packet::error_type; | ||||
| }; | ||||
| } // namespace repertory | ||||
|  | ||||
| #endif // INCLUDE_COMM_PACKET_PACKET_CLIENT_HPP_ | ||||
							
								
								
									
										99
									
								
								repertory/librepertory/include/comm/packet/packet_server.hpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										99
									
								
								repertory/librepertory/include/comm/packet/packet_server.hpp
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,99 @@ | ||||
| /* | ||||
|   Copyright <2018-2024> <scott.e.graves@protonmail.com> | ||||
|  | ||||
|   Permission is hereby granted, free of charge, to any person obtaining a copy | ||||
|   of this software and associated documentation files (the "Software"), to deal | ||||
|   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 "comm/packet/client_pool.hpp" | ||||
| #include "types/repertory.hpp" | ||||
| #include "utils/utils.hpp" | ||||
|  | ||||
| using namespace boost::asio; | ||||
| using boost::asio::ip::tcp; | ||||
|  | ||||
| namespace repertory { | ||||
| class packet_server final { | ||||
| public: | ||||
|   using closed_callback = std::function<void(const std::string &)>; | ||||
|   using message_complete_callback = client_pool::worker_complete_callback; | ||||
|   using message_handler_callback = std::function<void( | ||||
|       std::uint32_t, const std::string &, std::uint64_t, const std::string &, | ||||
|       packet *, packet &, message_complete_callback)>; | ||||
|  | ||||
| public: | ||||
|   packet_server(std::uint16_t port, std::string token, std::uint8_t pool_size, | ||||
|                 closed_callback closed, | ||||
|                 message_handler_callback message_handler); | ||||
|  | ||||
|   ~packet_server(); | ||||
|  | ||||
| public: | ||||
|   packet_server(const packet_server &) = delete; | ||||
|   packet_server(packet_server &&) = delete; | ||||
|   auto operator=(const packet_server &) -> packet_server & = delete; | ||||
|   auto operator=(packet_server &&) -> packet_server & = delete; | ||||
|  | ||||
| private: | ||||
|   struct connection { | ||||
|     connection(boost::asio::io_service &io_service, tcp::acceptor &acceptor_) | ||||
|         : socket(io_service), acceptor(acceptor_) {} | ||||
|  | ||||
|     tcp::socket socket; | ||||
|     tcp::acceptor &acceptor; | ||||
|     data_buffer buffer; | ||||
|     std::string client_id; | ||||
|     std::string nonce; | ||||
|  | ||||
|     void generate_nonce() { nonce = utils::generate_random_string(256U); } | ||||
|   }; | ||||
|  | ||||
| private: | ||||
|   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 &conn, 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> conn, | ||||
|                  boost::system::error_code err); | ||||
|  | ||||
|   void read_header(std::shared_ptr<connection> conn); | ||||
|  | ||||
|   void read_packet(std::shared_ptr<connection> conn, std::uint32_t data_size); | ||||
|  | ||||
|   void remove_client(connection &conn); | ||||
|  | ||||
|   void send_response(std::shared_ptr<connection> conn, | ||||
|                      const packet::error_type &result, packet &response); | ||||
| }; | ||||
| } // namespace repertory | ||||
|  | ||||
| #endif // INCLUDE_COMM_PACKET_PACKET_SERVER_HPP_ | ||||
							
								
								
									
										432
									
								
								repertory/librepertory/include/common.hpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										432
									
								
								repertory/librepertory/include/common.hpp
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,432 @@ | ||||
| /* | ||||
|   Copyright <2018-2024> <scott.e.graves@protonmail.com> | ||||
|  | ||||
|   Permission is hereby granted, free of charge, to any person obtaining a copy | ||||
|   of this software and associated documentation files (the "Software"), to deal | ||||
|   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_ | ||||
|  | ||||
| #if defined(__GNUC__) | ||||
| // clang-format off | ||||
| #define REPERTORY_IGNORE_WARNINGS_ENABLE()                                     \ | ||||
|   _Pragma("GCC diagnostic push")                                               \ | ||||
|   _Pragma("GCC diagnostic ignored \"-Waggressive-loop-optimizations\"")        \ | ||||
|   _Pragma("GCC diagnostic ignored \"-Wconversion\"")                           \ | ||||
|   _Pragma("GCC diagnostic ignored \"-Wdouble-promotion\"")                     \ | ||||
|   _Pragma("GCC diagnostic ignored \"-Wduplicated-branches\"")                  \ | ||||
|   _Pragma("GCC diagnostic ignored \"-Wfloat-conversion\"")                     \ | ||||
|   _Pragma("GCC diagnostic ignored \"-Wimplicit-fallthrough\"")                 \ | ||||
|   _Pragma("GCC diagnostic ignored \"-Wnull-dereference\"")                     \ | ||||
|   _Pragma("GCC diagnostic ignored \"-Wsign-conversion\"")                      \ | ||||
|   _Pragma("GCC diagnostic ignored \"-Wunused-but-set-variable\"")              \ | ||||
|   _Pragma("GCC diagnostic ignored \"-Wunused-parameter\"")                     \ | ||||
|   _Pragma("GCC diagnostic ignored \"-Wuseless-cast\"") | ||||
|  | ||||
| #define REPERTORY_IGNORE_WARNINGS_DISABLE()                                    \ | ||||
|   _Pragma("GCC diagnostic pop") | ||||
| #else | ||||
| #define REPERTORY_IGNORE_WARNINGS_ENABLE()  | ||||
| #define REPERTORY_IGNORE_WARNINGS_DISABLE()                                     | ||||
| #endif // defined(__GNUC__) | ||||
| // clang-format on | ||||
|  | ||||
| #ifdef __cplusplus | ||||
| REPERTORY_IGNORE_WARNINGS_ENABLE() | ||||
|  | ||||
| #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> | ||||
| #include <time.h> | ||||
| #else | ||||
| #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 | ||||
| #endif | ||||
|  | ||||
| #include <algorithm> | ||||
| #include <atomic> | ||||
| #include <chrono> | ||||
| #include <codecvt> | ||||
| #include <condition_variable> | ||||
| #include <deque> | ||||
| #include <filesystem> | ||||
| #include <fstream> | ||||
| #include <future> | ||||
| #include <iomanip> | ||||
| #include <iostream> | ||||
| #include <limits> | ||||
| #include <mutex> | ||||
| #include <optional> | ||||
| #include <random> | ||||
| #include <sstream> | ||||
| #include <string> | ||||
| #include <string_view> | ||||
| #include <thread> | ||||
| #include <type_traits> | ||||
| #include <unordered_map> | ||||
| #include <vector> | ||||
|  | ||||
| #include "sodium.h" | ||||
| template <typename data_type> | ||||
| [[nodiscard]] inline auto repertory_rand() -> data_type { | ||||
|   data_type ret{}; | ||||
|   randombytes_buf(&ret, sizeof(ret)); | ||||
|   return ret; | ||||
| } | ||||
|  | ||||
| #include "boost/archive/text_iarchive.hpp" | ||||
| #include "boost/archive/text_oarchive.hpp" | ||||
| #include "boost/asio.hpp" | ||||
| #include "boost/asio/io_context.hpp" | ||||
| #include "boost/bind/bind.hpp" | ||||
| #include "boost/dynamic_bitset.hpp" | ||||
| #include "boost/dynamic_bitset/serialization.hpp" | ||||
| #include "boost/endian/conversion.hpp" | ||||
| #include "boost/serialization/vector.hpp" | ||||
| #include "curl/curl.h" | ||||
| #include "curl/multi.h" | ||||
| #include "json.hpp" | ||||
| #include "sqlite3.h" | ||||
| #include "uuid.h" | ||||
|  | ||||
| #ifdef _WIN32 | ||||
| #include <sddl.h> | ||||
| #include "winfsp/winfsp.hpp" | ||||
| #else | ||||
| #if FUSE_USE_VERSION >= 30 | ||||
| #include <fuse.h> | ||||
| #include <fuse_lowlevel.h> | ||||
| #else | ||||
| #include <fuse/fuse.h> | ||||
| #endif | ||||
| #endif | ||||
|  | ||||
| #include "pugixml.hpp" | ||||
|  | ||||
| #include "httplib.h" | ||||
|  | ||||
| REPERTORY_IGNORE_WARNINGS_DISABLE() | ||||
|  | ||||
| using namespace std::chrono_literals; | ||||
| using json = nlohmann::json; | ||||
|  | ||||
| #define REPERTORY "repertory" | ||||
| #define REPERTORY_CONFIG_VERSION 0ull | ||||
| #define REPERTORY_DATA_NAME "repertory" | ||||
| #define REPERTORY_MIN_REMOTE_VERSION "2.0.0" | ||||
| #define REPERTORY_W L"repertory" | ||||
|  | ||||
| #ifdef _WIN32 | ||||
| #define REPERTORY_INVALID_HANDLE INVALID_HANDLE_VALUE | ||||
| #define REPERTORY_API_INVALID_HANDLE static_cast<std::uint64_t>(-1) | ||||
| using native_handle = HANDLE; | ||||
| #else | ||||
| #define REPERTORY_INVALID_HANDLE (-1) | ||||
| #define REPERTORY_API_INVALID_HANDLE REPERTORY_INVALID_HANDLE | ||||
| using native_handle = int; | ||||
| #endif | ||||
|  | ||||
| constexpr const auto NANOS_PER_SECOND = 1000000000L; | ||||
|  | ||||
| #ifdef _WIN32 | ||||
| #ifdef CreateDirectory | ||||
| #undef CreateDirectory | ||||
| #endif | ||||
|  | ||||
| #ifdef CreateFile | ||||
| #undef CreateFile | ||||
| #endif | ||||
|  | ||||
| #ifdef DeleteFile | ||||
| #undef DeleteFile | ||||
| #endif | ||||
|  | ||||
| #ifdef RemoveDirectory | ||||
| #undef RemoveDirectory | ||||
| #endif | ||||
|  | ||||
| #ifndef _SH_DENYRW | ||||
| #define _SH_DENYRW 0x10 // deny read/write mode | ||||
| #endif | ||||
|  | ||||
| #ifndef _SH_DENYWR | ||||
| #define _SH_DENYWR 0x20 // deny write mode | ||||
| #endif | ||||
|  | ||||
| #ifndef _SH_DENYRD | ||||
| #define _SH_DENYRD 0x30 // deny read mode | ||||
| #endif | ||||
|  | ||||
| #ifndef _SH_DENYNO | ||||
| #define _SH_DENYNO 0x40 // deny none mode | ||||
| #endif | ||||
|  | ||||
| #ifndef _SH_SECURE | ||||
| #define _SH_SECURE 0x80 // secure mode | ||||
| #endif | ||||
| #endif | ||||
|  | ||||
| #ifndef ENETDOWN | ||||
| #define ENETDOWN 100 | ||||
| #endif | ||||
|  | ||||
| #ifndef SETATTR_WANTS_MODE | ||||
| #define SETATTR_WANTS_MODE(attr) ((attr)->valid & (1 << 0)) | ||||
| #endif // SETATTR_WANTS_MODE | ||||
|  | ||||
| #ifndef SETATTR_WANTS_UID | ||||
| #define SETATTR_WANTS_UID(attr) ((attr)->valid & (1 << 1)) | ||||
| #endif // SETATTR_WANTS_UID | ||||
|  | ||||
| #ifndef SETATTR_WANTS_GID | ||||
| #define SETATTR_WANTS_GID(attr) ((attr)->valid & (1 << 2)) | ||||
| #endif // SETATTR_WANTS_GID | ||||
|  | ||||
| #ifndef SETATTR_WANTS_SIZE | ||||
| #define SETATTR_WANTS_SIZE(attr) ((attr)->valid & (1 << 3)) | ||||
| #endif // SETATTR_WANTS_SIZE | ||||
|  | ||||
| #ifndef SETATTR_WANTS_ACCTIME | ||||
| #define SETATTR_WANTS_ACCTIME(attr) ((attr)->valid & (1 << 4)) | ||||
| #endif // SETATTR_WANTS_ACCTIME | ||||
|  | ||||
| #ifndef SETATTR_WANTS_MODTIME | ||||
| #define SETATTR_WANTS_MODTIME(attr) ((attr)->valid & (1 << 5)) | ||||
| #endif // SETATTR_WANTS_MODTIME | ||||
|  | ||||
| #ifndef SETATTR_WANTS_CRTIME | ||||
| #define SETATTR_WANTS_CRTIME(attr) ((attr)->valid & (1 << 28)) | ||||
| #endif // SETATTR_WANTS_CRTIME | ||||
|  | ||||
| #ifndef SETATTR_WANTS_CHGTIME | ||||
| #define SETATTR_WANTS_CHGTIME(attr) ((attr)->valid & (1 << 29)) | ||||
| #endif // SETATTR_WANTS_CHGTIME | ||||
|  | ||||
| #ifndef SETATTR_WANTS_BKUPTIME | ||||
| #define SETATTR_WANTS_BKUPTIME(attr) ((attr)->valid & (1 << 30)) | ||||
| #endif // SETATTR_WANTS_BKUPTIME | ||||
|  | ||||
| #ifndef SETATTR_WANTS_FLAGS | ||||
| #define SETATTR_WANTS_FLAGS(attr) ((attr)->valid & (1 << 31)) | ||||
| #endif // SETATTR_WANTS_FLAGS | ||||
|  | ||||
| #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 | ||||
|  | ||||
| #ifndef fstat64 | ||||
| #define fstat64 fstat | ||||
| #endif | ||||
|  | ||||
| #ifndef pread64 | ||||
| #define pread64 pread | ||||
| #endif | ||||
|  | ||||
| #ifndef pwrite64 | ||||
| #define pwrite64 pwrite | ||||
| #endif | ||||
|  | ||||
| #ifndef stat64 | ||||
| #define stat64 stat | ||||
| #endif | ||||
|  | ||||
| #ifndef statfs64 | ||||
| #define statfs64 statfs | ||||
| #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 | ||||
| using BOOLEAN = std::uint8_t; | ||||
| using DWORD = std::uint32_t; | ||||
| using HANDLE = void *; | ||||
| using PUINT32 = std::uint32_t *; | ||||
| using PVOID = void *; | ||||
| using PWSTR = wchar_t *; | ||||
| using SIZE_T = std::uint64_t; | ||||
| using UINT16 = std::uint16_t; | ||||
| using UINT32 = std::uint32_t; | ||||
| using UINT64 = std::uint64_t; | ||||
| using VOID = void; | ||||
| using WCHAR = wchar_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{}; | ||||
| }; | ||||
|  | ||||
| using FileInfo = FSP_FSCTL_FILE_INFO; | ||||
| } // namespace Fsp::FileSystemBase | ||||
| #endif | ||||
|  | ||||
| using namespace Fsp; | ||||
|  | ||||
| namespace repertory { | ||||
| auto get_repertory_git_revision() -> const std::string &; | ||||
| auto get_repertory_version() -> const std::string &; | ||||
| } // namespace repertory | ||||
|  | ||||
| namespace { | ||||
| template <class... Ts> struct overloaded : Ts... { | ||||
|   using Ts::operator()...; | ||||
| }; | ||||
| template <class... Ts> overloaded(Ts...) -> overloaded<Ts...>; | ||||
| } // namespace | ||||
|  | ||||
| #define INTERFACE_SETUP(name)                                                  \ | ||||
| public:                                                                        \ | ||||
|   name(const name &) noexcept = delete;                                        \ | ||||
|   name &operator=(const name &) noexcept = delete;                             \ | ||||
|   name &operator=(name &&) noexcept = delete;                                  \ | ||||
|                                                                                \ | ||||
| protected:                                                                     \ | ||||
|   name() = default;                                                            \ | ||||
|   name(name &&) noexcept = default;                                            \ | ||||
|                                                                                \ | ||||
| public:                                                                        \ | ||||
|   virtual ~name() = default | ||||
|  | ||||
| #endif // __cplusplus | ||||
| #endif // INCLUDE_COMMON_HPP_ | ||||
							
								
								
									
										247
									
								
								repertory/librepertory/include/database/db_common.hpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										247
									
								
								repertory/librepertory/include/database/db_common.hpp
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,247 @@ | ||||
| /* | ||||
|   Copyright <2018-2024> <scott.e.graves@protonmail.com> | ||||
|  | ||||
|   Permission is hereby granted, free of charge, to any person obtaining a copy | ||||
|   of this software and associated documentation files (the "Software"), to deal | ||||
|   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_DATABASE_DB_COMMON_HPP_ | ||||
| #define INCLUDE_DATABASE_DB_COMMON_HPP_ | ||||
|  | ||||
| #include "utils/error_utils.hpp" | ||||
|  | ||||
| namespace repertory::db { | ||||
| using db_types_t = std::variant<std::int64_t, std::string>; | ||||
|  | ||||
| struct sqlite3_deleter { | ||||
|   void operator()(sqlite3 *db3) { | ||||
|     if (db3 != nullptr) { | ||||
|       sqlite3_close_v2(db3); | ||||
|     } | ||||
|   } | ||||
| }; | ||||
|  | ||||
| using db3_t = std::unique_ptr<sqlite3, sqlite3_deleter>; | ||||
|  | ||||
| struct sqlite3_statement_deleter { | ||||
|   void operator()(sqlite3_stmt *stmt) { | ||||
|     if (stmt != nullptr) { | ||||
|       sqlite3_finalize(stmt); | ||||
|     } | ||||
|   } | ||||
| }; | ||||
|  | ||||
| using db3_stmt_t = std::unique_ptr<sqlite3_stmt, sqlite3_statement_deleter>; | ||||
|  | ||||
| struct comp_data_t final { | ||||
|   std::string column_name; | ||||
|   std::string op_type; | ||||
|   db_types_t value; | ||||
| }; | ||||
|  | ||||
| class db_column final { | ||||
| public: | ||||
|   db_column() noexcept = default; | ||||
|   db_column(const db_column &) = default; | ||||
|   db_column(db_column &&column) noexcept = default; | ||||
|   ~db_column() = default; | ||||
|  | ||||
|   auto operator=(const db_column &) -> db_column & = default; | ||||
|   auto operator=(db_column &&) -> db_column & = default; | ||||
|  | ||||
|   db_column(std::int32_t index, std::string name, db_types_t value) noexcept | ||||
|       : index_(index), name_(std::move(name)), value_(std::move(value)) {} | ||||
|  | ||||
| private: | ||||
|   std::int32_t index_{}; | ||||
|   std::string name_; | ||||
|   db_types_t value_; | ||||
|  | ||||
| public: | ||||
|   [[nodiscard]] auto get_index() const -> std::int32_t { return index_; } | ||||
|  | ||||
|   [[nodiscard]] auto get_name() const -> std::string { return name_; } | ||||
|  | ||||
|   template <typename data_type> | ||||
|   [[nodiscard]] auto get_value() const -> data_type { | ||||
|     return std::visit( | ||||
|         overloaded{ | ||||
|             [](const data_type &value) -> data_type { return value; }, | ||||
|             [](auto &&) -> data_type { | ||||
|               throw std::runtime_error("data type not supported"); | ||||
|             }, | ||||
|         }, | ||||
|         value_); | ||||
|   } | ||||
|  | ||||
|   [[nodiscard]] auto get_value_as_json() const -> nlohmann::json { | ||||
|     return std::visit( | ||||
|         overloaded{ | ||||
|             [this](std::int64_t value) -> auto { | ||||
|               return nlohmann::json({{name_, value}}); | ||||
|             }, | ||||
|             [](auto &&value) -> auto { return nlohmann::json::parse(value); }, | ||||
|         }, | ||||
|         value_); | ||||
|   } | ||||
| }; | ||||
|  | ||||
| template <typename context_t> class db_row final { | ||||
| public: | ||||
|   db_row(std::shared_ptr<context_t> context) { | ||||
|     auto column_count = sqlite3_column_count(context->stmt.get()); | ||||
|     for (std::int32_t col = 0; col < column_count; col++) { | ||||
|       std::string name{sqlite3_column_name(context->stmt.get(), col)}; | ||||
|       auto column_type = sqlite3_column_type(context->stmt.get(), col); | ||||
|  | ||||
|       db_types_t value; | ||||
|       switch (column_type) { | ||||
|       case SQLITE_INTEGER: { | ||||
|         value = sqlite3_column_int64(context->stmt.get(), col); | ||||
|       } break; | ||||
|  | ||||
|       case SQLITE_TEXT: { | ||||
|         const auto *text = reinterpret_cast<const char *>( | ||||
|             sqlite3_column_text(context->stmt.get(), col)); | ||||
|         value = std::string(text == nullptr ? "" : text); | ||||
|       } break; | ||||
|  | ||||
|       default: | ||||
|         throw std::runtime_error("column type not implemented|" + name + '|' + | ||||
|                                  std::to_string(column_type)); | ||||
|       } | ||||
|  | ||||
|       columns_[name] = db_column{col, name, value}; | ||||
|     } | ||||
|   } | ||||
|  | ||||
| private: | ||||
|   std::map<std::string, db_column> columns_; | ||||
|  | ||||
| public: | ||||
|   [[nodiscard]] auto get_columns() const -> std::vector<db_column> { | ||||
|     std::vector<db_column> ret; | ||||
|     for (const auto &item : columns_) { | ||||
|       ret.push_back(item.second); | ||||
|     } | ||||
|     return ret; | ||||
|   } | ||||
|  | ||||
|   [[nodiscard]] auto get_column(std::int32_t index) const -> db_column { | ||||
|     auto iter = std::find_if(columns_.begin(), columns_.end(), | ||||
|                              [&index](auto &&col) -> bool { | ||||
|                                return col.second.get_index() == index; | ||||
|                              }); | ||||
|     if (iter == columns_.end()) { | ||||
|       throw std::out_of_range(""); | ||||
|     } | ||||
|  | ||||
|     return iter->second; | ||||
|   } | ||||
|  | ||||
|   [[nodiscard]] auto get_column(std::string name) const -> db_column { | ||||
|     return columns_.at(name); | ||||
|   } | ||||
| }; | ||||
|  | ||||
| template <typename context_t> struct db_result final { | ||||
|   db_result(std::shared_ptr<context_t> context, std::int32_t res) | ||||
|       : context_(std::move(context)), res_(res) { | ||||
|     constexpr const auto *function_name = | ||||
|         static_cast<const char *>(__FUNCTION__); | ||||
|  | ||||
|     if (res == SQLITE_OK) { | ||||
|       set_res(sqlite3_step(context_->stmt.get()), function_name); | ||||
|     } | ||||
|   } | ||||
|  | ||||
| private: | ||||
|   std::shared_ptr<context_t> context_; | ||||
|   mutable std::int32_t res_; | ||||
|  | ||||
| private: | ||||
|   void set_res(std::int32_t res, std::string function) const { | ||||
|     if (res != SQLITE_OK && res != SQLITE_DONE && res != SQLITE_ROW) { | ||||
|       utils::error::raise_error(function, "failed to step|" + | ||||
|                                               std::to_string(res) + '|' + | ||||
|                                               sqlite3_errstr(res)); | ||||
|     } | ||||
|     res_ = res; | ||||
|   } | ||||
|  | ||||
| public: | ||||
|   [[nodiscard]] auto ok() const -> bool { | ||||
|     return res_ == SQLITE_DONE || res_ == SQLITE_ROW; | ||||
|   } | ||||
|  | ||||
|   [[nodiscard]] auto get_error() const -> std::int32_t { return res_; } | ||||
|  | ||||
|   [[nodiscard]] auto get_error_str() const -> std::string { | ||||
|     return sqlite3_errstr(res_); | ||||
|   } | ||||
|  | ||||
|   [[nodiscard]] auto get_row(std::optional<db_row<context_t>> &row) const | ||||
|       -> bool { | ||||
|     constexpr const auto *function_name = | ||||
|         static_cast<const char *>(__FUNCTION__); | ||||
|  | ||||
|     row.reset(); | ||||
|     if (has_row()) { | ||||
|       row = db_row{context_}; | ||||
|       set_res(sqlite3_step(context_->stmt.get()), function_name); | ||||
|       return true; | ||||
|     } | ||||
|     return false; | ||||
|   } | ||||
|  | ||||
|   [[nodiscard]] auto has_row() const -> bool { return res_ == SQLITE_ROW; } | ||||
|  | ||||
|   void next_row() const { | ||||
|     constexpr const auto *function_name = | ||||
|         static_cast<const char *>(__FUNCTION__); | ||||
|  | ||||
|     if (has_row()) { | ||||
|       set_res(sqlite3_step(context_->stmt.get()), function_name); | ||||
|     } | ||||
|   } | ||||
| }; | ||||
|  | ||||
| inline void set_journal_mode(sqlite3 &db3) { | ||||
|   sqlite3_exec(&db3, "PRAGMA journal_mode = WAL;PRAGMA synchronous = NORMAL;", | ||||
|                nullptr, nullptr, nullptr); | ||||
| } | ||||
|  | ||||
| [[nodiscard]] inline auto execute_sql(sqlite3 &db3, const std::string &sql, | ||||
|                                       std::string &err) -> bool { | ||||
|   char *err_msg{nullptr}; | ||||
|   auto res = sqlite3_exec(&db3, sql.c_str(), nullptr, nullptr, &err_msg); | ||||
|   if (err_msg != nullptr) { | ||||
|     err = err_msg; | ||||
|     sqlite3_free(err_msg); | ||||
|     err_msg = nullptr; | ||||
|   } | ||||
|   if (res != SQLITE_OK) { | ||||
|     err = "failed to execute sql|" + sql + "|" + std::to_string(res) + '|' + | ||||
|           (err.empty() ? sqlite3_errstr(res) : err); | ||||
|     return false; | ||||
|   } | ||||
|  | ||||
|   return true; | ||||
| } | ||||
| } // namespace repertory::db | ||||
|  | ||||
| #endif // INCLUDE_DATABASE_DB_COMMON_HPP_ | ||||
							
								
								
									
										69
									
								
								repertory/librepertory/include/database/db_insert.hpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										69
									
								
								repertory/librepertory/include/database/db_insert.hpp
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,69 @@ | ||||
| /* | ||||
|   Copyright <2018-2024> <scott.e.graves@protonmail.com> | ||||
|  | ||||
|   Permission is hereby granted, free of charge, to any person obtaining a copy | ||||
|   of this software and associated documentation files (the "Software"), to deal | ||||
|   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_DATABASE_DB_INSERT_HPP_ | ||||
| #define INCLUDE_DATABASE_DB_INSERT_HPP_ | ||||
|  | ||||
| #include "database/db_common.hpp" | ||||
| #include "utils/error_utils.hpp" | ||||
|  | ||||
| namespace repertory::db { | ||||
| class db_insert final { | ||||
| public: | ||||
|   struct context final { | ||||
|     context(sqlite3 &db3_, std::string table_name_) | ||||
|         : db3(db3_), table_name(std::move(table_name_)) {} | ||||
|  | ||||
|     sqlite3 &db3; | ||||
|     std::string table_name; | ||||
|  | ||||
|     bool or_replace{false}; | ||||
|     std::map<std::string, db_types_t> values{}; | ||||
|     db3_stmt_t stmt{nullptr}; | ||||
|   }; | ||||
|  | ||||
|   using row = db_row<context>; | ||||
|  | ||||
| public: | ||||
|   db_insert(sqlite3 &db3, std::string table_name) | ||||
|       : context_(std::make_shared<context>(db3, table_name)) {} | ||||
|  | ||||
|   db_insert(std::shared_ptr<context> ctx) : context_(std::move(ctx)) {} | ||||
|  | ||||
| private: | ||||
|   std::shared_ptr<context> context_; | ||||
|  | ||||
| public: | ||||
|   [[nodiscard]] auto or_replace() -> db_insert & { | ||||
|     context_->or_replace = true; | ||||
|     return *this; | ||||
|   } | ||||
|  | ||||
|   [[nodiscard]] auto column_value(std::string column_name, db_types_t value) | ||||
|       -> db_insert &; | ||||
|  | ||||
|   [[nodiscard]] auto dump() const -> std::string; | ||||
|  | ||||
|   [[nodiscard]] auto go() const -> db_result<context>; | ||||
| }; | ||||
| } // namespace repertory::db | ||||
|  | ||||
| #endif // INCLUDE_DATABASE_DB_INSERT_HPP_ | ||||
							
								
								
									
										125
									
								
								repertory/librepertory/include/database/db_select.hpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										125
									
								
								repertory/librepertory/include/database/db_select.hpp
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,125 @@ | ||||
| /* | ||||
|   Copyright <2018-2024> <scott.e.graves@protonmail.com> | ||||
|  | ||||
|   Permission is hereby granted, free of charge, to any person obtaining a copy | ||||
|   of this software and associated documentation files (the "Software"), to deal | ||||
|   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_DATABASE_DB_SELECT_HPP_ | ||||
| #define INCLUDE_DATABASE_DB_SELECT_HPP_ | ||||
|  | ||||
| #include "database/db_common.hpp" | ||||
| #include "utils/error_utils.hpp" | ||||
|  | ||||
| namespace repertory::db { | ||||
| class db_select final { | ||||
| public: | ||||
|   struct context final { | ||||
|     context(sqlite3 &db3_, std::string table_name_) | ||||
|         : db3(db3_), table_name(std::move(table_name_)) {} | ||||
|  | ||||
|     sqlite3 &db3; | ||||
|     std::string table_name; | ||||
|  | ||||
|     std::vector<comp_data_t> ands{}; | ||||
|     std::vector<std::string> columns{}; | ||||
|     std::map<std::string, std::string> count_columns{}; | ||||
|     bool delete_query{false}; | ||||
|     std::optional<std::int32_t> limit; | ||||
|     std::optional<std::pair<std::string, bool>> order_by; | ||||
|     db3_stmt_t stmt{nullptr}; | ||||
|   }; | ||||
|  | ||||
|   using row = db_row<context>; | ||||
|  | ||||
| public: | ||||
|   db_select(sqlite3 &db3, std::string table_name) | ||||
|       : context_(std::make_shared<context>(db3, table_name)) {} | ||||
|  | ||||
|   db_select(std::shared_ptr<context> ctx) : context_(std::move(ctx)) {} | ||||
|  | ||||
| public: | ||||
|   struct db_where final { | ||||
|     db_where(std::shared_ptr<context> ctx, std::string column_name) | ||||
|         : context_(std::move(ctx)), column_name_(std::move(column_name)) {} | ||||
|  | ||||
|   public: | ||||
|     struct db_where_next final { | ||||
|       db_where_next(std::shared_ptr<context> ctx) : context_(std::move(ctx)) {} | ||||
|  | ||||
|     private: | ||||
|       std::shared_ptr<context> context_; | ||||
|  | ||||
|     public: | ||||
|       [[nodiscard]] auto and_where(std::string column_name) const -> db_where { | ||||
|         return db_where{context_, column_name}; | ||||
|       } | ||||
|  | ||||
|       [[nodiscard]] auto dump() const -> std::string { | ||||
|         return db_select{context_}.dump(); | ||||
|       } | ||||
|  | ||||
|       [[nodiscard]] auto go() const -> db_result<context> { | ||||
|         return db_select{context_}.go(); | ||||
|       } | ||||
|  | ||||
|       [[nodiscard]] auto limit(std::int32_t value) const -> db_select { | ||||
|         return db_select{context_}.limit(value); | ||||
|       } | ||||
|  | ||||
|       [[nodiscard]] auto order_by(std::string column_name, bool ascending) const | ||||
|           -> db_select { | ||||
|         return db_select{context_}.order_by(column_name, ascending); | ||||
|       } | ||||
|     }; | ||||
|  | ||||
|   private: | ||||
|     std::shared_ptr<context> context_; | ||||
|     std::string column_name_; | ||||
|  | ||||
|   public: | ||||
|     [[nodiscard]] auto equals(db_types_t value) const -> db_where_next { | ||||
|       context_->ands.emplace_back(comp_data_t{column_name_, "=", value}); | ||||
|       return db_where_next{context_}; | ||||
|     } | ||||
|   }; | ||||
|  | ||||
| private: | ||||
|   std::shared_ptr<context> context_; | ||||
|  | ||||
| public: | ||||
|   [[nodiscard]] auto column(std::string column_name) -> db_select &; | ||||
|  | ||||
|   [[nodiscard]] auto count(std::string column_name, std::string as_column_name) | ||||
|       -> db_select &; | ||||
|  | ||||
|   [[nodiscard]] auto delete_query() -> db_select &; | ||||
|  | ||||
|   [[nodiscard]] auto dump() const -> std::string; | ||||
|  | ||||
|   [[nodiscard]] auto go() const -> db_result<context>; | ||||
|  | ||||
|   [[nodiscard]] auto limit(std::int32_t value) -> db_select &; | ||||
|  | ||||
|   [[nodiscard]] auto order_by(std::string column_name, bool ascending) | ||||
|       -> db_select &; | ||||
|  | ||||
|   [[nodiscard]] auto where(std::string column_name) const -> db_where; | ||||
| }; | ||||
| } // namespace repertory::db | ||||
|  | ||||
| #endif // INCLUDE_DATABASE_DB_SELECT_HPP_ | ||||
							
								
								
									
										71
									
								
								repertory/librepertory/include/drives/directory_cache.hpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										71
									
								
								repertory/librepertory/include/drives/directory_cache.hpp
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,71 @@ | ||||
| /* | ||||
|   Copyright <2018-2024> <scott.e.graves@protonmail.com> | ||||
|  | ||||
|   Permission is hereby granted, free of charge, to any person obtaining a copy | ||||
|   of this software and associated documentation files (the "Software"), to deal | ||||
|   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 "utils/single_thread_service_base.hpp" | ||||
|  | ||||
| namespace repertory { | ||||
| class directory_iterator; | ||||
|  | ||||
| class directory_cache final : public single_thread_service_base { | ||||
| public: | ||||
|   using execute_callback = std::function<void(directory_iterator &)>; | ||||
|  | ||||
| private: | ||||
|   struct open_directory { | ||||
|     directory_iterator *iterator{nullptr}; | ||||
|     std::chrono::system_clock::time_point last_update{ | ||||
|         std::chrono::system_clock::now()}; | ||||
|   }; | ||||
|  | ||||
| public: | ||||
|   directory_cache() : single_thread_service_base("directory_cache") {} | ||||
|   ~directory_cache() override = default; | ||||
|  | ||||
|   directory_cache(const directory_cache &) = delete; | ||||
|   directory_cache(directory_cache &&) = delete; | ||||
|   auto operator=(const directory_cache &) -> directory_cache & = delete; | ||||
|   auto operator=(directory_cache &&) -> directory_cache & = delete; | ||||
|  | ||||
| private: | ||||
|   std::unordered_map<std::string, open_directory> directory_lookup_; | ||||
|   std::recursive_mutex directory_mutex_; | ||||
|   std::unique_ptr<std::thread> refresh_thread_; | ||||
|  | ||||
| protected: | ||||
|   void service_function() override; | ||||
|  | ||||
| public: | ||||
|   void execute_action(const std::string &api_path, | ||||
|                       const execute_callback &execute); | ||||
|  | ||||
|   [[nodiscard]] auto remove_directory(const std::string &api_path) | ||||
|       -> directory_iterator *; | ||||
|  | ||||
|   void remove_directory(directory_iterator *iterator); | ||||
|  | ||||
|   void set_directory(const std::string &api_path, directory_iterator *iterator); | ||||
| }; | ||||
| } // namespace repertory | ||||
|  | ||||
| #endif // INCLUDE_DRIVES_DIRECTORY_CACHE_HPP_ | ||||
							
								
								
									
										81
									
								
								repertory/librepertory/include/drives/directory_iterator.hpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										81
									
								
								repertory/librepertory/include/drives/directory_iterator.hpp
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,81 @@ | ||||
| /* | ||||
|   Copyright <2018-2024> <scott.e.graves@protonmail.com> | ||||
|  | ||||
|   Permission is hereby granted, free of charge, to any person obtaining a copy | ||||
|   of this software and associated documentation files (the "Software"), to deal | ||||
|   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 "types/remote.hpp" | ||||
| #include "types/repertory.hpp" | ||||
|  | ||||
| namespace repertory { | ||||
| class directory_iterator final { | ||||
| public: | ||||
| #ifndef _WIN32 | ||||
|   using populate_stat_callback = | ||||
|       std::function<void(const std::string &, std::uint64_t, | ||||
|                          const api_meta_map &, bool, struct stat *)>; | ||||
| #endif | ||||
| public: | ||||
|   explicit directory_iterator(directory_item_list list) | ||||
|       : items_(std::move(list)) {} | ||||
|  | ||||
|   directory_iterator(const directory_iterator &iterator) noexcept = default; | ||||
|  | ||||
|   directory_iterator(directory_iterator &&iterator) noexcept | ||||
|       : items_(std::move(iterator.items_)) {} | ||||
|  | ||||
| private: | ||||
|   directory_item_list items_; | ||||
|  | ||||
| public: | ||||
| #ifndef _WIN32 | ||||
|   [[nodiscard]] auto fill_buffer(const remote::file_offset &offset, | ||||
|                                  fuse_fill_dir_t filler_function, void *buffer, | ||||
|                                  populate_stat_callback populate_stat) -> int; | ||||
| #endif | ||||
|  | ||||
|   [[nodiscard]] auto get(std::size_t offset, std::string &item) -> int; | ||||
|  | ||||
|   [[nodiscard]] auto get_count() const -> std::size_t { return items_.size(); } | ||||
|  | ||||
|   [[nodiscard]] auto get_directory_item(std::size_t offset, directory_item &di) | ||||
|       -> api_error; | ||||
|  | ||||
|   [[nodiscard]] auto get_directory_item(const std::string &api_path, | ||||
|                                         directory_item &di) -> api_error; | ||||
|  | ||||
|   [[nodiscard]] auto get_json(std::size_t offset, json &item) -> int; | ||||
|  | ||||
|   [[nodiscard]] auto | ||||
|   get_next_directory_offset(const std::string &api_path) const -> std::size_t; | ||||
|  | ||||
| public: | ||||
|   auto operator=(const directory_iterator &iterator) noexcept | ||||
|       -> directory_iterator &; | ||||
|  | ||||
|   auto operator=(directory_iterator &&iterator) noexcept | ||||
|       -> directory_iterator &; | ||||
|  | ||||
|   auto operator=(directory_item_list list) noexcept -> directory_iterator &; | ||||
| }; | ||||
| } // namespace repertory | ||||
|  | ||||
| #endif // INCLUDE_DRIVES_DIRECTORY_ITERATOR_HPP_ | ||||
							
								
								
									
										58
									
								
								repertory/librepertory/include/drives/eviction.hpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										58
									
								
								repertory/librepertory/include/drives/eviction.hpp
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,58 @@ | ||||
| /* | ||||
|   Copyright <2018-2024> <scott.e.graves@protonmail.com> | ||||
|  | ||||
|   Permission is hereby granted, free of charge, to any person obtaining a copy | ||||
|   of this software and associated documentation files (the "Software"), to deal | ||||
|   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 "utils/single_thread_service_base.hpp" | ||||
|  | ||||
| namespace repertory { | ||||
| class app_config; | ||||
| class i_file_manager; | ||||
| class i_provider; | ||||
|  | ||||
| class eviction final : public single_thread_service_base { | ||||
| public: | ||||
|   eviction(i_provider &provider, const app_config &config, i_file_manager &fm) | ||||
|       : single_thread_service_base("eviction"), | ||||
|         provider_(provider), | ||||
|         config_(config), | ||||
|         fm_(fm) {} | ||||
|  | ||||
|   ~eviction() override = default; | ||||
|  | ||||
| private: | ||||
|   i_provider &provider_; | ||||
|   const app_config &config_; | ||||
|   i_file_manager &fm_; | ||||
|  | ||||
| private: | ||||
|   [[nodiscard]] auto check_minimum_requirements(const std::string &file_path) | ||||
|       -> bool; | ||||
|  | ||||
|   [[nodiscard]] auto get_filtered_cached_files() -> std::deque<std::string>; | ||||
|  | ||||
| protected: | ||||
|   void service_function() override; | ||||
| }; | ||||
| } // namespace repertory | ||||
|  | ||||
| #endif // INCLUDE_DRIVES_EVICTION_HPP_ | ||||
							
								
								
									
										41
									
								
								repertory/librepertory/include/drives/fuse/events.hpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										41
									
								
								repertory/librepertory/include/drives/fuse/events.hpp
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,41 @@ | ||||
| /* | ||||
|   Copyright <2018-2024> <scott.e.graves@protonmail.com> | ||||
|  | ||||
|   Permission is hereby granted, free of charge, to any person obtaining a copy | ||||
|   of this software and associated documentation files (the "Software"), to deal | ||||
|   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 "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_ | ||||
							
								
								
									
										617
									
								
								repertory/librepertory/include/drives/fuse/fuse_base.hpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										617
									
								
								repertory/librepertory/include/drives/fuse/fuse_base.hpp
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,617 @@ | ||||
| /* | ||||
|   Copyright <2018-2024> <scott.e.graves@protonmail.com> | ||||
|  | ||||
|   Permission is hereby granted, free of charge, to any person obtaining a copy | ||||
|   of this software and associated documentation files (the "Software"), to deal | ||||
|   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 "events/event_system.hpp" | ||||
| #include "utils/path_utils.hpp" | ||||
|  | ||||
| namespace repertory { | ||||
| class app_config; | ||||
| class i_provider; | ||||
|  | ||||
| class fuse_base { | ||||
|   E_CONSUMER(); | ||||
|  | ||||
| public: | ||||
|   explicit fuse_base(app_config &config); | ||||
|  | ||||
|   virtual ~fuse_base(); | ||||
|  | ||||
| public: | ||||
|   fuse_base(const fuse_base &) = delete; | ||||
|   fuse_base(fuse_base &&) = delete; | ||||
|   auto operator=(const fuse_base &) -> fuse_base & = delete; | ||||
|   auto operator=(fuse_base &&) -> fuse_base & = delete; | ||||
|  | ||||
| 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 auto instance() -> fuse_base &; | ||||
|  | ||||
| private: | ||||
|   struct fuse_operations fuse_ops_ {}; | ||||
|  | ||||
| private: | ||||
|   [[nodiscard]] auto 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, | ||||
|       bool disable_logging = false) -> int; | ||||
|  | ||||
|   [[nodiscard]] auto | ||||
|   execute_callback(const std::string &function_name, const char *path, | ||||
|                    const std::function<api_error(const std::string &)> &cb, | ||||
|                    bool disable_logging = false) -> int; | ||||
|  | ||||
|   static void execute_void_callback(const std::string &function_name, | ||||
|                                     const std::function<void()> &cb); | ||||
|  | ||||
|   static auto execute_void_pointer_callback(const std::string &function_name, | ||||
|                                             const std::function<void *()> &cb) | ||||
|       -> void *; | ||||
|  | ||||
|   void raise_fuse_event(std::string function_name, const std::string &api_path, | ||||
|                         int ret, bool disable_logging); | ||||
|  | ||||
| private: | ||||
|   [[nodiscard]] static auto access_(const char *path, int mask) -> int; | ||||
|  | ||||
| #ifdef __APPLE__ | ||||
|   [[nodiscard]] static auto chflags_(const char *path, uint32_t flags) -> int; | ||||
| #endif // __APPLE__ | ||||
|  | ||||
| #if FUSE_USE_VERSION >= 30 | ||||
|   [[nodiscard]] static auto chmod_(const char *path, mode_t mode, | ||||
|                                    struct fuse_file_info *fi) -> int; | ||||
| #else | ||||
|   [[nodiscard]] static auto chmod_(const char *path, mode_t mode) -> int; | ||||
| #endif | ||||
|  | ||||
| #if FUSE_USE_VERSION >= 30 | ||||
|   [[nodiscard]] static auto chown_(const char *path, uid_t uid, gid_t gid, | ||||
|                                    struct fuse_file_info *fi) -> int; | ||||
| #else | ||||
|   [[nodiscard]] static auto chown_(const char *path, uid_t uid, gid_t gid) | ||||
|       -> int; | ||||
| #endif | ||||
|  | ||||
|   [[nodiscard]] static auto create_(const char *path, mode_t mode, | ||||
|                                     struct fuse_file_info *fi) -> int; | ||||
|  | ||||
|   static void destroy_(void *ptr); | ||||
|  | ||||
|   [[nodiscard]] static auto fallocate_(const char *path, int mode, off_t offset, | ||||
|                                        off_t length, struct fuse_file_info *fi) | ||||
|       -> int; | ||||
|  | ||||
| #if FUSE_USE_VERSION < 30 | ||||
|   [[nodiscard]] static auto fgetattr_(const char *path, struct stat *st, | ||||
|                                       struct fuse_file_info *fi) -> int; | ||||
| #endif | ||||
|  | ||||
| #ifdef __APPLE__ | ||||
|   [[nodiscard]] static auto fsetattr_x_(const char *path, | ||||
|                                         struct setattr_x *attr, | ||||
|                                         struct fuse_file_info *fi) -> int; | ||||
| #endif // __APPLE__ | ||||
|  | ||||
|   [[nodiscard]] static auto fsync_(const char *path, int datasync, | ||||
|                                    struct fuse_file_info *fi) -> int; | ||||
|  | ||||
|   [[nodiscard]] static auto ftruncate_(const char *path, off_t size, | ||||
|                                        struct fuse_file_info *fi) -> int; | ||||
|  | ||||
| #if FUSE_USE_VERSION >= 30 | ||||
|   [[nodiscard]] static auto getattr_(const char *path, struct stat *st, | ||||
|                                      struct fuse_file_info *fi) -> int; | ||||
| #else | ||||
|   [[nodiscard]] static auto getattr_(const char *path, struct stat *st) -> int; | ||||
| #endif | ||||
|  | ||||
| #ifdef __APPLE__ | ||||
|   [[nodiscard]] static auto getxtimes_(const char *path, | ||||
|                                        struct timespec *bkuptime, | ||||
|                                        struct timespec *crtime) -> int; | ||||
| #endif // __APPLE__ | ||||
|  | ||||
| #if FUSE_USE_VERSION >= 30 | ||||
|   [[nodiscard]] static auto init_(struct fuse_conn_info *conn, | ||||
|                                   struct fuse_config *cfg) -> void *; | ||||
| #else | ||||
|   [[nodiscard]] static auto init_(struct fuse_conn_info *conn) -> void *; | ||||
| #endif | ||||
|  | ||||
|   [[nodiscard]] static auto mkdir_(const char *path, mode_t mode) -> int; | ||||
|  | ||||
|   [[nodiscard]] static auto open_(const char *path, struct fuse_file_info *fi) | ||||
|       -> int; | ||||
|  | ||||
|   [[nodiscard]] static auto opendir_(const char *path, | ||||
|                                      struct fuse_file_info *fi) -> int; | ||||
|  | ||||
|   [[nodiscard]] static auto read_(const char *path, char *buffer, | ||||
|                                   size_t read_size, off_t read_offset, | ||||
|                                   struct fuse_file_info *fi) -> int; | ||||
|  | ||||
| #if FUSE_USE_VERSION >= 30 | ||||
|   [[nodiscard]] static auto readdir_(const char *path, void *buf, | ||||
|                                      fuse_fill_dir_t fuse_fill_dir, | ||||
|                                      off_t offset, struct fuse_file_info *fi, | ||||
|                                      fuse_readdir_flags flags) -> int; | ||||
| #else | ||||
|   [[nodiscard]] static auto readdir_(const char *path, void *buf, | ||||
|                                      fuse_fill_dir_t fuse_fill_dir, | ||||
|                                      off_t offset, struct fuse_file_info *fi) | ||||
|       -> int; | ||||
| #endif | ||||
|  | ||||
|   [[nodiscard]] static auto release_(const char *path, | ||||
|                                      struct fuse_file_info *fi) -> int; | ||||
|  | ||||
|   [[nodiscard]] static auto releasedir_(const char *path, | ||||
|                                         struct fuse_file_info *fi) -> int; | ||||
|  | ||||
| #if FUSE_USE_VERSION >= 30 | ||||
|   [[nodiscard]] static auto rename_(const char *from, const char *to, | ||||
|                                     unsigned int flags) -> int; | ||||
| #else | ||||
|   [[nodiscard]] static auto rename_(const char *from, const char *to) -> int; | ||||
| #endif | ||||
|  | ||||
|   [[nodiscard]] static auto rmdir_(const char *path) -> int; | ||||
|  | ||||
| #ifdef HAS_SETXATTR | ||||
| #ifdef __APPLE__ | ||||
|   [[nodiscard]] static auto getxattr_(const char *path, const char *name, | ||||
|                                       char *value, size_t size, | ||||
|                                       uint32_t position) -> int; | ||||
|  | ||||
| #else  // __APPLE__ | ||||
|   [[nodiscard]] static auto getxattr_(const char *path, const char *name, | ||||
|                                       char *value, size_t size) -> int; | ||||
| #endif // __APPLE__ | ||||
|  | ||||
|   [[nodiscard]] static auto listxattr_(const char *path, char *buffer, | ||||
|                                        size_t size) -> int; | ||||
|  | ||||
|   [[nodiscard]] static auto removexattr_(const char *path, const char *name) | ||||
|       -> int; | ||||
|  | ||||
| #ifdef __APPLE__ | ||||
|   [[nodiscard]] static auto setxattr_(const char *path, const char *name, | ||||
|                                       const char *value, size_t size, int flags, | ||||
|                                       uint32_t position) -> int; | ||||
|  | ||||
| #else  // __APPLE__ | ||||
|   [[nodiscard]] static auto setxattr_(const char *path, const char *name, | ||||
|                                       const char *value, size_t size, int flags) | ||||
|       -> int; | ||||
| #endif // __APPLE__ | ||||
| #endif // HAS_SETXATTR | ||||
|  | ||||
| #ifdef __APPLE__ | ||||
|   [[nodiscard]] static auto setattr_x_(const char *path, struct setattr_x *attr) | ||||
|       -> int; | ||||
|  | ||||
|   [[nodiscard]] static auto setbkuptime_(const char *path, | ||||
|                                          const struct timespec *bkuptime) | ||||
|       -> int; | ||||
|  | ||||
|   [[nodiscard]] static auto setchgtime_(const char *path, | ||||
|                                         const struct timespec *chgtime) -> int; | ||||
|  | ||||
|   [[nodiscard]] static auto setcrtime_(const char *path, | ||||
|                                        const struct timespec *crtime) -> int; | ||||
|  | ||||
|   [[nodiscard]] static auto setvolname_(const char *volname) -> int; | ||||
|  | ||||
|   [[nodiscard]] static auto statfs_x_(const char *path, struct statfs *stbuf) | ||||
|       -> int; | ||||
|  | ||||
| #else  // __APPLE__ | ||||
|   [[nodiscard]] static auto statfs_(const char *path, struct statvfs *stbuf) | ||||
|       -> int; | ||||
| #endif // __APPLE__ | ||||
|  | ||||
| #if FUSE_USE_VERSION >= 30 | ||||
|   [[nodiscard]] static auto truncate_(const char *path, off_t size, | ||||
|                                       struct fuse_file_info *fi) -> int; | ||||
| #else | ||||
|   [[nodiscard]] static auto truncate_(const char *path, off_t size) -> int; | ||||
| #endif | ||||
|  | ||||
|   [[nodiscard]] static auto unlink_(const char *path) -> int; | ||||
|  | ||||
| #if FUSE_USE_VERSION >= 30 | ||||
|   [[nodiscard]] static auto utimens_(const char *path, | ||||
|                                      const struct timespec tv[2], | ||||
|                                      struct fuse_file_info *fi) -> int; | ||||
| #else | ||||
|   [[nodiscard]] static auto utimens_(const char *path, | ||||
|                                      const struct timespec tv[2]) -> int; | ||||
| #endif | ||||
|  | ||||
|   [[nodiscard]] static auto write_(const char *path, const char *buffer, | ||||
|                                    size_t write_size, off_t write_offset, | ||||
|                                    struct fuse_file_info *fi) -> int; | ||||
|  | ||||
| protected: | ||||
|   [[nodiscard]] virtual auto access_impl(std::string /*api_path*/, int /*mask*/) | ||||
|       -> api_error { | ||||
|     return api_error::not_implemented; | ||||
|   } | ||||
|  | ||||
| #ifdef __APPLE__ | ||||
|   [[nodiscard]] virtual auto chflags_impl(std::string /*api_path*/, | ||||
|                                           uint32_t /*flags*/) -> api_error { | ||||
|     return api_error::not_implemented; | ||||
|   } | ||||
| #endif // __APPLE__ | ||||
|  | ||||
| #if FUSE_USE_VERSION >= 30 | ||||
|   [[nodiscard]] virtual auto chmod_impl(std::string /*api_path*/, | ||||
|                                         mode_t /*mode*/, | ||||
|                                         struct fuse_file_info * /*fi*/) | ||||
|       -> api_error { | ||||
|     return api_error::not_implemented; | ||||
|   } | ||||
| #else | ||||
|   [[nodiscard]] virtual auto chmod_impl(std::string /*api_path*/, | ||||
|                                         mode_t /*mode*/) -> api_error { | ||||
|     return api_error::not_implemented; | ||||
|   } | ||||
| #endif | ||||
|  | ||||
| #if FUSE_USE_VERSION >= 30 | ||||
|   [[nodiscard]] virtual auto chown_impl(std::string /*api_path*/, uid_t /*uid*/, | ||||
|                                         gid_t /*gid*/, | ||||
|                                         struct fuse_file_info * /*fi*/) | ||||
|       -> api_error { | ||||
|     return api_error::not_implemented; | ||||
|   } | ||||
| #else | ||||
|   [[nodiscard]] virtual auto chown_impl(std::string /*api_path*/, uid_t /*uid*/, | ||||
|                                         gid_t /*gid*/) -> api_error { | ||||
|     return api_error::not_implemented; | ||||
|   } | ||||
| #endif | ||||
|  | ||||
|   [[nodiscard]] virtual auto create_impl(std::string /*api_path*/, | ||||
|                                          mode_t /*mode*/, | ||||
|                                          struct fuse_file_info * /*fi*/) | ||||
|       -> api_error { | ||||
|     return api_error::not_implemented; | ||||
|   } | ||||
|  | ||||
|   virtual void destroy_impl(void * /*ptr*/); | ||||
|  | ||||
|   [[nodiscard]] virtual auto | ||||
|   fallocate_impl(std::string /*api_path*/, int /*mode*/, off_t /*offset*/, | ||||
|                  off_t /*length*/, struct fuse_file_info * /*fi*/) | ||||
|       -> api_error { | ||||
|     return api_error::not_implemented; | ||||
|   } | ||||
|  | ||||
|   [[nodiscard]] virtual auto fgetattr_impl(std::string /*api_path*/, | ||||
|                                            struct stat * /*st*/, | ||||
|                                            struct fuse_file_info * /*fi*/) | ||||
|       -> api_error { | ||||
|     return api_error::not_implemented; | ||||
|   } | ||||
|  | ||||
| #ifdef __APPLE__ | ||||
|   [[nodiscard]] virtual auto fsetattr_x_impl(std::string /*api_path*/, | ||||
|                                              struct setattr_x * /*attr*/, | ||||
|                                              struct fuse_file_info * /*fi*/) | ||||
|       -> api_error { | ||||
|     return api_error::not_implemented; | ||||
|   } | ||||
| #endif // __APPLE__ | ||||
|  | ||||
|   [[nodiscard]] virtual auto fsync_impl(std::string /*api_path*/, | ||||
|                                         int /*datasync*/, | ||||
|                                         struct fuse_file_info * /*fi*/) | ||||
|       -> api_error { | ||||
|     return api_error::not_implemented; | ||||
|   } | ||||
|  | ||||
| #if FUSE_USE_VERSION < 30 | ||||
|   [[nodiscard]] virtual auto ftruncate_impl(std::string /*api_path*/, | ||||
|                                             off_t /*size*/, | ||||
|                                             struct fuse_file_info * /*fi*/) | ||||
|       -> api_error { | ||||
|     return api_error::not_implemented; | ||||
|   } | ||||
| #endif | ||||
|  | ||||
| #if FUSE_USE_VERSION >= 30 | ||||
|   [[nodiscard]] virtual auto getattr_impl(std::string /*api_path*/, | ||||
|                                           struct stat * /*st*/, | ||||
|                                           struct fuse_file_info * /*fi*/) | ||||
|       -> api_error { | ||||
|     return api_error::not_implemented; | ||||
|   } | ||||
| #else | ||||
|   [[nodiscard]] virtual auto getattr_impl(std::string /*api_path*/, | ||||
|                                           struct stat * /*st*/) -> api_error { | ||||
|     return api_error::not_implemented; | ||||
|   } | ||||
| #endif | ||||
|  | ||||
| #ifdef __APPLE__ | ||||
|   [[nodiscard]] virtual auto getxtimes_impl(std::string /*api_path*/, | ||||
|                                             struct timespec * /*bkuptime*/, | ||||
|                                             struct timespec * /*crtime*/) | ||||
|       -> api_error { | ||||
|     return api_error::not_implemented; | ||||
|   } | ||||
| #endif // __APPLE__ | ||||
|  | ||||
| #if FUSE_USE_VERSION >= 30 | ||||
|   virtual auto init_impl(struct fuse_conn_info *conn, struct fuse_config *cfg) | ||||
|       -> void *; | ||||
| #else | ||||
|   virtual auto init_impl(struct fuse_conn_info *conn) -> void *; | ||||
| #endif | ||||
|  | ||||
|   [[nodiscard]] virtual auto mkdir_impl(std::string /*api_path*/, | ||||
|                                         mode_t /*mode*/) -> api_error { | ||||
|     return api_error::not_implemented; | ||||
|   } | ||||
|  | ||||
|   [[nodiscard]] virtual auto open_impl(std::string /*api_path*/, | ||||
|                                        struct fuse_file_info * /*fi*/) | ||||
|       -> api_error { | ||||
|     return api_error::not_implemented; | ||||
|   } | ||||
|  | ||||
|   [[nodiscard]] virtual auto opendir_impl(std::string /*api_path*/, | ||||
|                                           struct fuse_file_info * /*fi*/) | ||||
|       -> api_error { | ||||
|     return api_error::not_implemented; | ||||
|   } | ||||
|  | ||||
|   [[nodiscard]] virtual auto | ||||
|   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*/) -> api_error { | ||||
|     return api_error::not_implemented; | ||||
|   } | ||||
|  | ||||
| #if FUSE_USE_VERSION >= 30 | ||||
|   [[nodiscard]] virtual auto | ||||
|   readdir_impl(std::string /*api_path*/, void * /*buf*/, | ||||
|                fuse_fill_dir_t /*fuse_fill_dir*/, off_t /*offset*/, | ||||
|                struct fuse_file_info * /*fi*/, fuse_readdir_flags /*flags*/) | ||||
|       -> api_error { | ||||
|     return api_error::not_implemented; | ||||
|   } | ||||
| #else | ||||
|   [[nodiscard]] virtual auto | ||||
|   readdir_impl(std::string /*api_path*/, void * /*buf*/, | ||||
|                fuse_fill_dir_t /*fuse_fill_dir*/, off_t /*offset*/, | ||||
|                struct fuse_file_info * /*fi*/) -> api_error { | ||||
|     return api_error::not_implemented; | ||||
|   } | ||||
| #endif | ||||
|  | ||||
|   [[nodiscard]] virtual auto release_impl(std::string /*api_path*/, | ||||
|                                           struct fuse_file_info * /*fi*/) | ||||
|       -> api_error { | ||||
|     return api_error::not_implemented; | ||||
|   } | ||||
|  | ||||
|   [[nodiscard]] virtual auto releasedir_impl(std::string /*api_path*/, | ||||
|                                              struct fuse_file_info * /*fi*/) | ||||
|       -> api_error { | ||||
|     return api_error::not_implemented; | ||||
|   } | ||||
|  | ||||
| #if FUSE_USE_VERSION >= 30 | ||||
|   [[nodiscard]] virtual auto rename_impl(std::string /*from_api_path*/, | ||||
|                                          std::string /*to_api_path*/, | ||||
|                                          unsigned int /*flags*/) -> api_error { | ||||
|     return api_error::not_implemented; | ||||
|   } | ||||
| #else | ||||
|   [[nodiscard]] virtual auto rename_impl(std::string /*from_api_path*/, | ||||
|                                          std::string /*to_api_path*/) | ||||
|       -> api_error { | ||||
|     return api_error::not_implemented; | ||||
|   } | ||||
| #endif | ||||
|  | ||||
|   [[nodiscard]] virtual auto rmdir_impl(std::string /*api_path*/) -> api_error { | ||||
|     return api_error::not_implemented; | ||||
|   } | ||||
|  | ||||
| #ifdef HAS_SETXATTR | ||||
| #ifdef __APPLE__ | ||||
|   [[nodiscard]] virtual auto | ||||
|   getxattr_impl(std::string /*api_path*/, const char * /*name*/, | ||||
|                 char * /*value*/, size_t /*size*/, uint32_t /*position*/, | ||||
|                 int & /*attribute_size*/) -> api_error { | ||||
|     return api_error::not_implemented; | ||||
|   } | ||||
| #else  // __APPLE__ | ||||
|   [[nodiscard]] virtual auto | ||||
|   getxattr_impl(std::string /*api_path*/, const char * /*name*/, | ||||
|                 char * /*value*/, size_t /*size*/, int & /*attribute_size*/) | ||||
|       -> api_error { | ||||
|     return api_error::not_implemented; | ||||
|   } | ||||
| #endif // __APPLE__ | ||||
|  | ||||
|   [[nodiscard]] virtual auto | ||||
|   listxattr_impl(std::string /*api_path*/, char * /*buffer*/, size_t /*size*/, | ||||
|                  int & /*required_size*/, bool & /*return_size*/) -> api_error { | ||||
|     return api_error::not_implemented; | ||||
|   } | ||||
|  | ||||
|   [[nodiscard]] virtual auto removexattr_impl(std::string /*api_path*/, | ||||
|                                               const char * /*name*/) | ||||
|       -> api_error { | ||||
|     return api_error::not_implemented; | ||||
|   } | ||||
|  | ||||
| #ifdef __APPLE__ | ||||
|   [[nodiscard]] virtual auto setxattr_impl(std::string /*api_path*/, | ||||
|                                            const char * /*name*/, | ||||
|                                            const char * /*value*/, | ||||
|                                            size_t /*size*/, int /*flags*/, | ||||
|                                            uint32_t /*position*/) -> api_error { | ||||
|     return api_error::not_implemented; | ||||
|   } | ||||
| #else  // __APPLE__ | ||||
|   [[nodiscard]] virtual auto | ||||
|   setxattr_impl(std::string /*api_path*/, const char * /*name*/, | ||||
|                 const char * /*value*/, size_t /*size*/, int /*flags*/) | ||||
|       -> api_error { | ||||
|     return api_error::not_implemented; | ||||
|   } | ||||
| #endif // __APPLE__ | ||||
| #endif // HAS_SETXATTR | ||||
|  | ||||
| #ifdef __APPLE__ | ||||
|   [[nodiscard]] virtual auto setattr_x_impl(std::string /*api_path*/, | ||||
|                                             struct setattr_x * /*attr*/) | ||||
|       -> api_error { | ||||
|     return api_error::not_implemented; | ||||
|   } | ||||
|  | ||||
|   [[nodiscard]] virtual auto | ||||
|   setbkuptime_impl(std::string /*api_path*/, | ||||
|                    const struct timespec * /*bkuptime*/) -> api_error { | ||||
|     return api_error::not_implemented; | ||||
|   } | ||||
|  | ||||
|   [[nodiscard]] virtual auto | ||||
|   setchgtime_impl(std::string /*api_path*/, const struct timespec * /*chgtime*/) | ||||
|       -> api_error { | ||||
|     return api_error::not_implemented; | ||||
|   } | ||||
|  | ||||
|   [[nodiscard]] virtual auto setcrtime_impl(std::string /*api_path*/, | ||||
|                                             const struct timespec * /*crtime*/) | ||||
|       -> api_error { | ||||
|     return api_error::not_implemented; | ||||
|   } | ||||
|  | ||||
|   [[nodiscard]] virtual auto setvolname_impl(const char * /*volname*/) | ||||
|       -> api_error { | ||||
|     return api_error::not_implemented; | ||||
|   } | ||||
|  | ||||
|   [[nodiscard]] virtual auto statfs_x_impl(std::string /*api_path*/, | ||||
|                                            struct statfs * /*stbuf*/) | ||||
|       -> api_error { | ||||
|     return api_error::not_implemented; | ||||
|   } | ||||
| #else  // __APPLE__ | ||||
|   [[nodiscard]] virtual auto statfs_impl(std::string /*api_path*/, | ||||
|                                          struct statvfs * /*stbuf*/) | ||||
|       -> api_error { | ||||
|     return api_error::not_implemented; | ||||
|   } | ||||
| #endif // __APPLE__ | ||||
|  | ||||
| #if FUSE_USE_VERSION >= 30 | ||||
|   [[nodiscard]] virtual auto truncate_impl(std::string /*api_path*/, | ||||
|                                            off_t /*size*/, | ||||
|                                            struct fuse_file_info * /*fi*/) | ||||
|       -> api_error { | ||||
|     return api_error::not_implemented; | ||||
|   } | ||||
| #else | ||||
|   [[nodiscard]] virtual auto truncate_impl(std::string /*api_path*/, | ||||
|                                            off_t /*size*/) -> api_error { | ||||
|     return api_error::not_implemented; | ||||
|   } | ||||
| #endif | ||||
|  | ||||
|   [[nodiscard]] virtual auto unlink_impl(std::string /*api_path*/) | ||||
|       -> api_error { | ||||
|     return api_error::not_implemented; | ||||
|   } | ||||
|  | ||||
| #if FUSE_USE_VERSION >= 30 | ||||
|   [[nodiscard]] virtual auto utimens_impl(std::string /*api_path*/, | ||||
|                                           const struct timespec /*tv*/[2], | ||||
|                                           struct fuse_file_info * /*fi*/) | ||||
|       -> api_error { | ||||
|     return api_error::not_implemented; | ||||
|   } | ||||
| #else | ||||
|   [[nodiscard]] virtual auto utimens_impl(std::string /*api_path*/, | ||||
|                                           const struct timespec /*tv*/[2]) | ||||
|       -> api_error { | ||||
|     return api_error::not_implemented; | ||||
|   } | ||||
| #endif | ||||
|  | ||||
|   [[nodiscard]] virtual auto | ||||
|   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*/) | ||||
|       -> api_error { | ||||
|     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*/) {} | ||||
|  | ||||
|   [[nodiscard]] virtual auto parse_args(std::vector<std::string> &args) -> int; | ||||
|  | ||||
|   virtual void shutdown(); | ||||
|  | ||||
| public: | ||||
|   static void display_options(std::vector<const char *> args); | ||||
|  | ||||
|   static void display_version_information(std::vector<const char *> args); | ||||
|  | ||||
|   static auto unmount(const std::string &mount_location) -> int; | ||||
|  | ||||
|   [[nodiscard]] auto get_mount_location() const -> std::string { | ||||
|     return mount_location_; | ||||
|   } | ||||
|  | ||||
|   [[nodiscard]] auto mount(std::vector<std::string> args) -> int; | ||||
| }; | ||||
| } // namespace repertory | ||||
|  | ||||
| #endif // _WIN32 | ||||
| #endif // INCLUDE_DRIVES_FUSE_FUSE_BASE_HPP_ | ||||
							
								
								
									
										333
									
								
								repertory/librepertory/include/drives/fuse/fuse_drive.hpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										333
									
								
								repertory/librepertory/include/drives/fuse/fuse_drive.hpp
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,333 @@ | ||||
| /* | ||||
|   Copyright <2018-2024> <scott.e.graves@protonmail.com> | ||||
|  | ||||
|   Permission is hereby granted, free of charge, to any person obtaining a copy | ||||
|   of this software and associated documentation files (the "Software"), to deal | ||||
|   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 "drives/fuse/fuse_drive_base.hpp" | ||||
| #include "file_manager/file_manager.hpp" | ||||
|  | ||||
| namespace repertory { | ||||
| class app_config; | ||||
| class console_consumer; | ||||
| class directory_cache; | ||||
| class eviction; | ||||
| class full_server; | ||||
| class i_provider; | ||||
| class lock_data; | ||||
| class logging_consumer; | ||||
| namespace remote_fuse { | ||||
| class remote_server; | ||||
| } | ||||
|  | ||||
| class fuse_drive final : public fuse_drive_base { | ||||
| public: | ||||
|   fuse_drive(app_config &config, lock_data &lock_data, i_provider &provider); | ||||
|  | ||||
|   ~fuse_drive() override = default; | ||||
|  | ||||
| public: | ||||
|   fuse_drive(const fuse_drive &) = delete; | ||||
|   fuse_drive(fuse_drive &&) = delete; | ||||
|  | ||||
|   auto operator=(const fuse_drive &) -> fuse_drive & = delete; | ||||
|   auto operator=(fuse_drive &&) -> fuse_drive & = delete; | ||||
|  | ||||
| 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<eviction> eviction_; | ||||
|   std::shared_ptr<file_manager> fm_; | ||||
|   std::shared_ptr<logging_consumer> logging_consumer_; | ||||
|   std::shared_ptr<remote_fuse::remote_server> remote_server_; | ||||
|   std::shared_ptr<full_server> server_; | ||||
|   bool was_mounted_ = false; | ||||
|  | ||||
| private: | ||||
|   void update_accessed_time(const std::string &api_path); | ||||
|  | ||||
| protected: | ||||
| #ifdef __APPLE__ | ||||
|   [[nodiscard]] auto chflags_impl(std::string api_path, uint32_t flags) | ||||
|       -> api_error override; | ||||
| #endif // __APPLE__ | ||||
|  | ||||
| #if FUSE_USE_VERSION >= 30 | ||||
|   [[nodiscard]] auto chmod_impl(std::string api_path, mode_t mode, | ||||
|                                 struct fuse_file_info *file_info) | ||||
|       -> api_error override; | ||||
| #else | ||||
|   [[nodiscard]] auto chmod_impl(std::string api_path, mode_t mode) | ||||
|       -> api_error override; | ||||
| #endif | ||||
|  | ||||
| #if FUSE_USE_VERSION >= 30 | ||||
|   [[nodiscard]] auto chown_impl(std::string api_path, uid_t uid, gid_t gid, | ||||
|                                 struct fuse_file_info *file_info) | ||||
|       -> api_error override; | ||||
| #else | ||||
|   [[nodiscard]] auto chown_impl(std::string api_path, uid_t uid, gid_t gid) | ||||
|       -> api_error override; | ||||
| #endif | ||||
|  | ||||
|   [[nodiscard]] auto create_impl(std::string api_path, mode_t mode, | ||||
|                                  struct fuse_file_info *file_info) | ||||
|       -> api_error override; | ||||
|  | ||||
|   void destroy_impl(void *ptr) override; | ||||
|  | ||||
|   [[nodiscard]] auto fallocate_impl(std::string api_path, int mode, | ||||
|                                     off_t offset, off_t length, | ||||
|                                     struct fuse_file_info *file_info) | ||||
|       -> api_error override; | ||||
|  | ||||
|   [[nodiscard]] auto fgetattr_impl(std::string api_path, struct stat *st, | ||||
|                                    struct fuse_file_info *file_info) | ||||
|       -> api_error override; | ||||
|  | ||||
| #ifdef __APPLE__ | ||||
|   [[nodiscard]] auto fsetattr_x_impl(std::string api_path, | ||||
|                                      struct setattr_x *attr, | ||||
|                                      struct fuse_file_info *file_info) | ||||
|       -> api_error override; | ||||
| #endif // __APPLE__ | ||||
|  | ||||
|   [[nodiscard]] auto fsync_impl(std::string api_path, int datasync, | ||||
|                                 struct fuse_file_info *file_info) | ||||
|       -> api_error override; | ||||
|  | ||||
| #if FUSE_USE_VERSION < 30 | ||||
|   [[nodiscard]] auto ftruncate_impl(std::string api_path, off_t size, | ||||
|                                     struct fuse_file_info *file_info) | ||||
|       -> api_error override; | ||||
| #endif | ||||
|  | ||||
| #if FUSE_USE_VERSION >= 30 | ||||
|   [[nodiscard]] auto getattr_impl(std::string api_path, struct stat *st, | ||||
|                                   struct fuse_file_info *file_info) | ||||
|       -> api_error override; | ||||
| #else | ||||
|   [[nodiscard]] auto getattr_impl(std::string api_path, struct stat *st) | ||||
|       -> api_error override; | ||||
| #endif | ||||
|  | ||||
| #ifdef __APPLE__ | ||||
|   [[nodiscard]] auto getxtimes_impl(std::string api_path, | ||||
|                                     struct timespec *bkuptime, | ||||
|                                     struct timespec *crtime) | ||||
|       -> api_error override; | ||||
| #endif // __APPLE__ | ||||
|  | ||||
| #if FUSE_USE_VERSION >= 30 | ||||
|   auto init_impl(struct fuse_conn_info *conn, struct fuse_config *cfg) | ||||
|       -> void * override; | ||||
| #else | ||||
|   auto init_impl(struct fuse_conn_info *conn) -> void * override; | ||||
| #endif | ||||
|  | ||||
|   [[nodiscard]] auto mkdir_impl(std::string api_path, mode_t mode) | ||||
|       -> api_error override; | ||||
|  | ||||
|   void notify_fuse_main_exit(int &ret) override; | ||||
|  | ||||
|   [[nodiscard]] auto open_impl(std::string api_path, | ||||
|                                struct fuse_file_info *file_info) | ||||
|       -> api_error override; | ||||
|  | ||||
|   [[nodiscard]] auto opendir_impl(std::string api_path, | ||||
|                                   struct fuse_file_info *file_info) | ||||
|       -> api_error override; | ||||
|  | ||||
|   [[nodiscard]] auto read_impl(std::string api_path, char *buffer, | ||||
|                                size_t read_size, off_t read_offset, | ||||
|                                struct fuse_file_info *file_info, | ||||
|                                std::size_t &bytes_read) -> api_error override; | ||||
|  | ||||
| #if FUSE_USE_VERSION >= 30 | ||||
|   [[nodiscard]] auto readdir_impl(std::string api_path, void *buf, | ||||
|                                   fuse_fill_dir_t fuse_fill_dir, off_t offset, | ||||
|                                   struct fuse_file_info *file_info, | ||||
|                                   fuse_readdir_flags flags) | ||||
|       -> api_error override; | ||||
| #else | ||||
|   [[nodiscard]] auto readdir_impl(std::string api_path, void *buf, | ||||
|                                   fuse_fill_dir_t fuse_fill_dir, off_t offset, | ||||
|                                   struct fuse_file_info *file_info) | ||||
|       -> api_error override; | ||||
| #endif | ||||
|  | ||||
|   [[nodiscard]] auto release_impl(std::string api_path, | ||||
|                                   struct fuse_file_info *file_info) | ||||
|       -> api_error override; | ||||
|  | ||||
|   [[nodiscard]] auto releasedir_impl(std::string api_path, | ||||
|                                      struct fuse_file_info *file_info) | ||||
|       -> api_error override; | ||||
|  | ||||
| #if FUSE_USE_VERSION >= 30 | ||||
|   [[nodiscard]] auto rename_impl(std::string from_api_path, | ||||
|                                  std::string to_api_path, unsigned int flags) | ||||
|       -> api_error override; | ||||
| #else | ||||
|   [[nodiscard]] auto rename_impl(std::string from_api_path, | ||||
|                                  std::string to_api_path) -> api_error override; | ||||
| #endif | ||||
|  | ||||
|   [[nodiscard]] auto rmdir_impl(std::string api_path) -> api_error override; | ||||
|  | ||||
| #ifdef HAS_SETXATTR | ||||
|   [[nodiscard]] auto getxattr_common(std::string api_path, const char *name, | ||||
|                                      char *value, size_t size, | ||||
|                                      int &attribute_size, uint32_t *position) | ||||
|       -> api_error; | ||||
|  | ||||
| #ifdef __APPLE__ | ||||
|   [[nodiscard]] auto getxattr_impl(std::string api_path, const char *name, | ||||
|                                    char *value, size_t size, uint32_t position, | ||||
|                                    int &attribute_size) -> api_error override; | ||||
| #else  // __APPLE__ | ||||
|   [[nodiscard]] auto getxattr_impl(std::string api_path, const char *name, | ||||
|                                    char *value, size_t size, | ||||
|                                    int &attribute_size) -> api_error override; | ||||
| #endif // __APPLE__ | ||||
|  | ||||
|   [[nodiscard]] auto listxattr_impl(std::string api_path, char *buffer, | ||||
|                                     size_t size, int &required_size, | ||||
|                                     bool &return_size) -> api_error override; | ||||
|  | ||||
|   [[nodiscard]] auto removexattr_impl(std::string api_path, const char *name) | ||||
|       -> api_error override; | ||||
|  | ||||
| #ifdef __APPLE__ | ||||
|   [[nodiscard]] auto setxattr_impl(std::string api_path, const char *name, | ||||
|                                    const char *value, size_t size, int flags, | ||||
|                                    uint32_t position) -> api_error override; | ||||
| #else  // __APPLE__ | ||||
|   [[nodiscard]] auto setxattr_impl(std::string api_path, const char *name, | ||||
|                                    const char *value, size_t size, int flags) | ||||
|       -> api_error override; | ||||
| #endif // __APPLE__ | ||||
| #endif // HAS_SETXATTR | ||||
|  | ||||
| #ifdef __APPLE__ | ||||
|   [[nodiscard]] auto setattr_x_impl(std::string api_path, | ||||
|                                     struct setattr_x *attr) | ||||
|       -> api_error override; | ||||
|  | ||||
|   [[nodiscard]] auto setbkuptime_impl(std::string api_path, | ||||
|                                       const struct timespec *bkuptime) | ||||
|       -> api_error override; | ||||
|  | ||||
|   [[nodiscard]] auto setchgtime_impl(std::string api_path, | ||||
|                                      const struct timespec *chgtime) | ||||
|       -> api_error override; | ||||
|  | ||||
|   [[nodiscard]] auto setcrtime_impl(std::string api_path, | ||||
|                                     const struct timespec *crtime) | ||||
|       -> api_error override; | ||||
|  | ||||
|   [[nodiscard]] auto setvolname_impl(const char *volname) -> api_error override; | ||||
|  | ||||
|   [[nodiscard]] auto statfs_x_impl(std::string api_path, struct statfs *stbuf) | ||||
|       -> api_error override; | ||||
| #else  // __APPLE__ | ||||
|   [[nodiscard]] auto statfs_impl(std::string api_path, struct statvfs *stbuf) | ||||
|       -> api_error override; | ||||
| #endif // __APPLE__ | ||||
|  | ||||
| #if FUSE_USE_VERSION >= 30 | ||||
|   [[nodiscard]] auto truncate_impl(std::string api_path, off_t size, | ||||
|                                    struct fuse_file_info *file_info) | ||||
|       -> api_error override; | ||||
| #else | ||||
|   [[nodiscard]] auto truncate_impl(std::string api_path, off_t size) | ||||
|       -> api_error override; | ||||
| #endif | ||||
|  | ||||
|   [[nodiscard]] auto unlink_impl(std::string api_path) -> api_error override; | ||||
|  | ||||
| #if FUSE_USE_VERSION >= 30 | ||||
|   [[nodiscard]] auto utimens_impl(std::string api_path, | ||||
|                                   const struct timespec tv[2], | ||||
|                                   struct fuse_file_info *file_info) | ||||
|       -> api_error override; | ||||
| #else | ||||
|   [[nodiscard]] auto utimens_impl(std::string api_path, | ||||
|                                   const struct timespec tv[2]) | ||||
|       -> api_error override; | ||||
| #endif | ||||
|  | ||||
|   [[nodiscard]] auto write_impl(std::string api_path, const char *buffer, | ||||
|                                 size_t write_size, off_t write_offset, | ||||
|                                 struct fuse_file_info *file_info, | ||||
|                                 std::size_t &bytes_written) | ||||
|       -> api_error override; | ||||
|  | ||||
| public: | ||||
|   [[nodiscard]] auto get_directory_item_count(const std::string &api_path) const | ||||
|       -> std::uint64_t override; | ||||
|  | ||||
|   [[nodiscard]] auto get_directory_items(const std::string &api_path) const | ||||
|       -> directory_item_list override; | ||||
|  | ||||
|   [[nodiscard]] auto get_file_size(const std::string &api_path) const | ||||
|       -> std::uint64_t override; | ||||
|  | ||||
|   [[nodiscard]] auto get_item_meta(const std::string &api_path, | ||||
|                                    api_meta_map &meta) const | ||||
|       -> api_error override; | ||||
|  | ||||
|   [[nodiscard]] auto get_item_meta(const std::string &api_path, | ||||
|                                    const std::string &name, | ||||
|                                    std::string &value) const | ||||
|       -> api_error override; | ||||
|  | ||||
|   [[nodiscard]] auto get_total_drive_space() const -> std::uint64_t override; | ||||
|  | ||||
|   [[nodiscard]] auto get_total_item_count() const -> std::uint64_t override; | ||||
|  | ||||
|   [[nodiscard]] auto get_used_drive_space() const -> std::uint64_t override; | ||||
|  | ||||
|   void get_volume_info(UINT64 &total_size, UINT64 &free_size, | ||||
|                        std::string &volume_label) const override; | ||||
|  | ||||
|   [[nodiscard]] auto is_processing(const std::string &api_path) const | ||||
|       -> bool override; | ||||
|  | ||||
|   [[nodiscard]] auto rename_directory(const std::string &from_api_path, | ||||
|                                       const std::string &to_api_path) | ||||
|       -> int override; | ||||
|  | ||||
|   [[nodiscard]] auto rename_file(const std::string &from_api_path, | ||||
|                                  const std::string &to_api_path, bool overwrite) | ||||
|       -> int override; | ||||
|  | ||||
|   void set_item_meta(const std::string &api_path, const std::string &key, | ||||
|                      const std::string &value) override; | ||||
| }; | ||||
| } // namespace repertory | ||||
|  | ||||
| #endif // _WIN32 | ||||
| #endif // INCLUDE_DRIVES_FUSE_FUSE_DRIVE_HPP_ | ||||
							
								
								
									
										143
									
								
								repertory/librepertory/include/drives/fuse/fuse_drive_base.hpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										143
									
								
								repertory/librepertory/include/drives/fuse/fuse_drive_base.hpp
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,143 @@ | ||||
| /* | ||||
|   Copyright <2018-2024> <scott.e.graves@protonmail.com> | ||||
|  | ||||
|   Permission is hereby granted, free of charge, to any person obtaining a copy | ||||
|   of this software and associated documentation files (the "Software"), to deal | ||||
|   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_BASE_HPP_ | ||||
| #define INCLUDE_DRIVES_FUSE_FUSE_DRIVE_BASE_HPP_ | ||||
| #ifndef _WIN32 | ||||
|  | ||||
| #include "drives/fuse/fuse_base.hpp" | ||||
| #include "drives/fuse/i_fuse_drive.hpp" | ||||
|  | ||||
| namespace repertory { | ||||
| class app_config; | ||||
| class i_provider; | ||||
|  | ||||
| class fuse_drive_base : public fuse_base, public i_fuse_drive { | ||||
| public: | ||||
|   explicit fuse_drive_base(app_config &config) : fuse_base(config) {} | ||||
|  | ||||
|   ~fuse_drive_base() override = default; | ||||
|  | ||||
| public: | ||||
|   fuse_drive_base(const fuse_drive_base &) = delete; | ||||
|   fuse_drive_base(fuse_drive_base &&) = delete; | ||||
|   auto operator=(const fuse_drive_base &) -> fuse_drive_base & = delete; | ||||
|   auto operator=(fuse_drive_base &&) -> fuse_drive_base & = delete; | ||||
|  | ||||
| protected: | ||||
|   [[nodiscard]] auto access_impl(std::string api_path, int mask) | ||||
|       -> api_error override; | ||||
|  | ||||
| protected: | ||||
|   [[nodiscard]] auto check_access(const std::string &api_path, int mask) const | ||||
|       -> api_error; | ||||
|  | ||||
|   [[nodiscard]] auto | ||||
|   check_and_perform(const std::string &api_path, int parent_mask, | ||||
|                     const std::function<api_error(api_meta_map &meta)> &action) | ||||
|       -> api_error; | ||||
|  | ||||
|   [[nodiscard]] auto get_current_gid() const -> gid_t; | ||||
|  | ||||
|   [[nodiscard]] auto get_current_uid() const -> uid_t; | ||||
|  | ||||
|   [[nodiscard]] auto get_effective_gid() const -> gid_t; | ||||
|  | ||||
|   [[nodiscard]] auto get_effective_uid() const -> uid_t; | ||||
|  | ||||
|   [[nodiscard]] static auto check_open_flags(int flags, int mask, | ||||
|                                              const api_error &fail_error) | ||||
|       -> api_error; | ||||
|  | ||||
|   [[nodiscard]] auto check_owner(const api_meta_map &meta) const -> api_error; | ||||
|  | ||||
|   [[nodiscard]] static auto check_readable(int flags, | ||||
|                                            const api_error &fail_error) | ||||
|       -> api_error; | ||||
|  | ||||
|   [[nodiscard]] static auto check_writeable(int flags, | ||||
|                                             const api_error &fail_error) | ||||
|       -> api_error; | ||||
|  | ||||
| #ifdef __APPLE__ | ||||
|   [[nodiscard]] static auto get_flags_from_meta(const api_meta_map &meta) | ||||
|       -> __uint32_t; | ||||
| #endif // __APPLE__ | ||||
|  | ||||
|   [[nodiscard]] static auto get_gid_from_meta(const api_meta_map &meta) | ||||
|       -> gid_t; | ||||
|  | ||||
|   [[nodiscard]] static auto get_mode_from_meta(const api_meta_map &meta) | ||||
|       -> mode_t; | ||||
|  | ||||
|   static void get_timespec_from_meta(const api_meta_map &meta, | ||||
|                                      const std::string &name, | ||||
|                                      struct timespec &ts); | ||||
|  | ||||
|   [[nodiscard]] static auto get_uid_from_meta(const api_meta_map &meta) | ||||
|       -> uid_t; | ||||
|  | ||||
| #ifdef __APPLE__ | ||||
|   [[nodiscard]] auto parse_xattr_parameters(const char *name, | ||||
|                                             const uint32_t &position, | ||||
|                                             std::string &attribute_name, | ||||
|                                             const std::string &api_path) | ||||
|       -> api_error; | ||||
| #else | ||||
|   [[nodiscard]] auto parse_xattr_parameters(const char *name, | ||||
|                                             std::string &attribute_name, | ||||
|                                             const std::string &api_path) | ||||
|       -> api_error; | ||||
| #endif | ||||
|  | ||||
| #ifdef __APPLE__ | ||||
|   [[nodiscard]] auto | ||||
|   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) -> api_error; | ||||
| #else | ||||
|   [[nodiscard]] auto parse_xattr_parameters(const char *name, const char *value, | ||||
|                                             size_t size, | ||||
|                                             std::string &attribute_name, | ||||
|                                             const std::string &api_path) | ||||
|       -> api_error; | ||||
| #endif | ||||
|  | ||||
|   static void populate_stat(const std::string &api_path, | ||||
|                             std::uint64_t size_or_count, | ||||
|                             const api_meta_map &meta, 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); | ||||
|  | ||||
| public: | ||||
|   [[nodiscard]] auto check_owner(const std::string &api_path) const | ||||
|       -> api_error override; | ||||
|  | ||||
|   [[nodiscard]] auto check_parent_access(const std::string &api_path, | ||||
|                                          int mask) const -> api_error override; | ||||
| }; | ||||
| } // namespace repertory | ||||
|  | ||||
| #endif // _WIN32 | ||||
| #endif // INCLUDE_DRIVES_FUSE_FUSE_DRIVE_BASE_HPP_ | ||||
							
								
								
									
										87
									
								
								repertory/librepertory/include/drives/fuse/i_fuse_drive.hpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										87
									
								
								repertory/librepertory/include/drives/fuse/i_fuse_drive.hpp
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,87 @@ | ||||
| /* | ||||
|   Copyright <2018-2024> <scott.e.graves@protonmail.com> | ||||
|  | ||||
|   Permission is hereby granted, free of charge, to any person obtaining a copy | ||||
|   of this software and associated documentation files (the "Software"), to deal | ||||
|   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 "types/repertory.hpp" | ||||
|  | ||||
| namespace repertory { | ||||
| class i_fuse_drive { | ||||
|   INTERFACE_SETUP(i_fuse_drive); | ||||
|  | ||||
| public: | ||||
|   [[nodiscard]] virtual auto check_owner(const std::string &api_path) const | ||||
|       -> api_error = 0; | ||||
|  | ||||
|   [[nodiscard]] virtual auto check_parent_access(const std::string &api_path, | ||||
|                                                  int mask) const | ||||
|       -> api_error = 0; | ||||
|  | ||||
|   [[nodiscard]] virtual auto | ||||
|   get_directory_item_count(const std::string &api_path) const | ||||
|       -> std::uint64_t = 0; | ||||
|  | ||||
|   [[nodiscard]] virtual auto | ||||
|   get_directory_items(const std::string &api_path) const | ||||
|       -> directory_item_list = 0; | ||||
|  | ||||
|   [[nodiscard]] virtual auto get_file_size(const std::string &api_path) const | ||||
|       -> std::uint64_t = 0; | ||||
|  | ||||
|   [[nodiscard]] virtual auto get_item_meta(const std::string &api_path, | ||||
|                                            api_meta_map &meta) const | ||||
|       -> api_error = 0; | ||||
|  | ||||
|   [[nodiscard]] virtual auto get_item_meta(const std::string &api_path, | ||||
|                                            const std::string &name, | ||||
|                                            std::string &value) const | ||||
|       -> api_error = 0; | ||||
|  | ||||
|   [[nodiscard]] virtual auto get_total_drive_space() const -> std::uint64_t = 0; | ||||
|  | ||||
|   [[nodiscard]] virtual auto get_total_item_count() const -> std::uint64_t = 0; | ||||
|  | ||||
|   [[nodiscard]] virtual auto get_used_drive_space() const -> std::uint64_t = 0; | ||||
|  | ||||
|   virtual void get_volume_info(UINT64 &total_size, UINT64 &free_size, | ||||
|                                std::string &volume_label) const = 0; | ||||
|  | ||||
|   [[nodiscard]] virtual auto is_processing(const std::string &api_path) const | ||||
|       -> bool = 0; | ||||
|  | ||||
|   [[nodiscard]] virtual auto rename_directory(const std::string &from_api_path, | ||||
|                                               const std::string &to_api_path) | ||||
|       -> int = 0; | ||||
|  | ||||
|   [[nodiscard]] virtual auto rename_file(const std::string &from_api_path, | ||||
|                                          const std::string &to_api_path, | ||||
|                                          bool overwrite) -> int = 0; | ||||
|  | ||||
|   virtual void set_item_meta(const std::string &api_path, | ||||
|                              const std::string &key, | ||||
|                              const std::string &value) = 0; | ||||
| }; | ||||
| } // namespace repertory | ||||
|  | ||||
| #endif | ||||
| #endif // INCLUDE_DRIVES_FUSE_I_FUSE_DRIVE_HPP_ | ||||
| @@ -0,0 +1,207 @@ | ||||
| /* | ||||
|   Copyright <2018-2024> <scott.e.graves@protonmail.com> | ||||
|  | ||||
|   Permission is hereby granted, free of charge, to any person obtaining a copy | ||||
|   of this software and associated documentation files (the "Software"), to deal | ||||
|   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 "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: | ||||
|   [[nodiscard]] virtual auto fuse_access(const char *path, | ||||
|                                          const std::int32_t &mask) | ||||
|       -> packet::error_type = 0; | ||||
|  | ||||
|   [[nodiscard]] virtual auto fuse_chflags(const char *path, std::uint32_t flags) | ||||
|       -> packet::error_type = 0; | ||||
|  | ||||
|   [[nodiscard]] virtual auto fuse_chmod(const char *path, | ||||
|                                         const remote::file_mode &mode) | ||||
|       -> packet::error_type = 0; | ||||
|  | ||||
|   [[nodiscard]] virtual auto fuse_chown(const char *path, | ||||
|                                         const remote::user_id &uid, | ||||
|                                         const remote::group_id &gid) | ||||
|       -> packet::error_type = 0; | ||||
|  | ||||
|   [[nodiscard]] virtual auto | ||||
|   fuse_create(const char *path, const remote::file_mode &mode, | ||||
|               const remote::open_flags &flags, remote::file_handle &handle) | ||||
|       -> packet::error_type = 0; | ||||
|   [[nodiscard]] virtual auto fuse_destroy() -> packet::error_type = 0; | ||||
|  | ||||
|   /*[[nodiscard]] 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;*/ | ||||
|  | ||||
|   [[nodiscard]] virtual auto | ||||
|   fuse_fgetattr(const char *path, remote::stat &r_stat, bool &directory, | ||||
|                 const remote::file_handle &handle) -> packet::error_type = 0; | ||||
|  | ||||
|   [[nodiscard]] virtual auto fuse_fsetattr_x(const char *path, | ||||
|                                              const remote::setattr_x &attr, | ||||
|                                              const remote::file_handle &handle) | ||||
|       -> packet::error_type = 0; | ||||
|  | ||||
|   [[nodiscard]] virtual auto fuse_fsync(const char *path, | ||||
|                                         const std::int32_t &datasync, | ||||
|                                         const remote::file_handle &handle) | ||||
|       -> packet::error_type = 0; | ||||
|  | ||||
|   [[nodiscard]] virtual auto fuse_ftruncate(const char *path, | ||||
|                                             const remote::file_offset &size, | ||||
|                                             const remote::file_handle &handle) | ||||
|       -> packet::error_type = 0; | ||||
|  | ||||
|   [[nodiscard]] virtual auto fuse_getattr(const char *path, | ||||
|                                           remote::stat &r_stat, bool &directory) | ||||
|       -> packet::error_type = 0; | ||||
|  | ||||
|   /*[[nodiscard]] virtual packet::error_type fuse_getxattr(const char *path, | ||||
|   const char *name, char *value, const remote::file_size &size) = 0; | ||||
|  | ||||
|   [[nodiscard]] virtual packet::error_type fuse_getxattrOSX(const char *path, | ||||
|   const char *name, char *value, const remote::file_size &size, std::uint32_t | ||||
|   position) = 0;*/ | ||||
|  | ||||
|   [[nodiscard]] virtual auto fuse_getxtimes(const char *path, | ||||
|                                             remote::file_time &bkuptime, | ||||
|                                             remote::file_time &crtime) | ||||
|       -> packet::error_type = 0; | ||||
|  | ||||
|   [[nodiscard]] virtual auto fuse_init() -> packet::error_type = 0; | ||||
|  | ||||
|   [[nodiscard]] /*virtual packet::error_type fuse_listxattr(const char *path, | ||||
|                    char *buffer, const remote::file_size &size) = 0;*/ | ||||
|  | ||||
|   [[nodiscard]] virtual auto | ||||
|   fuse_mkdir(const char *path, const remote::file_mode &mode) | ||||
|       -> packet::error_type = 0; | ||||
|  | ||||
|   [[nodiscard]] virtual auto fuse_open(const char *path, | ||||
|                                        const remote::open_flags &flags, | ||||
|                                        remote::file_handle &handle) | ||||
|       -> packet::error_type = 0; | ||||
|  | ||||
|   [[nodiscard]] virtual auto fuse_opendir(const char *path, | ||||
|                                           remote::file_handle &handle) | ||||
|       -> packet::error_type = 0; | ||||
|  | ||||
|   [[nodiscard]] virtual auto fuse_read(const char *path, char *buffer, | ||||
|                                        const remote::file_size &read_size, | ||||
|                                        const remote::file_offset &read_offset, | ||||
|                                        const remote::file_handle &handle) | ||||
|       -> packet::error_type = 0; | ||||
|  | ||||
|   [[nodiscard]] virtual auto | ||||
|   fuse_readdir(const char *path, const remote::file_offset &offset, | ||||
|                const remote::file_handle &handle, std::string &item_path) | ||||
|       -> packet::error_type = 0; | ||||
|  | ||||
|   [[nodiscard]] virtual auto fuse_release(const char *path, | ||||
|                                           const remote::file_handle &handle) | ||||
|       -> packet::error_type = 0; | ||||
|  | ||||
|   [[nodiscard]] virtual auto fuse_releasedir(const char *path, | ||||
|                                              const remote::file_handle &handle) | ||||
|       -> packet::error_type = 0; | ||||
|  | ||||
|   //[[nodiscard]] virtual packet::error_type fuse_removexattr(const char *path, | ||||
|   // const char *name) = | ||||
|   // 0; | ||||
|  | ||||
|   [[nodiscard]] virtual auto fuse_rename(const char *from, const char *to) | ||||
|       -> packet::error_type = 0; | ||||
|  | ||||
|   [[nodiscard]] virtual auto fuse_rmdir(const char *path) | ||||
|       -> packet::error_type = 0; | ||||
|  | ||||
|   [[nodiscard]] virtual auto fuse_setattr_x(const char *path, | ||||
|                                             remote::setattr_x &attr) | ||||
|       -> packet::error_type = 0; | ||||
|  | ||||
|   [[nodiscard]] virtual auto fuse_setbkuptime(const char *path, | ||||
|                                               const remote::file_time &bkuptime) | ||||
|       -> packet::error_type = 0; | ||||
|  | ||||
|   [[nodiscard]] virtual auto fuse_setchgtime(const char *path, | ||||
|                                              const remote::file_time &chgtime) | ||||
|       -> packet::error_type = 0; | ||||
|  | ||||
|   [[nodiscard]] virtual auto fuse_setcrtime(const char *path, | ||||
|                                             const remote::file_time &crtime) | ||||
|       -> packet::error_type = 0; | ||||
|  | ||||
|   [[nodiscard]] virtual auto fuse_setvolname(const char *volname) | ||||
|       -> packet::error_type = 0; | ||||
|  | ||||
|   /*[[nodiscard]] 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; | ||||
|   [[nodiscard]] 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, std::uint32_t position) = 0;*/ | ||||
|  | ||||
|   [[nodiscard]] virtual auto fuse_statfs(const char *path, std::uint64_t frsize, | ||||
|                                          remote::statfs &r_stat) | ||||
|       -> packet::error_type = 0; | ||||
|  | ||||
|   [[nodiscard]] virtual auto | ||||
|   fuse_statfs_x(const char *path, std::uint64_t bsize, remote::statfs_x &r_stat) | ||||
|       -> packet::error_type = 0; | ||||
|  | ||||
|   [[nodiscard]] virtual auto fuse_truncate(const char *path, | ||||
|                                            const remote::file_offset &size) | ||||
|       -> packet::error_type = 0; | ||||
|  | ||||
|   [[nodiscard]] virtual auto fuse_unlink(const char *path) | ||||
|       -> packet::error_type = 0; | ||||
|  | ||||
|   [[nodiscard]] virtual auto fuse_utimens(const char *path, | ||||
|                                           const remote::file_time *tv, | ||||
|                                           std::uint64_t op0, std::uint64_t op1) | ||||
|       -> packet::error_type = 0; | ||||
|  | ||||
|   [[nodiscard]] virtual auto fuse_write(const char *path, const char *buffer, | ||||
|                                         const remote::file_size &writeSize, | ||||
|                                         const remote::file_offset &writeOffset, | ||||
|                                         const remote::file_handle &handle) | ||||
|       -> packet::error_type = 0; | ||||
|  | ||||
|   [[nodiscard]] virtual auto fuse_write_base64( | ||||
|       const char *path, const char *buffer, const remote::file_size &writeSize, | ||||
|       const remote::file_offset &writeOffset, const remote::file_handle &handle) | ||||
|       -> packet::error_type = 0; | ||||
|  | ||||
|   virtual void set_fuse_uid_gid(const remote::user_id &uid, | ||||
|                                 const remote::group_id &gid) = 0; | ||||
| }; | ||||
|  | ||||
| using remote_instance_factory = | ||||
|     std::function<std::unique_ptr<i_remote_instance>()>; | ||||
| } // namespace repertory::remote_fuse | ||||
|  | ||||
| #endif // INCLUDE_DRIVES_FUSE_REMOTEFUSE_I_REMOTE_INSTANCE_HPP_ | ||||
| @@ -0,0 +1,226 @@ | ||||
| /* | ||||
|   Copyright <2018-2024> <scott.e.graves@protonmail.com> | ||||
|  | ||||
|   Permission is hereby granted, free of charge, to any person obtaining a copy | ||||
|   of this software and associated documentation files (the "Software"), to deal | ||||
|   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 "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: | ||||
|   [[nodiscard]] auto fuse_access(const char *path, const std::int32_t &mask) | ||||
|       -> packet::error_type override; | ||||
|  | ||||
|   [[nodiscard]] auto fuse_chflags(const char *path, std::uint32_t flags) | ||||
|       -> packet::error_type override; | ||||
|  | ||||
|   [[nodiscard]] auto fuse_chmod(const char *path, const remote::file_mode &mode) | ||||
|       -> packet::error_type override; | ||||
|  | ||||
|   [[nodiscard]] auto fuse_chown(const char *path, const remote::user_id &uid, | ||||
|                                 const remote::group_id &gid) | ||||
|       -> packet::error_type override; | ||||
|  | ||||
|   [[nodiscard]] auto fuse_destroy() -> packet::error_type override; | ||||
|  | ||||
|   [[nodiscard]] /*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 ;*/ | ||||
|  | ||||
|   [[nodiscard]] auto | ||||
|   fuse_fgetattr(const char *path, remote::stat &st, bool &directory, | ||||
|                 const remote::file_handle &handle) | ||||
|       -> packet::error_type override; | ||||
|  | ||||
|   [[nodiscard]] auto fuse_fsetattr_x(const char *path, | ||||
|                                      const remote::setattr_x &attr, | ||||
|                                      const remote::file_handle &handle) | ||||
|       -> packet::error_type override; | ||||
|  | ||||
|   [[nodiscard]] auto fuse_fsync(const char *path, const std::int32_t &datasync, | ||||
|                                 const remote::file_handle &handle) | ||||
|       -> packet::error_type override; | ||||
|  | ||||
|   [[nodiscard]] auto fuse_ftruncate(const char *path, | ||||
|                                     const remote::file_offset &size, | ||||
|                                     const remote::file_handle &handle) | ||||
|       -> packet::error_type override; | ||||
|  | ||||
|   [[nodiscard]] auto fuse_getattr(const char *path, remote::stat &st, | ||||
|                                   bool &directory) | ||||
|       -> packet::error_type override; | ||||
|  | ||||
|   /*[[nodiscard]] packet::error_type fuse_getxattr(const char *path, const char | ||||
|   *name, char *value, const remote::file_size &size) override ; | ||||
|  | ||||
|   [[nodiscard]] packet::error_type fuse_getxattrOSX(const char *path, const char | ||||
|   *name, char *value, const remote::file_size &size, std::uint32_t position) | ||||
|   override ;*/ | ||||
|  | ||||
|   [[nodiscard]] auto fuse_getxtimes(const char *path, | ||||
|                                     remote::file_time &bkuptime, | ||||
|                                     remote::file_time &crtime) | ||||
|       -> packet::error_type override; | ||||
|  | ||||
|   [[nodiscard]] auto fuse_init() -> packet::error_type override; | ||||
|  | ||||
|   /*[[nodiscard]] packet::error_type fuse_listxattr(const char *path, char | ||||
|    *buffer, const remote::file_size &size) override ;*/ | ||||
|  | ||||
|   [[nodiscard]] auto fuse_mkdir(const char *path, const remote::file_mode &mode) | ||||
|       -> packet::error_type override; | ||||
|  | ||||
|   [[nodiscard]] auto fuse_opendir(const char *path, remote::file_handle &handle) | ||||
|       -> packet::error_type override; | ||||
|  | ||||
|   [[nodiscard]] auto | ||||
|   fuse_create(const char *path, const remote::file_mode &mode, | ||||
|               const remote::open_flags &flags, remote::file_handle &handle) | ||||
|       -> packet::error_type override; | ||||
|  | ||||
|   [[nodiscard]] auto fuse_open(const char *path, | ||||
|                                const remote::open_flags &flags, | ||||
|                                remote::file_handle &handle) | ||||
|       -> packet::error_type override; | ||||
|  | ||||
|   [[nodiscard]] auto fuse_read(const char *path, char *buffer, | ||||
|                                const remote::file_size &read_size, | ||||
|                                const remote::file_offset &read_offset, | ||||
|                                const remote::file_handle &handle) | ||||
|       -> packet::error_type override; | ||||
|  | ||||
|   [[nodiscard]] auto fuse_rename(const char *from, const char *to) | ||||
|       -> packet::error_type override; | ||||
|  | ||||
|   [[nodiscard]] auto | ||||
|   fuse_readdir(const char *path, const remote::file_offset &offset, | ||||
|                const remote::file_handle &handle, std::string &item_path) | ||||
|       -> packet::error_type override; | ||||
|  | ||||
|   [[nodiscard]] auto fuse_release(const char *path, | ||||
|                                   const remote::file_handle &handle) | ||||
|       -> packet::error_type override; | ||||
|  | ||||
|   [[nodiscard]] auto fuse_releasedir(const char *path, | ||||
|                                      const remote::file_handle &handle) | ||||
|       -> packet::error_type override; | ||||
|  | ||||
|   /*[[nodiscard]] packet::error_type fuse_removexattr(const char *path, const | ||||
|    * char *name) override | ||||
|    * ;*/ | ||||
|  | ||||
|   [[nodiscard]] auto fuse_rmdir(const char *path) | ||||
|       -> packet::error_type override; | ||||
|  | ||||
|   [[nodiscard]] auto fuse_setattr_x(const char *path, remote::setattr_x &attr) | ||||
|       -> packet::error_type override; | ||||
|  | ||||
|   [[nodiscard]] auto fuse_setbkuptime(const char *path, | ||||
|                                       const remote::file_time &bkuptime) | ||||
|       -> packet::error_type override; | ||||
|  | ||||
|   [[nodiscard]] auto fuse_setchgtime(const char *path, | ||||
|                                      const remote::file_time &chgtime) | ||||
|       -> packet::error_type override; | ||||
|  | ||||
|   [[nodiscard]] auto fuse_setcrtime(const char *path, | ||||
|                                     const remote::file_time &crtime) | ||||
|       -> packet::error_type override; | ||||
|  | ||||
|   [[nodiscard]] auto fuse_setvolname(const char *volname) | ||||
|       -> packet::error_type override; | ||||
|  | ||||
|   [[nodiscard]] /*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 ; | ||||
|  | ||||
|   [[nodiscard]] 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, std::uint32_t position) override ;*/ | ||||
|  | ||||
|   [[nodiscard]] auto | ||||
|   fuse_statfs(const char *path, std::uint64_t frsize, remote::statfs &st) | ||||
|       -> packet::error_type override; | ||||
|  | ||||
|   [[nodiscard]] auto fuse_statfs_x(const char *path, std::uint64_t bsize, | ||||
|                                    remote::statfs_x &st) | ||||
|       -> packet::error_type override; | ||||
|  | ||||
|   [[nodiscard]] auto fuse_truncate(const char *path, | ||||
|                                    const remote::file_offset &size) | ||||
|       -> packet::error_type override; | ||||
|  | ||||
|   [[nodiscard]] auto fuse_unlink(const char *path) | ||||
|       -> packet::error_type override; | ||||
|  | ||||
|   [[nodiscard]] auto fuse_utimens(const char *path, const remote::file_time *tv, | ||||
|                                   std::uint64_t op0, std::uint64_t op1) | ||||
|       -> packet::error_type override; | ||||
|  | ||||
|   [[nodiscard]] auto 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) | ||||
|       -> packet::error_type override; | ||||
|  | ||||
|   [[nodiscard]] auto 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) | ||||
|       -> packet::error_type override; | ||||
|  | ||||
|   [[nodiscard]] auto json_create_directory_snapshot(const std::string &path, | ||||
|                                                     json &json_data) | ||||
|       -> packet::error_type override; | ||||
|  | ||||
|   [[nodiscard]] auto json_read_directory_snapshot( | ||||
|       const std::string &path, const remote::file_handle &handle, | ||||
|       std::uint32_t page, json &json_data) -> packet::error_type override; | ||||
|  | ||||
|   [[nodiscard]] auto | ||||
|   json_release_directory_snapshot(const std::string &path, | ||||
|                                   const remote::file_handle &handle) | ||||
|       -> packet::error_type 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_ | ||||
| @@ -0,0 +1,246 @@ | ||||
| /* | ||||
|   Copyright <2018-2024> <scott.e.graves@protonmail.com> | ||||
|  | ||||
|   Permission is hereby granted, free of charge, to any person obtaining a copy | ||||
|   of this software and associated documentation files (the "Software"), to deal | ||||
|   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 "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 remote_fuse { | ||||
| class remote_fuse_drive final : public fuse_base { | ||||
| public: | ||||
|   remote_fuse_drive(app_config &config, remote_instance_factory factory, | ||||
|                     lock_data &lock) | ||||
|       : fuse_base(config), factory_(std::move(factory)), lock_data_(lock) {} | ||||
|  | ||||
|   ~remote_fuse_drive() override = default; | ||||
|  | ||||
| private: | ||||
|   remote_instance_factory factory_; | ||||
|   lock_data &lock_data_; | ||||
|   std::shared_ptr<console_consumer> console_consumer_; | ||||
|   std::shared_ptr<logging_consumer> logging_consumer_; | ||||
|   std::shared_ptr<i_remote_instance> remote_instance_; | ||||
|   std::shared_ptr<server> server_; | ||||
|   bool was_mounted_ = false; | ||||
|  | ||||
| private: | ||||
|   void populate_stat(const remote::stat &r_stat, bool directory, | ||||
|                      struct stat &unix_st); | ||||
|  | ||||
| protected: | ||||
|   [[nodiscard]] auto access_impl(std::string api_path, int mask) | ||||
|       -> api_error override; | ||||
|  | ||||
| #ifdef __APPLE__ | ||||
|   [[nodiscard]] auto chflags_impl(std::string api_path, uint32_t flags) | ||||
|       -> api_error override; | ||||
| #endif // __APPLE__ | ||||
|  | ||||
| #if FUSE_USE_VERSION >= 30 | ||||
|   [[nodiscard]] auto chmod_impl(std::string api_path, mode_t mode, | ||||
|                                 struct fuse_file_info *f_info) | ||||
|       -> api_error override; | ||||
| #else | ||||
|   [[nodiscard]] auto chmod_impl(std::string api_path, mode_t mode) | ||||
|       -> api_error override; | ||||
| #endif | ||||
|  | ||||
| #if FUSE_USE_VERSION >= 30 | ||||
|   [[nodiscard]] auto chown_impl(std::string api_path, uid_t uid, gid_t gid, | ||||
|                                 struct fuse_file_info *f_info) | ||||
|       -> api_error override; | ||||
| #else | ||||
|   [[nodiscard]] auto chown_impl(std::string api_path, uid_t uid, gid_t gid) | ||||
|       -> api_error override; | ||||
| #endif | ||||
|  | ||||
|   [[nodiscard]] auto create_impl(std::string api_path, mode_t mode, | ||||
|                                  struct fuse_file_info *f_info) | ||||
|       -> api_error override; | ||||
|  | ||||
|   void destroy_impl(void * /*ptr*/) override; | ||||
|  | ||||
|   [[nodiscard]] auto fgetattr_impl(std::string api_path, struct stat *unix_st, | ||||
|                                    struct fuse_file_info *f_info) | ||||
|       -> api_error override; | ||||
|  | ||||
| #ifdef __APPLE__ | ||||
|   [[nodiscard]] auto fsetattr_x_impl(std::string api_path, | ||||
|                                      struct setattr_x *attr, | ||||
|                                      struct fuse_file_info *f_info) | ||||
|       -> api_error override; | ||||
| #endif // __APPLE__ | ||||
|  | ||||
|   [[nodiscard]] auto fsync_impl(std::string api_path, int datasync, | ||||
|                                 struct fuse_file_info *f_info) | ||||
|       -> api_error override; | ||||
|  | ||||
| #if FUSE_USE_VERSION < 30 | ||||
|   [[nodiscard]] auto ftruncate_impl(std::string api_path, off_t size, | ||||
|                                     struct fuse_file_info *f_info) | ||||
|       -> api_error override; | ||||
| #endif | ||||
|  | ||||
| #if FUSE_USE_VERSION >= 30 | ||||
|   [[nodiscard]] auto getattr_impl(std::string api_path, struct stat *unix_st, | ||||
|                                   struct fuse_file_info *f_info) | ||||
|       -> api_error override; | ||||
| #else | ||||
|   [[nodiscard]] auto getattr_impl(std::string api_path, struct stat *unix_st) | ||||
|       -> api_error override; | ||||
| #endif | ||||
|  | ||||
| #ifdef __APPLE__ | ||||
|   [[nodiscard]] auto getxtimes_impl(std::string api_path, | ||||
|                                     struct timespec *bkuptime, | ||||
|                                     struct timespec *crtime) | ||||
|       -> api_error override; | ||||
| #endif // __APPLE__ | ||||
|  | ||||
| #if FUSE_USE_VERSION >= 30 | ||||
|   auto init_impl(struct fuse_conn_info *conn, struct fuse_config *cfg) | ||||
|       -> void * override; | ||||
| #else | ||||
|   auto init_impl(struct fuse_conn_info *conn) -> void * override; | ||||
| #endif | ||||
|  | ||||
|   [[nodiscard]] auto mkdir_impl(std::string api_path, mode_t mode) | ||||
|       -> api_error override; | ||||
|  | ||||
|   void notify_fuse_main_exit(int &ret) override; | ||||
|  | ||||
|   [[nodiscard]] auto open_impl(std::string api_path, | ||||
|                                struct fuse_file_info *f_info) | ||||
|       -> api_error override; | ||||
|  | ||||
|   [[nodiscard]] auto opendir_impl(std::string api_path, | ||||
|                                   struct fuse_file_info *f_info) | ||||
|       -> api_error override; | ||||
|  | ||||
|   [[nodiscard]] auto read_impl(std::string api_path, char *buffer, | ||||
|                                size_t read_size, off_t read_offset, | ||||
|                                struct fuse_file_info *f_info, | ||||
|                                std::size_t &bytes_read) -> api_error override; | ||||
|  | ||||
| #if FUSE_USE_VERSION >= 30 | ||||
|   [[nodiscard]] auto readdir_impl(std::string api_path, void *buf, | ||||
|                                   fuse_fill_dir_t fuse_fill_dir, off_t offset, | ||||
|                                   struct fuse_file_info *f_info, | ||||
|                                   fuse_readdir_flags flags) | ||||
|       -> api_error override; | ||||
| #else | ||||
|   [[nodiscard]] auto readdir_impl(std::string api_path, void *buf, | ||||
|                                   fuse_fill_dir_t fuse_fill_dir, off_t offset, | ||||
|                                   struct fuse_file_info *f_info) | ||||
|       -> api_error override; | ||||
| #endif | ||||
|  | ||||
|   [[nodiscard]] auto release_impl(std::string api_path, | ||||
|                                   struct fuse_file_info *f_info) | ||||
|       -> api_error override; | ||||
|  | ||||
|   [[nodiscard]] auto releasedir_impl(std::string api_path, | ||||
|                                      struct fuse_file_info *f_info) | ||||
|       -> api_error override; | ||||
|  | ||||
| #if FUSE_USE_VERSION >= 30 | ||||
|   [[nodiscard]] auto rename_impl(std::string from_api_path, | ||||
|                                  std::string to_api_path, unsigned int flags) | ||||
|       -> api_error override; | ||||
| #else | ||||
|   [[nodiscard]] auto rename_impl(std::string from_api_path, | ||||
|                                  std::string to_api_path) -> api_error override; | ||||
| #endif | ||||
|  | ||||
|   [[nodiscard]] auto rmdir_impl(std::string api_path) -> api_error override; | ||||
|  | ||||
| #ifdef __APPLE__ | ||||
|   [[nodiscard]] auto setattr_x_impl(std::string api_path, | ||||
|                                     struct setattr_x *attr) | ||||
|       -> api_error override; | ||||
|  | ||||
|   [[nodiscard]] auto setbkuptime_impl(std::string api_path, | ||||
|                                       const struct timespec *bkuptime) | ||||
|       -> api_error override; | ||||
|  | ||||
|   [[nodiscard]] auto setchgtime_impl(std::string api_path, | ||||
|                                      const struct timespec *chgtime) | ||||
|       -> api_error override; | ||||
|  | ||||
|   [[nodiscard]] auto setcrtime_impl(std::string api_path, | ||||
|                                     const struct timespec *crtime) | ||||
|       -> api_error override; | ||||
|  | ||||
|   [[nodiscard]] virtual auto setvolname_impl(const char *volname) | ||||
|       -> api_error override; | ||||
|  | ||||
|   [[nodiscard]] auto statfs_x_impl(std::string api_path, struct statfs *stbuf) | ||||
|       -> api_error override; | ||||
|  | ||||
| #else  // __APPLE__ | ||||
|   [[nodiscard]] auto statfs_impl(std::string api_path, struct statvfs *stbuf) | ||||
|       -> api_error override; | ||||
| #endif // __APPLE__ | ||||
|  | ||||
| #if FUSE_USE_VERSION >= 30 | ||||
|   [[nodiscard]] auto truncate_impl(std::string api_path, off_t size, | ||||
|                                    struct fuse_file_info *f_info) | ||||
|       -> api_error override; | ||||
| #else | ||||
|   [[nodiscard]] auto truncate_impl(std::string api_path, off_t size) | ||||
|       -> api_error override; | ||||
| #endif | ||||
|  | ||||
|   [[nodiscard]] auto unlink_impl(std::string api_path) -> api_error override; | ||||
|  | ||||
| #if FUSE_USE_VERSION >= 30 | ||||
|   [[nodiscard]] auto utimens_impl(std::string api_path, | ||||
|                                   const struct timespec tv[2], | ||||
|                                   struct fuse_file_info *f_info) | ||||
|       -> api_error override; | ||||
| #else | ||||
|   [[nodiscard]] auto utimens_impl(std::string api_path, | ||||
|                                   const struct timespec tv[2]) | ||||
|       -> api_error override; | ||||
| #endif | ||||
|  | ||||
|   [[nodiscard]] auto write_impl(std::string api_path, const char *buffer, | ||||
|                                 size_t write_size, off_t write_offset, | ||||
|                                 struct fuse_file_info *f_info, | ||||
|                                 std::size_t &bytes_written) | ||||
|       -> api_error override; | ||||
| }; | ||||
| } // namespace remote_fuse | ||||
| } // namespace repertory | ||||
|  | ||||
| #endif // _WIN32 | ||||
| #endif // INCLUDE_DRIVES_FUSE_REMOTEFUSE_REMOTE_FUSE_DRIVE_HPP_ | ||||
| @@ -0,0 +1,338 @@ | ||||
| /* | ||||
|   Copyright <2018-2024> <scott.e.graves@protonmail.com> | ||||
|  | ||||
|   Permission is hereby granted, free of charge, to any person obtaining a copy | ||||
|   of this software and associated documentation files (the "Software"), to deal | ||||
|   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 "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: | ||||
|   [[nodiscard]] auto construct_path(std::string path) -> std::string; | ||||
|  | ||||
|   [[nodiscard]] auto construct_path(const std::wstring &path) -> std::string; | ||||
|  | ||||
|   [[nodiscard]] static auto empty_as_zero(const json &data) -> std::string; | ||||
|  | ||||
|   [[nodiscard]] auto populate_file_info(const std::string &api_path, | ||||
|                                         remote::file_info &file_info) | ||||
|       -> packet::error_type; | ||||
|  | ||||
|   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 stat64 &unix_st, remote::stat &r_stat); | ||||
|  | ||||
|   [[nodiscard]] auto update_to_windows_format(json &item) -> json &; | ||||
|  | ||||
| protected: | ||||
|   void delete_open_directory(void *dir) override; | ||||
|  | ||||
| public: | ||||
|   // FUSE Layer | ||||
|   [[nodiscard]] auto fuse_access(const char *path, const std::int32_t &mask) | ||||
|       -> packet::error_type override; | ||||
|  | ||||
|   [[nodiscard]] auto fuse_chflags(const char *path, std::uint32_t flags) | ||||
|       -> packet::error_type override; | ||||
|  | ||||
|   [[nodiscard]] auto fuse_chmod(const char *path, const remote::file_mode &mode) | ||||
|       -> packet::error_type override; | ||||
|  | ||||
|   [[nodiscard]] auto fuse_chown(const char *path, const remote::user_id &uid, | ||||
|                                 const remote::group_id &gid) | ||||
|       -> packet::error_type override; | ||||
|  | ||||
|   [[nodiscard]] auto | ||||
|   fuse_create(const char *path, const remote::file_mode &mode, | ||||
|               const remote::open_flags &flags, remote::file_handle &handle) | ||||
|       -> packet::error_type override; | ||||
|  | ||||
|   [[nodiscard]] auto fuse_destroy() -> packet::error_type override; | ||||
|  | ||||
|   /*[[nodiscard]] 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 | ||||
|      ;*/ | ||||
|  | ||||
|   [[nodiscard]] auto fuse_fgetattr(const char *path, remote::stat &r_stat, | ||||
|                                    bool &directory, | ||||
|                                    const remote::file_handle &handle) | ||||
|       -> packet::error_type override; | ||||
|  | ||||
|   [[nodiscard]] auto fuse_fsetattr_x(const char *path, | ||||
|                                      const remote::setattr_x &attr, | ||||
|                                      const remote::file_handle &handle) | ||||
|       -> packet::error_type override; | ||||
|  | ||||
|   [[nodiscard]] auto fuse_fsync(const char *path, const std::int32_t &datasync, | ||||
|                                 const remote::file_handle &handle) | ||||
|       -> packet::error_type override; | ||||
|  | ||||
|   [[nodiscard]] auto fuse_ftruncate(const char *path, | ||||
|                                     const remote::file_offset &size, | ||||
|                                     const remote::file_handle &handle) | ||||
|       -> packet::error_type override; | ||||
|  | ||||
|   [[nodiscard]] auto fuse_getattr(const char *path, remote::stat &r_stat, | ||||
|                                   bool &directory) | ||||
|       -> packet::error_type override; | ||||
|  | ||||
|   /*[[nodiscard]] packet::error_type fuse_getxattr(const char *path, const char | ||||
|   *name, char *value, const remote::file_size &size) override ; | ||||
|  | ||||
|   [[nodiscard]] packet::error_type fuse_getxattrOSX(const char *path, const char | ||||
|   *name, char *value, const remote::file_size &size, std::uint32_t position) | ||||
|   override ;*/ | ||||
|  | ||||
|   [[nodiscard]] auto fuse_getxtimes(const char *path, | ||||
|                                     remote::file_time &bkuptime, | ||||
|                                     remote::file_time &crtime) | ||||
|       -> packet::error_type override; | ||||
|  | ||||
|   [[nodiscard]] auto fuse_init() -> packet::error_type override; | ||||
|  | ||||
|   [[nodiscard]] /*packet::error_type fuse_listxattr(const char *path, char | ||||
|                  *buffer, const remote::file_size &size) override ;*/ | ||||
|  | ||||
|   [[nodiscard]] auto | ||||
|   fuse_mkdir(const char *path, const remote::file_mode &mode) | ||||
|       -> packet::error_type override; | ||||
|  | ||||
|   [[nodiscard]] auto fuse_open(const char *path, | ||||
|                                const remote::open_flags &flags, | ||||
|                                remote::file_handle &handle) | ||||
|       -> packet::error_type override; | ||||
|  | ||||
|   [[nodiscard]] auto fuse_opendir(const char *path, remote::file_handle &handle) | ||||
|       -> packet::error_type override; | ||||
|  | ||||
|   [[nodiscard]] auto fuse_read(const char *path, char *buffer, | ||||
|                                const remote::file_size &read_size, | ||||
|                                const remote::file_offset &read_offset, | ||||
|                                const remote::file_handle &handle) | ||||
|       -> packet::error_type override; | ||||
|  | ||||
|   [[nodiscard]] auto fuse_rename(const char *from, const char *to) | ||||
|       -> packet::error_type override; | ||||
|  | ||||
|   [[nodiscard]] auto | ||||
|   fuse_readdir(const char *path, const remote::file_offset &offset, | ||||
|                const remote::file_handle &handle, std::string &item_path) | ||||
|       -> packet::error_type override; | ||||
|  | ||||
|   [[nodiscard]] auto fuse_release(const char *path, | ||||
|                                   const remote::file_handle &handle) | ||||
|       -> packet::error_type override; | ||||
|  | ||||
|   [[nodiscard]] auto fuse_releasedir(const char *path, | ||||
|                                      const remote::file_handle &handle) | ||||
|       -> packet::error_type override; | ||||
|  | ||||
|   /*[[nodiscard]] packet::error_type fuse_removexattr(const char *path, const | ||||
|    * char *name) override | ||||
|    * ;*/ | ||||
|  | ||||
|   [[nodiscard]] auto fuse_rmdir(const char *path) | ||||
|       -> packet::error_type override; | ||||
|  | ||||
|   [[nodiscard]] auto fuse_setattr_x(const char *path, remote::setattr_x &attr) | ||||
|       -> packet::error_type override; | ||||
|  | ||||
|   [[nodiscard]] auto fuse_setbkuptime(const char *path, | ||||
|                                       const remote::file_time &bkuptime) | ||||
|       -> packet::error_type override; | ||||
|  | ||||
|   [[nodiscard]] auto fuse_setchgtime(const char *path, | ||||
|                                      const remote::file_time &chgtime) | ||||
|       -> packet::error_type override; | ||||
|  | ||||
|   [[nodiscard]] auto fuse_setcrtime(const char *path, | ||||
|                                     const remote::file_time &crtime) | ||||
|       -> packet::error_type override; | ||||
|  | ||||
|   [[nodiscard]] auto fuse_setvolname(const char *volname) | ||||
|       -> packet::error_type override; | ||||
|  | ||||
|   /*[[nodiscard]] 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 ; | ||||
|  | ||||
|   [[nodiscard]] 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, std::uint32_t position) override ;*/ | ||||
|  | ||||
|   [[nodiscard]] auto fuse_statfs(const char *path, std::uint64_t frsize, | ||||
|                                  remote::statfs &r_stat) | ||||
|       -> packet::error_type override; | ||||
|  | ||||
|   [[nodiscard]] auto fuse_statfs_x(const char *path, std::uint64_t bsize, | ||||
|                                    remote::statfs_x &r_stat) | ||||
|       -> packet::error_type override; | ||||
|  | ||||
|   [[nodiscard]] auto fuse_truncate(const char *path, | ||||
|                                    const remote::file_offset &size) | ||||
|       -> packet::error_type override; | ||||
|  | ||||
|   [[nodiscard]] auto fuse_unlink(const char *path) | ||||
|       -> packet::error_type override; | ||||
|  | ||||
|   [[nodiscard]] auto fuse_utimens(const char *path, const remote::file_time *tv, | ||||
|                                   std::uint64_t op0, std::uint64_t op1) | ||||
|       -> packet::error_type override; | ||||
|  | ||||
|   [[nodiscard]] auto 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) | ||||
|       -> packet::error_type override; | ||||
|  | ||||
|   [[nodiscard]] auto 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) | ||||
|       -> packet::error_type override; | ||||
|  | ||||
|   void set_fuse_uid_gid(const remote::user_id &, | ||||
|                         const remote::group_id &) override {} | ||||
|  | ||||
|   // JSON Layer | ||||
|   [[nodiscard]] auto winfsp_get_dir_buffer(PVOID /*file_desc*/, | ||||
|                                            PVOID *& /*ptr*/) | ||||
|       -> packet::error_type override { | ||||
|     return STATUS_INVALID_HANDLE; | ||||
|   } | ||||
|  | ||||
|   [[nodiscard]] auto json_create_directory_snapshot(const std::string &path, | ||||
|                                                     json &json_data) | ||||
|       -> packet::error_type override; | ||||
|  | ||||
|   [[nodiscard]] auto json_read_directory_snapshot( | ||||
|       const std::string &path, const remote::file_handle &handle, | ||||
|       std::uint32_t page, json &json_data) -> packet::error_type override; | ||||
|  | ||||
|   [[nodiscard]] auto | ||||
|   json_release_directory_snapshot(const std::string &path, | ||||
|                                   const remote::file_handle &handle) | ||||
|       -> packet::error_type override; | ||||
|  | ||||
|   // WinFSP Layer | ||||
|   [[nodiscard]] auto winfsp_can_delete(PVOID file_desc, PWSTR file_name) | ||||
|       -> packet::error_type override; | ||||
|  | ||||
|   [[nodiscard]] auto winfsp_cleanup(PVOID file_desc, PWSTR file_name, | ||||
|                                     UINT32 flags, BOOLEAN &was_closed) | ||||
|       -> packet::error_type override; | ||||
|  | ||||
|   [[nodiscard]] auto winfsp_close(PVOID file_desc) | ||||
|       -> packet::error_type override; | ||||
|  | ||||
|   [[nodiscard]] auto | ||||
|   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) -> packet::error_type override; | ||||
|  | ||||
|   [[nodiscard]] auto winfsp_flush(PVOID file_desc, remote::file_info *file_info) | ||||
|       -> packet::error_type override; | ||||
|  | ||||
|   [[nodiscard]] auto winfsp_get_file_info(PVOID file_desc, | ||||
|                                           remote::file_info *file_info) | ||||
|       -> packet::error_type override; | ||||
|  | ||||
|   [[nodiscard]] auto | ||||
|   winfsp_get_security_by_name(PWSTR file_name, PUINT32 attributes, | ||||
|                               std::uint64_t * /*security_descriptor_size*/, | ||||
|                               std::wstring & /*str_descriptor*/) | ||||
|       -> packet::error_type override; | ||||
|  | ||||
|   [[nodiscard]] auto winfsp_get_volume_info(UINT64 &total_size, | ||||
|                                             UINT64 &free_size, | ||||
|                                             std::string &volume_label) | ||||
|       -> packet::error_type override; | ||||
|  | ||||
|   [[nodiscard]] auto winfsp_mounted(const std::wstring &location) | ||||
|       -> packet::error_type override; | ||||
|  | ||||
|   [[nodiscard]] auto winfsp_open(PWSTR file_name, UINT32 create_options, | ||||
|                                  UINT32 granted_access, PVOID *file_desc, | ||||
|                                  remote::file_info *file_info, | ||||
|                                  std::string &normalized_name) | ||||
|       -> packet::error_type override; | ||||
|  | ||||
|   [[nodiscard]] auto winfsp_overwrite(PVOID file_desc, UINT32 attributes, | ||||
|                                       BOOLEAN replace_attributes, | ||||
|                                       UINT64 /*allocation_size*/, | ||||
|                                       remote::file_info *file_info) | ||||
|       -> packet::error_type override; | ||||
|  | ||||
|   [[nodiscard]] auto winfsp_read(PVOID file_desc, PVOID buffer, UINT64 offset, | ||||
|                                  UINT32 length, PUINT32 bytes_transferred) | ||||
|       -> packet::error_type override; | ||||
|  | ||||
|   [[nodiscard]] auto winfsp_read_directory(PVOID file_desc, PWSTR /*pattern*/, | ||||
|                                            PWSTR marker, json &itemList) | ||||
|       -> packet::error_type override; | ||||
|  | ||||
|   [[nodiscard]] auto winfsp_rename(PVOID /*file_desc*/, PWSTR file_name, | ||||
|                                    PWSTR new_file_name, | ||||
|                                    BOOLEAN replace_if_exists) | ||||
|       -> packet::error_type override; | ||||
|  | ||||
|   [[nodiscard]] auto winfsp_set_basic_info( | ||||
|       PVOID file_desc, UINT32 attributes, UINT64 creation_time, | ||||
|       UINT64 last_access_time, UINT64 last_write_time, UINT64 change_time, | ||||
|       remote::file_info *file_info) -> packet::error_type override; | ||||
|  | ||||
|   [[nodiscard]] auto winfsp_set_file_size(PVOID file_desc, UINT64 new_size, | ||||
|                                           BOOLEAN set_allocation_size, | ||||
|                                           remote::file_info *file_info) | ||||
|       -> packet::error_type override; | ||||
|  | ||||
|   [[nodiscard]] auto winfsp_unmounted(const std::wstring &location) | ||||
|       -> packet::error_type override; | ||||
|  | ||||
|   [[nodiscard]] auto | ||||
|   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) | ||||
|       -> packet::error_type override; | ||||
| }; | ||||
| } // namespace remote_fuse | ||||
| } // namespace repertory | ||||
|  | ||||
| #endif | ||||
| #endif // INCLUDE_DRIVES_FUSE_REMOTEFUSE_REMOTE_SERVER_HPP_ | ||||
| @@ -0,0 +1,47 @@ | ||||
| /* | ||||
|   Copyright <2018-2024> <scott.e.graves@protonmail.com> | ||||
|  | ||||
|   Permission is hereby granted, free of charge, to any person obtaining a copy | ||||
|   of this software and associated documentation files (the "Software"), to deal | ||||
|   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_REMOTE_JSON_HPP_ | ||||
| #define INCLUDE_DRIVES_REMOTE_I_REMOTE_JSON_HPP_ | ||||
|  | ||||
| #include "comm/packet/packet.hpp" | ||||
|  | ||||
| namespace repertory { | ||||
| class i_remote_json { | ||||
|   INTERFACE_SETUP(i_remote_json); | ||||
|  | ||||
| public: | ||||
|   [[nodiscard]] virtual auto | ||||
|   json_create_directory_snapshot(const std::string &path, json &json_data) | ||||
|       -> packet::error_type = 0; | ||||
|  | ||||
|   [[nodiscard]] virtual auto json_read_directory_snapshot( | ||||
|       const std::string &path, const remote::file_handle &handle, | ||||
|       std::uint32_t page, json &json_data) -> packet::error_type = 0; | ||||
|  | ||||
|   [[nodiscard]] virtual auto | ||||
|   json_release_directory_snapshot(const std::string &path, | ||||
|                                   const remote::file_handle &handle) | ||||
|       -> packet::error_type = 0; | ||||
| }; | ||||
| } // namespace repertory | ||||
|  | ||||
| #endif // INCLUDE_DRIVES_REMOTE_I_REMOTE_JSON_HPP_ | ||||
| @@ -0,0 +1,114 @@ | ||||
| /* | ||||
|   Copyright <2018-2024> <scott.e.graves@protonmail.com> | ||||
|  | ||||
|   Permission is hereby granted, free of charge, to any person obtaining a copy | ||||
|   of this software and associated documentation files (the "Software"), to deal | ||||
|   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 "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 = ""; | ||||
|     std::string path; | ||||
|   }; | ||||
|  | ||||
|   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::recursive_mutex compat_mutex_; | ||||
|   std::unordered_map<std::string, std::vector<void *>> directory_lookup_; | ||||
|   std::recursive_mutex directory_mutex_; | ||||
|   std::unordered_map<native_handle, open_info> file_lookup_; | ||||
|   mutable std::recursive_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 | ||||
|   [[nodiscard]] auto get_directory_buffer(const native_handle &handle, | ||||
|                                           PVOID *&buffer) -> bool; | ||||
| #endif // _WIN32 | ||||
|  | ||||
|   [[nodiscard]] auto get_open_file_path(const native_handle &handle) | ||||
|       -> std::string; | ||||
|  | ||||
|   [[nodiscard]] auto get_open_info(const native_handle &handle, open_info &oi) | ||||
|       -> bool; | ||||
|  | ||||
|   [[nodiscard]] auto has_open_directory(const std::string &client_id, void *dir) | ||||
|       -> bool; | ||||
|  | ||||
|   [[nodiscard]] auto has_compat_open_info(const remote::file_handle &handle, | ||||
|                                           int error_return) -> int; | ||||
|  | ||||
|   template <typename error_type> | ||||
|   [[nodiscard]] auto has_open_info(const native_handle &handle, | ||||
|                                    const error_type &error_return) | ||||
|       -> error_type { | ||||
|     recur_mutex_lock file_lock(file_mutex_); | ||||
|     return ((file_lookup_.find(handle) == file_lookup_.end()) ? error_return | ||||
|                                                               : 0); | ||||
|   } | ||||
|  | ||||
|   void remove_all(const std::string &file_path); | ||||
|  | ||||
|   void remove_compat_open_info(const remote::file_handle &handle); | ||||
|  | ||||
|   auto remove_directory(const std::string &client_id, void *dir) -> bool; | ||||
|  | ||||
|   void remove_open_info(const native_handle &handle); | ||||
|  | ||||
|   void set_client_id(const native_handle &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, | ||||
|                             const std::string &file_path); | ||||
|  | ||||
|   void set_open_info(const native_handle &handle, open_info oi); | ||||
|  | ||||
| public: | ||||
|   [[nodiscard]] auto get_open_file_count(const std::string &file_path) const | ||||
|       -> std::size_t; | ||||
| }; | ||||
| } // namespace repertory | ||||
|  | ||||
| #endif // INCLUDE_DRIVES_REMOTE_REMOTE_OPEN_FILE_TABLE_HPP_ | ||||
							
								
								
									
										1442
									
								
								repertory/librepertory/include/drives/remote/remote_server_base.hpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										1442
									
								
								repertory/librepertory/include/drives/remote/remote_server_base.hpp
									
									
									
									
									
										Normal file
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							| @@ -0,0 +1,75 @@ | ||||
| /* | ||||
|   Copyright <2018-2024> <scott.e.graves@protonmail.com> | ||||
|  | ||||
|   Permission is hereby granted, free of charge, to any person obtaining a copy | ||||
|   of this software and associated documentation files (the "Software"), to deal | ||||
|   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 "types/remote.hpp" | ||||
| #include "types/repertory.hpp" | ||||
|  | ||||
| namespace repertory { | ||||
| class i_winfsp_drive { | ||||
|   INTERFACE_SETUP(i_winfsp_drive); | ||||
|  | ||||
| public: | ||||
|   [[nodiscard]] virtual auto | ||||
|   get_directory_item_count(const std::string &api_path) const | ||||
|       -> std::uint64_t = 0; | ||||
|  | ||||
|   [[nodiscard]] virtual auto | ||||
|   get_directory_items(const std::string &api_path) const | ||||
|       -> directory_item_list = 0; | ||||
|  | ||||
|   [[nodiscard]] virtual auto get_file_size(const std::string &api_path) const | ||||
|       -> std::uint64_t = 0; | ||||
|  | ||||
|   [[nodiscard]] virtual auto get_item_meta(const std::string &api_path, | ||||
|                                            const std::string &name, | ||||
|                                            std::string &value) const | ||||
|       -> api_error = 0; | ||||
|  | ||||
|   [[nodiscard]] virtual auto get_item_meta(const std::string &api_path, | ||||
|                                            api_meta_map &meta) const | ||||
|       -> api_error = 0; | ||||
|  | ||||
|   [[nodiscard]] virtual auto | ||||
|   get_security_by_name(PWSTR file_name, PUINT32 attributes, | ||||
|                        PSECURITY_DESCRIPTOR descriptor, | ||||
|                        std::uint64_t *descriptor_size) -> NTSTATUS = 0; | ||||
|  | ||||
|   [[nodiscard]] virtual auto get_total_drive_space() const -> std::uint64_t = 0; | ||||
|  | ||||
|   [[nodiscard]] virtual auto get_total_item_count() const -> std::uint64_t = 0; | ||||
|  | ||||
|   [[nodiscard]] virtual auto get_used_drive_space() const -> std::uint64_t = 0; | ||||
|  | ||||
|   virtual void get_volume_info(UINT64 &total_size, UINT64 &free_size, | ||||
|                                std::string &volume_label) const = 0; | ||||
|  | ||||
|   [[nodiscard]] virtual auto populate_file_info(const std::string &api_path, | ||||
|                                                 remote::file_info &fi) | ||||
|       -> api_error = 0; | ||||
| }; | ||||
| } // namespace repertory | ||||
|  | ||||
| #endif // _WIN32 | ||||
| #endif // INCLUDE_DRIVES_WINFSP_I_WINFSP_DRIVE_HPP_ | ||||
| @@ -0,0 +1,117 @@ | ||||
| /* | ||||
|   Copyright <2018-2024> <scott.e.graves@protonmail.com> | ||||
|  | ||||
|   Permission is hereby granted, free of charge, to any person obtaining a copy | ||||
|   of this software and associated documentation files (the "Software"), to deal | ||||
|   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 "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 auto winfsp_can_delete(PVOID file_desc, PWSTR file_name) | ||||
|       -> packet::error_type = 0; | ||||
|  | ||||
|   virtual auto winfsp_cleanup(PVOID file_desc, PWSTR file_name, UINT32 flags, | ||||
|                               BOOLEAN &was_closed) -> packet::error_type = 0; | ||||
|  | ||||
|   virtual auto winfsp_close(PVOID file_desc) -> packet::error_type = 0; | ||||
|  | ||||
|   virtual auto winfsp_create(PWSTR file_name, UINT32 create_options, | ||||
|                              UINT32 granted_access, UINT32 file_attributes, | ||||
|                              UINT64 allocation_size, PVOID *file_desc, | ||||
|                              remote::file_info *file_info, | ||||
|                              std::string &normalized_name, BOOLEAN &exists) | ||||
|       -> packet::error_type = 0; | ||||
|  | ||||
|   virtual auto winfsp_flush(PVOID file_desc, remote::file_info *file_info) | ||||
|       -> packet::error_type = 0; | ||||
|  | ||||
|   virtual auto winfsp_get_dir_buffer(PVOID file_desc, PVOID *&ptr) | ||||
|       -> packet::error_type = 0; | ||||
|  | ||||
|   virtual auto winfsp_get_file_info(PVOID file_desc, remote::file_info *file_info) | ||||
|       -> packet::error_type = 0; | ||||
|  | ||||
|   virtual auto | ||||
|   winfsp_get_security_by_name(PWSTR file_name, PUINT32 file_attributes, | ||||
|                               std::uint64_t *security_descriptor_size, | ||||
|                               std::wstring &str_descriptor) | ||||
|       -> packet::error_type = 0; | ||||
|  | ||||
|   virtual auto winfsp_get_volume_info(UINT64 &total_size, UINT64 &free_size, | ||||
|                                       std::string &volume_label) | ||||
|       -> packet::error_type = 0; | ||||
|  | ||||
|   virtual auto winfsp_mounted(const std::wstring &location) | ||||
|       -> packet::error_type = 0; | ||||
|  | ||||
|   virtual auto winfsp_open(PWSTR file_name, UINT32 create_options, | ||||
|                            UINT32 granted_access, PVOID *file_desc, | ||||
|                            remote::file_info *file_info, | ||||
|                            std::string &normalized_name) | ||||
|       -> packet::error_type = 0; | ||||
|  | ||||
|   virtual auto winfsp_overwrite(PVOID file_desc, UINT32 file_attributes, | ||||
|                                 BOOLEAN replace_file_attributes, | ||||
|                                 UINT64 allocation_size, | ||||
|                                 remote::file_info *file_info) | ||||
|       -> packet::error_type = 0; | ||||
|  | ||||
|   virtual auto winfsp_read(PVOID file_desc, PVOID buffer, UINT64 offset, | ||||
|                            UINT32 length, PUINT32 bytes_transferred) | ||||
|       -> packet::error_type = 0; | ||||
|  | ||||
|   virtual auto winfsp_read_directory(PVOID file_desc, PWSTR pattern, | ||||
|                                      PWSTR marker, json &itemList) | ||||
|       -> packet::error_type = 0; | ||||
|  | ||||
|   virtual auto winfsp_rename(PVOID file_desc, PWSTR file_name, PWSTR new_file_name, | ||||
|                              BOOLEAN replace_if_exists) -> packet::error_type = 0; | ||||
|  | ||||
|   virtual auto winfsp_set_basic_info(PVOID file_desc, UINT32 file_attributes, | ||||
|                                      UINT64 creation_time, UINT64 last_access_time, | ||||
|                                      UINT64 last_write_time, UINT64 change_time, | ||||
|                                      remote::file_info *file_info) | ||||
|       -> packet::error_type = 0; | ||||
|  | ||||
|   virtual auto winfsp_set_file_size(PVOID file_desc, UINT64 new_size, | ||||
|                                     BOOLEAN set_allocation_size, | ||||
|                                     remote::file_info *file_info) | ||||
|       -> packet::error_type = 0; | ||||
|  | ||||
|   virtual auto winfsp_unmounted(const std::wstring &location) | ||||
|       -> packet::error_type = 0; | ||||
|  | ||||
|   virtual auto 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) | ||||
|       -> packet::error_type = 0; | ||||
| }; | ||||
|  | ||||
| using remote_instance_factory = | ||||
|     std::function<std::unique_ptr<i_remote_instance>()>; | ||||
| } // namespace repertory::remote_winfsp | ||||
|  | ||||
| #endif // INCLUDE_DRIVES_WINFSP_REMOTEWINFSP_I_REMOTE_INSTANCE_HPP_ | ||||
| @@ -0,0 +1,141 @@ | ||||
| /* | ||||
|   Copyright <2018-2024> <scott.e.graves@protonmail.com> | ||||
|  | ||||
|   Permission is hereby granted, free of charge, to any person obtaining a copy | ||||
|   of this software and associated documentation files (the "Software"), to deal | ||||
|   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 "comm/packet/packet.hpp" | ||||
| #include "comm/packet/packet_client.hpp" | ||||
| #include "drives/remote/remote_open_file_table.hpp" | ||||
| #include "drives/winfsp/remotewinfsp/i_remote_instance.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 auto to_handle(PVOID file_desc) -> native_handle; | ||||
| #endif | ||||
|  | ||||
| protected: | ||||
|   void delete_open_directory(void * /*dir*/) override {} | ||||
|  | ||||
| public: | ||||
|   auto json_create_directory_snapshot(const std::string &path, json &json_data) | ||||
|       -> packet::error_type override; | ||||
|  | ||||
|   auto json_read_directory_snapshot(const std::string &path, | ||||
|                                     const remote::file_handle &handle, | ||||
|                                     std::uint32_t page, json &json_data) | ||||
|       -> packet::error_type override; | ||||
|  | ||||
|   auto json_release_directory_snapshot(const std::string &path, | ||||
|                                        const remote::file_handle &handle) | ||||
|       -> packet::error_type override; | ||||
|  | ||||
|   auto winfsp_can_delete(PVOID file_desc, PWSTR file_name) | ||||
|       -> packet::error_type override; | ||||
|  | ||||
|   auto winfsp_cleanup(PVOID file_desc, PWSTR file_name, UINT32 flags, | ||||
|                       BOOLEAN &was_closed) -> packet::error_type override; | ||||
|  | ||||
|   auto winfsp_close(PVOID file_desc) -> packet::error_type override; | ||||
|  | ||||
|   auto 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) -> packet::error_type override; | ||||
|  | ||||
|   auto winfsp_flush(PVOID file_desc, remote::file_info *file_info) | ||||
|       -> packet::error_type override; | ||||
|  | ||||
|   auto winfsp_get_dir_buffer(PVOID file_desc, PVOID *&ptr) | ||||
|       -> packet::error_type override; | ||||
|  | ||||
|   auto winfsp_get_file_info(PVOID file_desc, remote::file_info *file_info) | ||||
|       -> packet::error_type override; | ||||
|  | ||||
|   auto winfsp_get_security_by_name(PWSTR file_name, PUINT32 attributes, | ||||
|                                    std::uint64_t *descriptor_size, | ||||
|                                    std::wstring &string_descriptor) | ||||
|       -> packet::error_type override; | ||||
|  | ||||
|   auto winfsp_get_volume_info(UINT64 &total_size, UINT64 &free_size, | ||||
|                               std::string &volume_label) | ||||
|       -> packet::error_type override; | ||||
|  | ||||
|   auto winfsp_mounted(const std::wstring &location) | ||||
|       -> packet::error_type override; | ||||
|  | ||||
|   auto winfsp_open(PWSTR file_name, UINT32 create_options, | ||||
|                    UINT32 granted_access, PVOID *file_desc, | ||||
|                    remote::file_info *file_info, std::string &normalized_name) | ||||
|       -> packet::error_type override; | ||||
|  | ||||
|   auto winfsp_overwrite(PVOID file_desc, UINT32 attributes, | ||||
|                         BOOLEAN replace_attributes, UINT64 allocation_size, | ||||
|                         remote::file_info *file_info) | ||||
|       -> packet::error_type override; | ||||
|  | ||||
|   auto winfsp_read(PVOID file_desc, PVOID buffer, UINT64 offset, UINT32 length, | ||||
|                    PUINT32 bytes_transferred) -> packet::error_type override; | ||||
|  | ||||
|   auto winfsp_read_directory(PVOID file_desc, PWSTR pattern, PWSTR marker, | ||||
|                              json &itemList) -> packet::error_type override; | ||||
|  | ||||
|   auto winfsp_rename(PVOID file_desc, PWSTR file_name, PWSTR new_file_name, | ||||
|                      BOOLEAN replace_if_exists) -> packet::error_type override; | ||||
|  | ||||
|   auto winfsp_set_basic_info(PVOID file_desc, UINT32 attributes, | ||||
|                              UINT64 creation_time, UINT64 last_access_time, | ||||
|                              UINT64 last_write_time, UINT64 change_time, | ||||
|                              remote::file_info *file_info) | ||||
|       -> packet::error_type override; | ||||
|  | ||||
|   auto winfsp_set_file_size(PVOID file_desc, UINT64 new_size, | ||||
|                             BOOLEAN set_allocation_size, | ||||
|                             remote::file_info *file_info) | ||||
|       -> packet::error_type override; | ||||
|  | ||||
|   auto winfsp_unmounted(const std::wstring &location) | ||||
|       -> packet::error_type override; | ||||
|  | ||||
|   auto 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) | ||||
|       -> packet::error_type override; | ||||
| }; | ||||
| } // namespace remote_winfsp | ||||
| } // namespace repertory | ||||
|  | ||||
| #endif // INCLUDE_DRIVES_WINFSP_REMOTEWINFSP_REMOTE_CLIENT_HPP_ | ||||
| @@ -0,0 +1,286 @@ | ||||
| /* | ||||
|   Copyright <2018-2024> <scott.e.graves@protonmail.com> | ||||
|  | ||||
|   Permission is hereby granted, free of charge, to any person obtaining a copy | ||||
|   of this software and associated documentation files (the "Software"), to deal | ||||
|   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 "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, | ||||
|                            utils::string::to_lower(mount_location)) {} | ||||
|  | ||||
| private: | ||||
|   [[nodiscard]] auto construct_path(std::string path) -> std::string; | ||||
|  | ||||
|   [[nodiscard]] auto populate_file_info(const std::string &api_path, | ||||
|                                         remote::file_info &file_info) | ||||
|       -> packet::error_type; | ||||
|  | ||||
|   void populate_stat(const char *path, bool directory, remote::stat &r_stat, | ||||
|                      const struct _stat64 &unix_st); | ||||
|  | ||||
| public: | ||||
|   // FUSE Layer | ||||
|   auto fuse_access(const char *path, const std::int32_t &mask) | ||||
|       -> packet::error_type override; | ||||
|  | ||||
|   auto fuse_chflags(const char *path, std::uint32_t flags) | ||||
|       -> packet::error_type override; | ||||
|  | ||||
|   auto fuse_chmod(const char *path, const remote::file_mode &mode) | ||||
|       -> packet::error_type override; | ||||
|  | ||||
|   auto fuse_chown(const char *path, const remote::user_id &uid, | ||||
|                   const remote::group_id &gid) -> packet::error_type override; | ||||
|  | ||||
|   auto fuse_destroy() -> packet::error_type 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 ;*/ | ||||
|  | ||||
|   auto fuse_fgetattr(const char *path, remote::stat &r_stat, bool &directory, | ||||
|                      const remote::file_handle &handle) | ||||
|       -> packet::error_type override; | ||||
|  | ||||
|   auto fuse_fsetattr_x(const char *path, const remote::setattr_x &attr, | ||||
|                        const remote::file_handle &handle) | ||||
|       -> packet::error_type override; | ||||
|  | ||||
|   auto fuse_fsync(const char *path, const std::int32_t &datasync, | ||||
|                   const remote::file_handle &handle) | ||||
|       -> packet::error_type override; | ||||
|  | ||||
|   auto fuse_ftruncate(const char *path, const remote::file_offset &size, | ||||
|                       const remote::file_handle &handle) | ||||
|       -> packet::error_type override; | ||||
|  | ||||
|   auto fuse_getattr(const char *path, remote::stat &r_stat, bool &directory) | ||||
|       -> packet::error_type 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, std::uint32_t position) override ;*/ | ||||
|  | ||||
|   auto fuse_getxtimes(const char *path, remote::file_time &bkuptime, | ||||
|                       remote::file_time &crtime) -> packet::error_type override; | ||||
|  | ||||
|   auto fuse_init() -> packet::error_type override; | ||||
|  | ||||
|   /*packet::error_type fuse_listxattr(const char *path, char *buffer, | ||||
|                                          const remote::file_size &size) override | ||||
|      ;*/ | ||||
|  | ||||
|   auto fuse_mkdir(const char *path, const remote::file_mode &mode) | ||||
|       -> packet::error_type override; | ||||
|  | ||||
|   auto fuse_opendir(const char *path, remote::file_handle &handle) | ||||
|       -> packet::error_type override; | ||||
|  | ||||
|   auto fuse_create(const char *path, const remote::file_mode &mode, | ||||
|                    const remote::open_flags &flags, remote::file_handle &handle) | ||||
|       -> packet::error_type override; | ||||
|  | ||||
|   auto fuse_open(const char *path, const remote::open_flags &flags, | ||||
|                  remote::file_handle &handle) -> packet::error_type override; | ||||
|  | ||||
|   auto fuse_read(const char *path, char *buffer, | ||||
|                  const remote::file_size &read_size, | ||||
|                  const remote::file_offset &read_offset, | ||||
|                  const remote::file_handle &handle) | ||||
|       -> packet::error_type override; | ||||
|  | ||||
|   auto fuse_rename(const char *from, const char *to) | ||||
|       -> packet::error_type override; | ||||
|  | ||||
|   auto 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) | ||||
|       -> packet::error_type override; | ||||
|  | ||||
|   auto 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) | ||||
|       -> packet::error_type override; | ||||
|  | ||||
|   auto fuse_readdir(const char *path, const remote::file_offset &offset, | ||||
|                     const remote::file_handle &handle, std::string &item_path) | ||||
|       -> packet::error_type override; | ||||
|  | ||||
|   auto fuse_release(const char *path, const remote::file_handle &handle) | ||||
|       -> packet::error_type override; | ||||
|  | ||||
|   auto fuse_releasedir(const char *path, const remote::file_handle &handle) | ||||
|       -> packet::error_type override; | ||||
|  | ||||
|   /*packet::error_type fuse_removexattr(const char *path, const char *name) | ||||
|    * override ;*/ | ||||
|  | ||||
|   auto fuse_rmdir(const char *path) -> packet::error_type override; | ||||
|  | ||||
|   auto fuse_setattr_x(const char *path, remote::setattr_x &attr) | ||||
|       -> packet::error_type override; | ||||
|  | ||||
|   auto fuse_setbkuptime(const char *path, const remote::file_time &bkuptime) | ||||
|       -> packet::error_type override; | ||||
|  | ||||
|   auto fuse_setchgtime(const char *path, const remote::file_time &chgtime) | ||||
|       -> packet::error_type override; | ||||
|  | ||||
|   auto fuse_setcrtime(const char *path, const remote::file_time &crtime) | ||||
|       -> packet::error_type override; | ||||
|  | ||||
|   auto fuse_setvolname(const char *volname) -> packet::error_type 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, | ||||
|                                            std::uint32_t position) override ;*/ | ||||
|  | ||||
|   auto fuse_statfs(const char *path, std::uint64_t frsize, | ||||
|                    remote::statfs &r_stat) -> packet::error_type override; | ||||
|  | ||||
|   auto fuse_statfs_x(const char *path, std::uint64_t bsize, | ||||
|                      remote::statfs_x &r_stat) -> packet::error_type override; | ||||
|  | ||||
|   auto fuse_truncate(const char *path, const remote::file_offset &size) | ||||
|       -> packet::error_type override; | ||||
|  | ||||
|   auto fuse_unlink(const char *path) -> packet::error_type override; | ||||
|  | ||||
|   auto fuse_utimens(const char *path, const remote::file_time *tv, | ||||
|                     std::uint64_t op0, std::uint64_t op1) | ||||
|       -> packet::error_type override; | ||||
|  | ||||
|   void set_fuse_uid_gid(const remote::user_id & /* uid */, | ||||
|                         const remote::group_id & /* gid */) override {} | ||||
|  | ||||
|   // JSON Layer | ||||
|   auto json_create_directory_snapshot(const std::string &path, json &json_data) | ||||
|       -> packet::error_type override; | ||||
|  | ||||
|   auto json_read_directory_snapshot(const std::string &path, | ||||
|                                     const remote::file_handle &handle, | ||||
|                                     std::uint32_t page, json &json_data) | ||||
|       -> packet::error_type override; | ||||
|  | ||||
|   auto json_release_directory_snapshot(const std::string &path, | ||||
|                                        const remote::file_handle &handle) | ||||
|       -> packet::error_type override; | ||||
|  | ||||
|   // WinFSP Layer | ||||
|   auto winfsp_can_delete(PVOID file_desc, PWSTR file_name) | ||||
|       -> packet::error_type override; | ||||
|  | ||||
|   auto winfsp_cleanup(PVOID file_desc, PWSTR file_name, UINT32 flags, | ||||
|                       BOOLEAN &was_closed) -> packet::error_type override; | ||||
|  | ||||
|   auto winfsp_close(PVOID file_desc) -> packet::error_type override; | ||||
|  | ||||
|   auto 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) -> packet::error_type override; | ||||
|  | ||||
|   auto winfsp_flush(PVOID file_desc, remote::file_info *file_info) | ||||
|       -> packet::error_type override; | ||||
|  | ||||
|   auto winfsp_get_dir_buffer(PVOID file_desc, PVOID *&ptr) | ||||
|       -> packet::error_type override; | ||||
|  | ||||
|   auto winfsp_get_file_info(PVOID file_desc, remote::file_info *file_info) | ||||
|       -> packet::error_type override; | ||||
|  | ||||
|   auto winfsp_get_security_by_name(PWSTR file_name, PUINT32 attributes, | ||||
|                                    std::uint64_t *descriptor_size, | ||||
|                                    std::wstring &string_descriptor) | ||||
|       -> packet::error_type override; | ||||
|  | ||||
|   auto winfsp_get_volume_info(UINT64 &total_size, UINT64 &free_size, | ||||
|                               std::string &volume_label) | ||||
|       -> packet::error_type override; | ||||
|  | ||||
|   auto winfsp_mounted(const std::wstring &location) | ||||
|       -> packet::error_type override; | ||||
|  | ||||
|   auto winfsp_open(PWSTR file_name, UINT32 create_options, | ||||
|                    UINT32 granted_access, PVOID *file_desc, | ||||
|                    remote::file_info *file_info, std::string &normalized_name) | ||||
|       -> packet::error_type override; | ||||
|  | ||||
|   auto winfsp_overwrite(PVOID file_desc, UINT32 attributes, | ||||
|                         BOOLEAN replace_attributes, UINT64 allocation_size, | ||||
|                         remote::file_info *file_info) | ||||
|       -> packet::error_type override; | ||||
|  | ||||
|   auto winfsp_read(PVOID file_desc, PVOID buffer, UINT64 offset, UINT32 length, | ||||
|                    PUINT32 bytes_transferred) -> packet::error_type override; | ||||
|  | ||||
|   auto winfsp_read_directory(PVOID file_desc, PWSTR pattern, PWSTR marker, | ||||
|                              json &item_list) -> packet::error_type override; | ||||
|  | ||||
|   auto winfsp_rename(PVOID file_desc, PWSTR file_name, PWSTR new_file_name, | ||||
|                      BOOLEAN replace_if_exists) -> packet::error_type override; | ||||
|  | ||||
|   auto winfsp_set_basic_info(PVOID file_desc, UINT32 attributes, | ||||
|                              UINT64 creation_time, UINT64 last_access_time, | ||||
|                              UINT64 last_write_time, UINT64 change_time, | ||||
|                              remote::file_info *file_info) | ||||
|       -> packet::error_type override; | ||||
|  | ||||
|   auto winfsp_set_file_size(PVOID file_desc, UINT64 new_size, | ||||
|                             BOOLEAN set_allocation_size, | ||||
|                             remote::file_info *file_info) | ||||
|       -> packet::error_type override; | ||||
|  | ||||
|   auto winfsp_unmounted(const std::wstring &location) | ||||
|       -> packet::error_type override; | ||||
|  | ||||
|   auto 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) | ||||
|       -> packet::error_type override; | ||||
| }; | ||||
| } // namespace remote_winfsp | ||||
| } // namespace repertory | ||||
|  | ||||
| #endif // _WIN32 | ||||
| #endif // INCLUDE_DRIVES_WINFSP_REMOTEWINFSP_REMOTE_SERVER_HPP_ | ||||
| @@ -0,0 +1,155 @@ | ||||
| /* | ||||
|   Copyright <2018-2024> <scott.e.graves@protonmail.com> | ||||
|  | ||||
|   Permission is hereby granted, free of charge, to any person obtaining a copy | ||||
|   of this software and associated documentation files (the "Software"), to deal | ||||
|   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 "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, remote_instance_factory factory, | ||||
|                       lock_data &lock); | ||||
|  | ||||
|   ~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: | ||||
|     auto OnStart(ULONG, PWSTR *) -> NTSTATUS override; | ||||
|  | ||||
|     auto OnStop() -> NTSTATUS 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 populate_file_info(const json &item, FSP_FSCTL_FILE_INFO &file_info); | ||||
|  | ||||
|   static void set_file_info(FileInfo &dest, const remote::file_info &src); | ||||
|  | ||||
| public: | ||||
|   auto CanDelete(PVOID file_node, PVOID file_desc, PWSTR file_name) | ||||
|       -> NTSTATUS override; | ||||
|  | ||||
|   VOID Cleanup(PVOID file_node, PVOID file_desc, PWSTR file_name, | ||||
|                ULONG flags) override; | ||||
|  | ||||
|   VOID Close(PVOID file_node, PVOID file_desc) override; | ||||
|  | ||||
|   auto 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) -> NTSTATUS override; | ||||
|  | ||||
|   auto Flush(PVOID file_node, PVOID file_desc, FileInfo *file_info) | ||||
|       -> NTSTATUS override; | ||||
|  | ||||
|   auto GetFileInfo(PVOID file_node, PVOID file_desc, FileInfo *file_info) | ||||
|       -> NTSTATUS override; | ||||
|  | ||||
|   auto GetSecurityByName(PWSTR file_name, PUINT32 attributes, | ||||
|                          PSECURITY_DESCRIPTOR descriptor, | ||||
|                          SIZE_T *descriptor_size) -> NTSTATUS override; | ||||
|  | ||||
|   auto GetVolumeInfo(VolumeInfo *volume_info) -> NTSTATUS override; | ||||
|  | ||||
|   auto Init(PVOID host) -> NTSTATUS override; | ||||
|  | ||||
|   [[nodiscard]] auto mount(const std::vector<std::string> &drive_args) -> int; | ||||
|  | ||||
|   auto Mounted(PVOID host) -> NTSTATUS override; | ||||
|  | ||||
|   auto Open(PWSTR file_name, UINT32 create_options, UINT32 granted_access, | ||||
|             PVOID *file_node, PVOID *file_desc, OpenFileInfo *ofi) | ||||
|       -> NTSTATUS override; | ||||
|  | ||||
|   auto Overwrite(PVOID file_node, PVOID file_desc, UINT32 attributes, | ||||
|                  BOOLEAN replace_attributes, UINT64 allocation_size, | ||||
|                  FileInfo *file_info) -> NTSTATUS override; | ||||
|  | ||||
|   auto Read(PVOID file_node, PVOID file_desc, PVOID buffer, UINT64 offset, | ||||
|             ULONG length, PULONG bytes_transferred) -> NTSTATUS override; | ||||
|  | ||||
|   auto ReadDirectory(PVOID file_node, PVOID file_desc, PWSTR pattern, | ||||
|                      PWSTR marker, PVOID buffer, ULONG buffer_length, | ||||
|                      PULONG bytes_transferred) -> NTSTATUS override; | ||||
|  | ||||
|   auto Rename(PVOID file_node, PVOID file_desc, PWSTR file_name, | ||||
|               PWSTR new_file_name, BOOLEAN replace_if_exists) | ||||
|       -> NTSTATUS override; | ||||
|  | ||||
|   auto 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) -> NTSTATUS override; | ||||
|  | ||||
|   auto SetFileSize(PVOID file_node, PVOID file_desc, UINT64 new_size, | ||||
|                    BOOLEAN set_allocation_size, FileInfo *file_info) | ||||
|       -> NTSTATUS override; | ||||
|  | ||||
|   VOID Unmounted(PVOID host) override; | ||||
|  | ||||
|   auto 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) | ||||
|       -> NTSTATUS 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_ | ||||
							
								
								
									
										204
									
								
								repertory/librepertory/include/drives/winfsp/winfsp_drive.hpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										204
									
								
								repertory/librepertory/include/drives/winfsp/winfsp_drive.hpp
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,204 @@ | ||||
| /* | ||||
|   Copyright <2018-2024> <scott.e.graves@protonmail.com> | ||||
|  | ||||
|   Permission is hereby granted, free of charge, to any person obtaining a copy | ||||
|   of this software and associated documentation files (the "Software"), to deal | ||||
|   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 "drives/eviction.hpp" | ||||
| #include "drives/winfsp/i_winfsp_drive.hpp" | ||||
| #include "drives/winfsp/remotewinfsp/remote_server.hpp" | ||||
| #include "events/event_system.hpp" | ||||
| #include "file_manager/file_manager.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: | ||||
|     auto OnStart(ULONG, PWSTR *) -> NTSTATUS override; | ||||
|  | ||||
|     auto OnStop() -> NTSTATUS override; | ||||
|   }; | ||||
|  | ||||
| private: | ||||
|   i_provider &provider_; | ||||
|   app_config &config_; | ||||
|   lock_data &lock_; | ||||
|   std::unique_ptr<full_server> server_; | ||||
|   std::unique_ptr<file_manager> fm_; | ||||
|   std::unique_ptr<eviction> eviction_; | ||||
|   std::unique_ptr<remote_winfsp::remote_server> remote_server_; | ||||
|  | ||||
| private: | ||||
|   static auto parse_mount_location(const std::wstring &mount_location) | ||||
|       -> std::string; | ||||
|  | ||||
|   void populate_file_info(const std::string &api_path, std::uint64_t file_size, | ||||
|                           const api_meta_map &meta, | ||||
|                           FSP_FSCTL_OPEN_FILE_INFO &ofi); | ||||
|  | ||||
|   void populate_file_info(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: | ||||
|   auto CanDelete(PVOID file_node, PVOID file_desc, PWSTR file_name) | ||||
|       -> NTSTATUS override; | ||||
|  | ||||
|   VOID Cleanup(PVOID file_node, PVOID file_desc, PWSTR file_name, | ||||
|                ULONG flags) override; | ||||
|  | ||||
|   VOID Close(PVOID file_node, PVOID file_desc) override; | ||||
|  | ||||
|   auto 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) -> NTSTATUS override; | ||||
|  | ||||
|   auto Flush(PVOID file_node, PVOID file_desc, FileInfo *file_info) | ||||
|       -> NTSTATUS override; | ||||
|  | ||||
|   [[nodiscard]] auto get_directory_item_count(const std::string &api_path) const | ||||
|       -> std::uint64_t override; | ||||
|  | ||||
|   [[nodiscard]] auto get_directory_items(const std::string &api_path) const | ||||
|       -> directory_item_list override; | ||||
|  | ||||
|   auto GetFileInfo(PVOID file_node, PVOID file_desc, FileInfo *file_info) | ||||
|       -> NTSTATUS override; | ||||
|  | ||||
|   [[nodiscard]] auto get_file_size(const std::string &api_path) const | ||||
|       -> std::uint64_t override; | ||||
|  | ||||
|   [[nodiscard]] auto get_item_meta(const std::string &api_path, | ||||
|                                    api_meta_map &meta) const | ||||
|       -> api_error override; | ||||
|  | ||||
|   [[nodiscard]] auto get_item_meta(const std::string &api_path, | ||||
|                                    const std::string &name, | ||||
|                                    std::string &value) const | ||||
|       -> api_error override; | ||||
|  | ||||
|   [[nodiscard]] auto get_security_by_name(PWSTR file_name, PUINT32 attributes, | ||||
|                                           PSECURITY_DESCRIPTOR descriptor, | ||||
|                                           std::uint64_t *descriptor_size) | ||||
|       -> NTSTATUS override; | ||||
|  | ||||
|   auto GetSecurityByName(PWSTR file_name, PUINT32 attributes, | ||||
|                          PSECURITY_DESCRIPTOR descriptor, | ||||
|                          SIZE_T *descriptor_size) -> NTSTATUS override; | ||||
|  | ||||
|   [[nodiscard]] auto get_total_drive_space() const -> std::uint64_t override; | ||||
|  | ||||
|   [[nodiscard]] auto get_total_item_count() const -> std::uint64_t override; | ||||
|  | ||||
|   [[nodiscard]] auto get_used_drive_space() const -> std::uint64_t override; | ||||
|  | ||||
|   void get_volume_info(UINT64 &total_size, UINT64 &free_size, | ||||
|                        std::string &volume_label) const override; | ||||
|  | ||||
|   auto GetVolumeInfo(VolumeInfo *volume_info) -> NTSTATUS override; | ||||
|  | ||||
|   auto Init(PVOID host) -> NTSTATUS override; | ||||
|  | ||||
|   [[nodiscard]] auto mount(const std::vector<std::string> &drive_args) -> int; | ||||
|  | ||||
|   auto Mounted(PVOID host) -> NTSTATUS override; | ||||
|  | ||||
|   auto Open(PWSTR file_name, UINT32 create_options, UINT32 granted_access, | ||||
|             PVOID *file_node, PVOID *file_desc, OpenFileInfo *ofi) | ||||
|       -> NTSTATUS override; | ||||
|  | ||||
|   auto Overwrite(PVOID file_node, PVOID file_desc, UINT32 attributes, | ||||
|                  BOOLEAN replace_attributes, UINT64 allocation_size, | ||||
|                  FileInfo *file_info) -> NTSTATUS override; | ||||
|  | ||||
|   [[nodiscard]] auto populate_file_info(const std::string &api_path, | ||||
|                                         remote::file_info &file_info) | ||||
|       -> api_error override; | ||||
|  | ||||
|   auto Read(PVOID file_node, PVOID file_desc, PVOID buffer, UINT64 offset, | ||||
|             ULONG length, PULONG bytes_transferred) -> NTSTATUS override; | ||||
|  | ||||
|   auto ReadDirectory(PVOID file_node, PVOID file_desc, PWSTR pattern, | ||||
|                      PWSTR marker, PVOID buffer, ULONG bufferLength, | ||||
|                      PULONG bytes_transferred) -> NTSTATUS override; | ||||
|  | ||||
|   auto Rename(PVOID file_node, PVOID file_desc, PWSTR file_name, | ||||
|               PWSTR new_file_name, BOOLEAN replace_if_exists) | ||||
|       -> NTSTATUS override; | ||||
|  | ||||
|   auto 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) -> NTSTATUS override; | ||||
|  | ||||
|   auto SetFileSize(PVOID file_node, PVOID file_desc, UINT64 new_size, | ||||
|                    BOOLEAN set_allocation_size, FileInfo *file_info) | ||||
|       -> NTSTATUS override; | ||||
|  | ||||
|   VOID Unmounted(PVOID host) override; | ||||
|  | ||||
|   auto 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) | ||||
|       -> NTSTATUS override; | ||||
|  | ||||
|   void shutdown(); | ||||
|  | ||||
|   static void display_options(std::vector<const char *> /* args */) {} | ||||
|  | ||||
|   static void | ||||
|   display_version_information(std::vector<const char *> /* args */) {} | ||||
| }; | ||||
| } // namespace repertory | ||||
|  | ||||
| #endif // _WIN32 | ||||
| #endif // INCLUDE_DRIVES_WINFSP_WINFSP_DRIVE_HPP_ | ||||
| @@ -0,0 +1,53 @@ | ||||
| /* | ||||
|   Copyright <2018-2024> <scott.e.graves@protonmail.com> | ||||
|  | ||||
|   Permission is hereby granted, free of charge, to any person obtaining a copy | ||||
|   of this software and associated documentation files (the "Software"), to deal | ||||
|   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 "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_ | ||||
| @@ -0,0 +1,64 @@ | ||||
| /* | ||||
|   Copyright <2018-2024> <scott.e.graves@protonmail.com> | ||||
|  | ||||
|   Permission is hereby granted, free of charge, to any person obtaining a copy | ||||
|   of this software and associated documentation files (the "Software"), to deal | ||||
|   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 "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(std::size_t count); | ||||
|  | ||||
|   void close_log_file(); | ||||
|  | ||||
|   void logging_thread(bool drain); | ||||
|  | ||||
|   void process_event(const event &event); | ||||
|  | ||||
|   void reopen_log_file(); | ||||
| }; | ||||
| } // namespace repertory | ||||
|  | ||||
| #endif // INCLUDE_EVENTS_CONSUMERS_LOGGING_CONSUMER_HPP_ | ||||
							
								
								
									
										74
									
								
								repertory/librepertory/include/events/event.hpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										74
									
								
								repertory/librepertory/include/events/event.hpp
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,74 @@ | ||||
| /* | ||||
|   Copyright <2018-2024> <scott.e.graves@protonmail.com> | ||||
|  | ||||
|   Permission is hereby granted, free of charge, to any person obtaining a copy | ||||
|   of this software and associated documentation files (the "Software"), to deal | ||||
|   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_ | ||||
|  | ||||
| namespace repertory { | ||||
| enum class event_level { | ||||
|   error, | ||||
|   warn, | ||||
|   normal, | ||||
|   debug, | ||||
|   verbose, | ||||
| }; | ||||
|  | ||||
| auto event_level_from_string(std::string level) -> event_level; | ||||
|  | ||||
| auto event_level_to_string(const event_level &level) -> std::string; | ||||
|  | ||||
| class event { | ||||
| protected: | ||||
|   explicit event(bool allow_async) : allow_async_(allow_async) {} | ||||
|  | ||||
|   event(const std::stringstream &ss, json j, bool allow_async) | ||||
|       : allow_async_(allow_async), ss_(ss.str()), j_(std::move(j)) {} | ||||
|  | ||||
| public: | ||||
|   event(const event &) = delete; | ||||
|   event(event &&) = delete; | ||||
|   auto operator=(const event &) -> event & = delete; | ||||
|   auto operator=(event &&) -> event & = delete; | ||||
|   virtual ~event() = default; | ||||
|  | ||||
| private: | ||||
|   bool allow_async_; | ||||
|  | ||||
| protected: | ||||
|   std::stringstream ss_; | ||||
|   json j_; | ||||
|  | ||||
| public: | ||||
|   [[nodiscard]] virtual auto clone() const -> std::shared_ptr<event> = 0; | ||||
|  | ||||
|   [[nodiscard]] auto get_allow_async() const -> bool { return allow_async_; } | ||||
|  | ||||
|   [[nodiscard]] virtual auto get_event_level() const -> event_level = 0; | ||||
|  | ||||
|   [[nodiscard]] auto get_json() const -> json { return j_; } | ||||
|  | ||||
|   [[nodiscard]] virtual auto get_name() const -> std::string = 0; | ||||
|  | ||||
|   [[nodiscard]] virtual auto get_single_line() const -> std::string = 0; | ||||
| }; | ||||
| } // namespace repertory | ||||
|  | ||||
| #endif // INCLUDE_EVENTS_EVENT_HPP_ | ||||
							
								
								
									
										262
									
								
								repertory/librepertory/include/events/event_system.hpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										262
									
								
								repertory/librepertory/include/events/event_system.hpp
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,262 @@ | ||||
| /* | ||||
|   Copyright <2018-2024> <scott.e.graves@protonmail.com> | ||||
|  | ||||
|   Permission is hereby granted, free of charge, to any person obtaining a copy | ||||
|   of this software and associated documentation files (the "Software"), to deal | ||||
|   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 "events/event.hpp" | ||||
| #include "events/t_event_system.hpp" | ||||
| #include "utils/string_utils.hpp" | ||||
|  | ||||
| namespace repertory { | ||||
| using event_system = t_event_system<event>; | ||||
| using event_consumer = event_system::event_consumer; | ||||
|  | ||||
| #define E_CAST(t) ((std::string)t) | ||||
| #define E_DOUBLE(d) std::to_string(d) | ||||
| #define E_DOUBLE_PRECISE(dbl_val)                                              \ | ||||
|   ([](const double &d) -> std::string {                                        \ | ||||
|     std::stringstream ss;                                                      \ | ||||
|     ss << std::fixed << std::setprecision(2) << d;                             \ | ||||
|     return ss.str();                                                           \ | ||||
|   })(dbl_val) | ||||
| #define E_FROM_BOOL(t) std::to_string(t) | ||||
| #define E_FROM_EXCEPTION(e) std::string(e.what() ? e.what() : "") | ||||
| #define E_FROM_INT32(t) std::to_string(t) | ||||
| #define E_FROM_INT64(t) std::to_string(t) | ||||
| #define E_FROM_UINT16(t) std::to_string(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_CURL_CODE(t) std::string(curl_easy_strerror(t)) | ||||
| #define E_FROM_UINT8(t) std::to_string(t) | ||||
| #define E_FROM_UINT32(t) std::to_string(t) | ||||
| #define E_FROM_UINT64(t) std::to_string(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 &val) {                                    \ | ||||
|     auto ts_val = ts(val);                                                     \ | ||||
|     ss_ << "|" << #short_name << "|" << ts_val;                                \ | ||||
|     j_[#name] = ts_val;                                                        \ | ||||
|   }                                                                            \ | ||||
|                                                                                \ | ||||
| public:                                                                        \ | ||||
|   [[nodiscard]] auto get_##name() const->json { return j_[#name]; } | ||||
|  | ||||
| #define E_BEGIN(name, el)                                                      \ | ||||
|   class name final : public virtual event {                                    \ | ||||
|   private:                                                                     \ | ||||
|     name(const std::stringstream &ss, const json &j, bool allow_async)         \ | ||||
|         : event(ss, j, allow_async) {}                                         \ | ||||
|                                                                                \ | ||||
|   public:                                                                      \ | ||||
|     ~name() override = default;                                                \ | ||||
|                                                                                \ | ||||
|   public:                                                                      \ | ||||
|     static const event_level level = event_level::el;                          \ | ||||
|                                                                                \ | ||||
|   public:                                                                      \ | ||||
|     [[nodiscard]] auto get_name() const -> std::string override {              \ | ||||
|       return #name;                                                            \ | ||||
|     }                                                                          \ | ||||
|                                                                                \ | ||||
|     [[nodiscard]] auto get_event_level() const -> event_level override {       \ | ||||
|       return name::level;                                                      \ | ||||
|     }                                                                          \ | ||||
|                                                                                \ | ||||
|     [[nodiscard]] auto get_single_line() const -> std::string override {       \ | ||||
|       const auto s = ss_.str();                                                \ | ||||
|       return get_name() + (s.empty() ? "" : s);                                \ | ||||
|     }                                                                          \ | ||||
|                                                                                \ | ||||
|     [[nodiscard]] auto clone() const -> std::shared_ptr<event> 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 &evt) { callback(evt); })) | ||||
|  | ||||
| #define E_SUBSCRIBE_EXACT(name, callback)                                      \ | ||||
|   event_consumers_.emplace_back(std::make_shared<repertory::event_consumer>(   \ | ||||
|       #name, [this](const event &evt) {                                        \ | ||||
|         callback(dynamic_cast<const name &>(evt));                             \ | ||||
|       })) | ||||
|  | ||||
| #define E_SUBSCRIBE_ALL(callback)                                              \ | ||||
|   event_consumers_.emplace_back(std::make_shared<repertory::event_consumer>(   \ | ||||
|       [this](const event &evt) { callback(evt); })) | ||||
| } // namespace repertory | ||||
|  | ||||
| #endif // INCLUDE_EVENTS_EVENT_SYSTEM_HPP_ | ||||
							
								
								
									
										301
									
								
								repertory/librepertory/include/events/events.hpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										301
									
								
								repertory/librepertory/include/events/events.hpp
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,301 @@ | ||||
| /* | ||||
|   Copyright <2018-2024> <scott.e.graves@protonmail.com> | ||||
|  | ||||
|   Permission is hereby granted, free of charge, to any person obtaining a copy | ||||
|   of this software and associated documentation files (the "Software"), to deal | ||||
|   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 "events/event_system.hpp" | ||||
| #include "types/repertory.hpp" | ||||
| #include "utils/utils.hpp" | ||||
|  | ||||
| namespace repertory { | ||||
| // clang-format off | ||||
| E_SIMPLE2(curl_error, normal, true, | ||||
|   std::string, url, url, E_STRING, | ||||
|   CURLcode, res, res, E_FROM_CURL_CODE  | ||||
| ); | ||||
|  | ||||
| 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_removed_externally, warn, true, | ||||
|   std::string, api_path, ap, E_STRING, | ||||
|   std::string, source, src, 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_SIMPLE4(filesystem_item_handle_opened, 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 | ||||
| ); | ||||
|  | ||||
| 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_SIMPLE4(file_upload_completed, normal, true, | ||||
|   std::string, api_path, ap, E_STRING, | ||||
|   std::string, source, src, E_STRING, | ||||
|   api_error, result, res, E_FROM_API_FILE_ERROR, | ||||
|   bool, cancelled, cancel, E_FROM_BOOL | ||||
| ); | ||||
|  | ||||
| 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_SIMPLE1(file_upload_removed, debug, true, | ||||
|   std::string, api_path, ap, E_STRING | ||||
| ); | ||||
|  | ||||
| E_SIMPLE3(file_upload_retry, 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(file_upload_started, 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(provider_upload_begin, normal, true, | ||||
|   std::string, api_path, ap, E_STRING, | ||||
|   std::string, source, src, E_STRING | ||||
| ); | ||||
|  | ||||
| E_SIMPLE3(provider_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_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_begin, debug, true, | ||||
|   std::string, service, svc, E_STRING | ||||
| ); | ||||
|  | ||||
| E_SIMPLE1(service_shutdown_end, debug, true, | ||||
|   std::string, service, svc, E_STRING | ||||
| ); | ||||
|  | ||||
| E_SIMPLE1(service_started, debug, true, | ||||
|   std::string, service, svc, E_STRING | ||||
| ); | ||||
|  | ||||
| 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_ | ||||
							
								
								
									
										192
									
								
								repertory/librepertory/include/events/t_event_system.hpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										192
									
								
								repertory/librepertory/include/events/t_event_system.hpp
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,192 @@ | ||||
| /* | ||||
|   Copyright <2018-2024> <scott.e.graves@protonmail.com> | ||||
|  | ||||
|   Permission is hereby granted, free of charge, to any person obtaining a copy | ||||
|   of this software and associated documentation files (the "Software"), to deal | ||||
|   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 "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; | ||||
|   auto operator=(const t_event_system &) -> t_event_system & = delete; | ||||
|   auto operator=(t_event_system &&) -> 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); } | ||||
|  | ||||
|   public: | ||||
|     event_consumer(const event_consumer &) = delete; | ||||
|     event_consumer(event_consumer &&) = delete; | ||||
|     auto operator=(const event_consumer &) -> event_consumer & = delete; | ||||
|     auto operator=(event_consumer &&) -> event_consumer & = delete; | ||||
|  | ||||
|   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 auto instance() -> t_event_system &; | ||||
|  | ||||
| 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_; | ||||
|   stop_type stop_requested_ = false; | ||||
|  | ||||
| private: | ||||
|   void process_events() { | ||||
|     std::vector<std::shared_ptr<event_type>> events; | ||||
|     { | ||||
|       unique_mutex_lock lock(event_mutex_); | ||||
|       if (not stop_requested_ && event_list_.empty()) { | ||||
|         event_notify_.wait_for(lock, 1s); | ||||
|       } | ||||
|  | ||||
|       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 lock(consumer_mutex_); | ||||
|       if (event_consumers_.find(name) != event_consumers_.end()) { | ||||
|         for (auto *consumer : event_consumers_[name]) { | ||||
|           if (event.get_allow_async()) { | ||||
|             futures.emplace_back( | ||||
|                 std::async(std::launch::async, [consumer, &event]() { | ||||
|                   consumer->notify_event(event); | ||||
|                 })); | ||||
|           } else { | ||||
|             consumer->notify_event(event); | ||||
|           } | ||||
|         } | ||||
|       } | ||||
|  | ||||
|       while (not futures.empty()) { | ||||
|         futures.front().get(); | ||||
|         futures.pop_front(); | ||||
|       } | ||||
|     }; | ||||
|  | ||||
|     for (const auto &evt : events) { | ||||
|       notify_events("", *evt.get()); | ||||
|       notify_events(evt->get_name(), *evt.get()); | ||||
|     } | ||||
|   } | ||||
|  | ||||
|   void queue_event(std::shared_ptr<event_type> evt) { | ||||
|     mutex_lock lock(event_mutex_); | ||||
|     event_list_.push_back(std::move(evt)); | ||||
|     event_notify_.notify_all(); | ||||
|   } | ||||
|  | ||||
| public: | ||||
|   void attach(event_consumer *consumer) { | ||||
|     recur_mutex_lock lock(consumer_mutex_); | ||||
|     event_consumers_[""].push_back(consumer); | ||||
|   } | ||||
|  | ||||
|   void attach(const std::string &event_name, event_consumer *consumer) { | ||||
|     recur_mutex_lock lock(consumer_mutex_); | ||||
|     event_consumers_[event_name].push_back(consumer); | ||||
|   } | ||||
|  | ||||
|   template <typename event_t, typename... arg_t> void raise(arg_t &&...args) { | ||||
|     queue_event(std::make_shared<event_t>(std::forward<arg_t>(args)...)); | ||||
|   } | ||||
|  | ||||
|   void release(event_consumer *consumer) { | ||||
|     recur_mutex_lock lock(consumer_mutex_); | ||||
|     auto iter = | ||||
|         std::find_if(event_consumers_.begin(), event_consumers_.end(), | ||||
|                      [&](const auto &item) -> bool { | ||||
|                        return utils::collection_includes(item.second, consumer); | ||||
|                      }); | ||||
|  | ||||
|     if (iter != event_consumers_.end()) { | ||||
|       utils::remove_element_from((*iter).second, consumer); | ||||
|     } | ||||
|   } | ||||
|  | ||||
|   void start() { | ||||
|     mutex_lock lock(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 lock(run_mutex_); | ||||
|     if (event_thread_) { | ||||
|       stop_requested_ = true; | ||||
|       event_notify_.notify_all(); | ||||
|  | ||||
|       event_thread_->join(); | ||||
|       event_thread_.reset(); | ||||
|  | ||||
|       process_events(); | ||||
|     } | ||||
|   } | ||||
| }; | ||||
| } // namespace repertory | ||||
|  | ||||
| #endif // INCLUDE_EVENTS_T_EVENT_SYSTEM_HPP_ | ||||
							
								
								
									
										102
									
								
								repertory/librepertory/include/file_manager/events.hpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										102
									
								
								repertory/librepertory/include/file_manager/events.hpp
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,102 @@ | ||||
| /* | ||||
|   Copyright <2018-2024> <scott.e.graves@protonmail.com> | ||||
|  | ||||
|   Permission is hereby granted, free of charge, to any person obtaining a copy | ||||
|   of this software and associated documentation files (the "Software"), to deal | ||||
|   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_FILE_MANAGER_EVENTS_HPP_ | ||||
| #define INCLUDE_FILE_MANAGER_EVENTS_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_SIMPLE5(download_chunk_begin, debug, true, | ||||
|   std::string, api_path, ap, E_STRING, | ||||
|   std::string, dest_path, dest, E_STRING, | ||||
|   std::size_t, chunk, chunk, E_FROM_SIZE_T, | ||||
|   std::size_t, total, total, E_FROM_SIZE_T, | ||||
|   std::size_t, complete, complete, E_FROM_SIZE_T | ||||
| ); | ||||
|  | ||||
| E_SIMPLE6(download_chunk_end, debug, true, | ||||
|   std::string, api_path, ap, E_STRING, | ||||
|   std::string, dest_path, dest, E_STRING, | ||||
|   std::size_t, chunk, chunk, E_FROM_SIZE_T, | ||||
|   std::size_t, total, total, E_FROM_SIZE_T, | ||||
|   std::size_t, complete, complete, E_FROM_SIZE_T, | ||||
|   api_error, result, result, E_FROM_API_FILE_ERROR | ||||
| ); | ||||
|  | ||||
| E_SIMPLE3(download_end, normal, true, | ||||
|   std::string, api_path, ap, E_STRING, | ||||
|   std::string, dest_path, dest, E_STRING, | ||||
|   api_error, result, result, E_FROM_API_FILE_ERROR | ||||
| ); | ||||
|  | ||||
| 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_SIMPLE2(download_stored_removed, normal, true, | ||||
|   std::string, api_path, ap, E_STRING, | ||||
|   std::string, dest_path, dest, E_STRING | ||||
| ); | ||||
|  | ||||
| E_SIMPLE3(download_stored_failed, error, true, | ||||
|   std::string, api_path, ap, E_STRING, | ||||
|   std::string, dest_path, dest, E_STRING, | ||||
|   std::string, error, err, E_STRING | ||||
| ); | ||||
|  | ||||
| E_SIMPLE1(item_timeout, normal, true, | ||||
|   std::string, api_path, ap, E_STRING | ||||
| ); | ||||
| // clang-format on | ||||
| } // namespace repertory | ||||
|  | ||||
| #endif // INCLUDE_FILE_MANAGER_EVENTS_HPP_ | ||||
							
								
								
									
										563
									
								
								repertory/librepertory/include/file_manager/file_manager.hpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										563
									
								
								repertory/librepertory/include/file_manager/file_manager.hpp
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,563 @@ | ||||
| /* | ||||
|   Copyright <2018-2024> <scott.e.graves@protonmail.com> | ||||
|  | ||||
|   Permission is hereby granted, free of charge, to any person obtaining a copy | ||||
|   of this software and associated documentation files (the "Software"), to deal | ||||
|   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_FILE_MANAGER_FILE_MANAGER_HPP_ | ||||
| #define INCLUDE_FILE_MANAGER_FILE_MANAGER_HPP_ | ||||
|  | ||||
| #include "database/db_common.hpp" | ||||
| #include "events/event_system.hpp" | ||||
| #include "events/events.hpp" | ||||
| #include "file_manager/i_file_manager.hpp" | ||||
| #include "file_manager/i_open_file.hpp" | ||||
| #include "file_manager/i_upload_manager.hpp" | ||||
| #include "platform/platform.hpp" | ||||
| #include "types/repertory.hpp" | ||||
| #include "utils/native_file.hpp" | ||||
|  | ||||
| namespace repertory { | ||||
| class app_config; | ||||
| class i_provider; | ||||
|  | ||||
| class file_manager final : public i_file_manager, public i_upload_manager { | ||||
|   E_CONSUMER(); | ||||
|  | ||||
| public: | ||||
|   class open_file_base : public i_closeable_open_file { | ||||
|   public: | ||||
|     open_file_base(std::uint64_t chunk_size, std::uint8_t chunk_timeout, | ||||
|                    filesystem_item fsi, i_provider &provider); | ||||
|  | ||||
|     open_file_base(std::uint64_t chunk_size, std::uint8_t chunk_timeout, | ||||
|                    filesystem_item fsi, | ||||
|                    std::map<std::uint64_t, open_file_data> open_data, | ||||
|                    i_provider &provider); | ||||
|  | ||||
|     ~open_file_base() override = default; | ||||
|  | ||||
|   public: | ||||
|     open_file_base() = delete; | ||||
|     open_file_base(const open_file_base &) noexcept = delete; | ||||
|     open_file_base(open_file_base &&) noexcept = delete; | ||||
|     auto operator=(open_file_base &&) noexcept -> open_file_base & = delete; | ||||
|     auto operator=(const open_file_base &) noexcept | ||||
|         -> open_file_base & = delete; | ||||
|  | ||||
|   public: | ||||
|     class download final { | ||||
|     public: | ||||
|       download() = default; | ||||
|  | ||||
|       ~download() = default; | ||||
|  | ||||
|     public: | ||||
|       download(const download &) noexcept = delete; | ||||
|       download(download &&) noexcept = delete; | ||||
|       auto operator=(download &&) noexcept -> download & = delete; | ||||
|       auto operator=(const download &) noexcept -> download & = delete; | ||||
|  | ||||
|     private: | ||||
|       bool complete_{false}; | ||||
|       api_error error_{api_error::success}; | ||||
|       std::mutex mtx_; | ||||
|       std::condition_variable notify_; | ||||
|  | ||||
|     public: | ||||
|       void notify(const api_error &err); | ||||
|  | ||||
|       auto wait() -> api_error; | ||||
|     }; | ||||
|  | ||||
|     class io_item final { | ||||
|     public: | ||||
|       io_item(std::function<api_error()> action) : action_(std::move(action)) {} | ||||
|  | ||||
|       ~io_item() = default; | ||||
|  | ||||
|     public: | ||||
|       io_item() = delete; | ||||
|       io_item(const io_item &) noexcept = delete; | ||||
|       io_item(io_item &&) noexcept = delete; | ||||
|       auto operator=(io_item &&) noexcept -> io_item & = delete; | ||||
|       auto operator=(const io_item &) noexcept -> io_item & = delete; | ||||
|  | ||||
|     private: | ||||
|       std::function<api_error()> action_; | ||||
|       std::mutex mtx_; | ||||
|       std::condition_variable notify_; | ||||
|       std::optional<api_error> result_; | ||||
|  | ||||
|     public: | ||||
|       void action(); | ||||
|  | ||||
|       [[nodiscard]] auto get_result() -> api_error; | ||||
|     }; | ||||
|  | ||||
|   protected: | ||||
|     std::uint64_t chunk_size_; | ||||
|     std::uint8_t chunk_timeout_; | ||||
|     filesystem_item fsi_; | ||||
|     std::size_t last_chunk_size_; | ||||
|     std::map<std::uint64_t, open_file_data> open_data_; | ||||
|     i_provider &provider_; | ||||
|  | ||||
|   private: | ||||
|     api_error error_{api_error::success}; | ||||
|     mutable std::mutex error_mtx_; | ||||
|     stop_type io_stop_requested_{false}; | ||||
|     std::unique_ptr<std::thread> io_thread_; | ||||
|  | ||||
|   protected: | ||||
|     std::unordered_map<std::size_t, std::shared_ptr<download>> | ||||
|         active_downloads_; | ||||
|     mutable std::recursive_mutex file_mtx_; | ||||
|     std::atomic<std::chrono::system_clock::time_point> last_access_{ | ||||
|         std::chrono::system_clock::now()}; | ||||
|     bool modified_{false}; | ||||
|     native_file_ptr nf_; | ||||
|     mutable std::mutex io_thread_mtx_; | ||||
|     std::condition_variable io_thread_notify_; | ||||
|     std::deque<std::shared_ptr<io_item>> io_thread_queue_; | ||||
|     bool removed_{false}; | ||||
|  | ||||
|   private: | ||||
|     void file_io_thread(); | ||||
|  | ||||
|   protected: | ||||
|     [[nodiscard]] auto do_io(std::function<api_error()> action) -> api_error; | ||||
|  | ||||
|     virtual auto is_download_complete() const -> bool = 0; | ||||
|  | ||||
|     void reset_timeout(); | ||||
|  | ||||
|     auto set_api_error(const api_error &e) -> api_error; | ||||
|  | ||||
|   public: | ||||
|     void add(std::uint64_t handle, open_file_data ofd) override; | ||||
|  | ||||
|     [[nodiscard]] auto can_close() const -> bool override; | ||||
|  | ||||
|     auto close() -> bool override; | ||||
|  | ||||
|     [[nodiscard]] auto get_api_error() const -> api_error; | ||||
|  | ||||
|     [[nodiscard]] auto get_api_path() const -> std::string override; | ||||
|  | ||||
|     [[nodiscard]] auto get_chunk_size() const -> std::size_t override { | ||||
|       return chunk_size_; | ||||
|     } | ||||
|  | ||||
|     [[nodiscard]] auto get_file_size() const -> std::uint64_t override; | ||||
|  | ||||
|     [[nodiscard]] auto get_filesystem_item() const -> filesystem_item override; | ||||
|  | ||||
|     [[nodiscard]] auto get_handles() const | ||||
|         -> std::vector<std::uint64_t> override; | ||||
|  | ||||
|     [[nodiscard]] auto get_open_data() const | ||||
|         -> std::map<std::uint64_t, open_file_data> override; | ||||
|  | ||||
|     [[nodiscard]] auto get_open_data(std::uint64_t handle) const | ||||
|         -> open_file_data override; | ||||
|  | ||||
|     [[nodiscard]] auto get_open_file_count() const -> std::size_t override; | ||||
|  | ||||
|     [[nodiscard]] auto get_source_path() const -> std::string override { | ||||
|       return fsi_.source_path; | ||||
|     } | ||||
|  | ||||
|     [[nodiscard]] auto has_handle(std::uint64_t handle) const -> bool override { | ||||
|       return open_data_.find(handle) != open_data_.end(); | ||||
|     } | ||||
|  | ||||
|     [[nodiscard]] auto is_directory() const -> bool override { | ||||
|       return fsi_.directory; | ||||
|     } | ||||
|  | ||||
|     [[nodiscard]] auto is_modified() const -> bool override; | ||||
|  | ||||
|     void remove(std::uint64_t handle) override; | ||||
|  | ||||
|     void set_api_path(const std::string &api_path) override; | ||||
|   }; | ||||
|  | ||||
|   class open_file final : public open_file_base { | ||||
|   public: | ||||
|     open_file(std::uint64_t chunk_size, std::uint8_t chunk_timeout, | ||||
|               filesystem_item fsi, i_provider &provider, i_upload_manager &mgr); | ||||
|  | ||||
|     open_file(std::uint64_t chunk_size, std::uint8_t chunk_timeout, | ||||
|               filesystem_item fsi, | ||||
|               std::map<std::uint64_t, open_file_data> open_data, | ||||
|               i_provider &provider, i_upload_manager &mgr); | ||||
|  | ||||
|     open_file(std::uint64_t chunk_size, std::uint8_t chunk_timeout, | ||||
|               filesystem_item fsi, i_provider &provider, | ||||
|               std::optional<boost::dynamic_bitset<>> read_state, | ||||
|               i_upload_manager &mgr); | ||||
|  | ||||
|   private: | ||||
|     open_file(std::uint64_t chunk_size, std::uint8_t chunk_timeout, | ||||
|               filesystem_item fsi, | ||||
|               std::map<std::uint64_t, open_file_data> open_data, | ||||
|               i_provider &provider, | ||||
|               std::optional<boost::dynamic_bitset<>> read_state, | ||||
|               i_upload_manager &mgr); | ||||
|  | ||||
|   public: | ||||
|     open_file() = delete; | ||||
|     open_file(const open_file &) noexcept = delete; | ||||
|     open_file(open_file &&) noexcept = delete; | ||||
|     auto operator=(open_file &&) noexcept -> open_file & = delete; | ||||
|     auto operator=(const open_file &) noexcept -> open_file & = delete; | ||||
|  | ||||
|   public: | ||||
|     ~open_file() override; | ||||
|  | ||||
|   private: | ||||
|     i_upload_manager &mgr_; | ||||
|  | ||||
|   private: | ||||
|     bool notified_ = false; | ||||
|     std::size_t read_chunk_index_{}; | ||||
|     boost::dynamic_bitset<> read_state_; | ||||
|     std::unique_ptr<std::thread> reader_thread_; | ||||
|     std::unique_ptr<std::thread> download_thread_; | ||||
|     stop_type stop_requested_ = false; | ||||
|  | ||||
|   private: | ||||
|     void download_chunk(std::size_t chunk, bool skip_active, bool should_reset); | ||||
|  | ||||
|     void download_range(std::size_t start_chunk_index, | ||||
|                         std::size_t end_chunk_index_inclusive, | ||||
|                         bool should_reset); | ||||
|  | ||||
|     void set_modified(); | ||||
|  | ||||
|     void update_background_reader(std::size_t read_chunk); | ||||
|  | ||||
|   protected: | ||||
|     auto is_download_complete() const -> bool override { | ||||
|       return read_state_.all(); | ||||
|     } | ||||
|  | ||||
|   public: | ||||
|     auto close() -> bool override; | ||||
|  | ||||
|     [[nodiscard]] auto get_read_state() const | ||||
|         -> boost::dynamic_bitset<> override; | ||||
|  | ||||
|     [[nodiscard]] auto get_read_state(std::size_t chunk) const -> bool override; | ||||
|  | ||||
|     [[nodiscard]] auto is_complete() const -> bool override; | ||||
|  | ||||
|     auto is_write_supported() const -> bool override { return true; } | ||||
|  | ||||
|     [[nodiscard]] auto native_operation(native_operation_callback callback) | ||||
|         -> api_error override; | ||||
|  | ||||
|     [[nodiscard]] auto native_operation(std::uint64_t new_file_size, | ||||
|                                         native_operation_callback callback) | ||||
|         -> api_error override; | ||||
|  | ||||
|     void remove(std::uint64_t handle) override; | ||||
|  | ||||
|     [[nodiscard]] auto read(std::size_t read_size, std::uint64_t read_offset, | ||||
|                             data_buffer &data) -> api_error override; | ||||
|  | ||||
|     [[nodiscard]] auto resize(std::uint64_t new_file_size) | ||||
|         -> api_error override; | ||||
|  | ||||
|     [[nodiscard]] auto write(std::uint64_t write_offset, | ||||
|                              const data_buffer &data, | ||||
|                              std::size_t &bytes_written) -> api_error override; | ||||
|   }; | ||||
|  | ||||
|   class ring_buffer_open_file final : public open_file_base { | ||||
|   public: | ||||
|     ring_buffer_open_file(std::string buffer_directory, | ||||
|                           std::uint64_t chunk_size, std::uint8_t chunk_timeout, | ||||
|                           filesystem_item fsi, i_provider &provider); | ||||
|  | ||||
|     ring_buffer_open_file(std::string buffer_directory, | ||||
|                           std::uint64_t chunk_size, std::uint8_t chunk_timeout, | ||||
|                           filesystem_item fsi, i_provider &provider, | ||||
|                           std::size_t ring_size); | ||||
|  | ||||
|     ~ring_buffer_open_file() override; | ||||
|  | ||||
|   public: | ||||
|     ring_buffer_open_file() = delete; | ||||
|     ring_buffer_open_file(const ring_buffer_open_file &) noexcept = delete; | ||||
|     ring_buffer_open_file(ring_buffer_open_file &&) noexcept = delete; | ||||
|     auto operator=(ring_buffer_open_file &&) noexcept | ||||
|         -> ring_buffer_open_file & = delete; | ||||
|     auto operator=(const ring_buffer_open_file &) noexcept | ||||
|         -> ring_buffer_open_file & = delete; | ||||
|  | ||||
|   private: | ||||
|     boost::dynamic_bitset<> ring_state_; | ||||
|     std::size_t total_chunks_; | ||||
|  | ||||
|   private: | ||||
|     std::unique_ptr<std::thread> chunk_forward_thread_; | ||||
|     std::unique_ptr<std::thread> chunk_reverse_thread_; | ||||
|     std::condition_variable chunk_notify_; | ||||
|     mutable std::mutex chunk_mtx_; | ||||
|     std::size_t current_chunk_{}; | ||||
|     std::size_t first_chunk_{}; | ||||
|     std::size_t last_chunk_; | ||||
|  | ||||
|   private: | ||||
|     auto download_chunk(std::size_t chunk) -> api_error; | ||||
|  | ||||
|     void forward_reader_thread(std::size_t count); | ||||
|  | ||||
|     void reverse_reader_thread(std::size_t count); | ||||
|  | ||||
|   protected: | ||||
|     auto is_download_complete() const -> bool override; | ||||
|  | ||||
|   public: | ||||
|     void forward(std::size_t count); | ||||
|  | ||||
|     [[nodiscard]] auto get_current_chunk() const -> std::size_t { | ||||
|       return current_chunk_; | ||||
|     } | ||||
|  | ||||
|     [[nodiscard]] auto get_first_chunk() const -> std::size_t { | ||||
|       return first_chunk_; | ||||
|     } | ||||
|  | ||||
|     [[nodiscard]] auto get_last_chunk() const -> std::size_t { | ||||
|       return last_chunk_; | ||||
|     } | ||||
|  | ||||
|     [[nodiscard]] auto get_read_state() const | ||||
|         -> boost::dynamic_bitset<> override; | ||||
|  | ||||
|     [[nodiscard]] auto get_read_state(std::size_t chunk) const -> bool override; | ||||
|  | ||||
|     [[nodiscard]] auto get_total_chunks() const -> std::size_t { | ||||
|       return total_chunks_; | ||||
|     } | ||||
|  | ||||
|     [[nodiscard]] auto is_complete() const -> bool override { return true; } | ||||
|  | ||||
|     auto is_write_supported() const -> bool override { return false; } | ||||
|  | ||||
|     [[nodiscard]] auto native_operation(native_operation_callback callback) | ||||
|         -> api_error override; | ||||
|  | ||||
|     [[nodiscard]] auto native_operation(std::uint64_t, | ||||
|                                         native_operation_callback) | ||||
|         -> api_error override { | ||||
|       return api_error::not_supported; | ||||
|     } | ||||
|  | ||||
|     [[nodiscard]] auto read(std::size_t read_size, std::uint64_t read_offset, | ||||
|                             data_buffer &data) -> api_error override; | ||||
|  | ||||
|     [[nodiscard]] auto resize(std::uint64_t) -> api_error override { | ||||
|       return api_error::not_supported; | ||||
|     } | ||||
|  | ||||
|     void reverse(std::size_t count); | ||||
|  | ||||
|     void set(std::size_t first_chunk, std::size_t current_chunk); | ||||
|  | ||||
|     void set_api_path(const std::string &api_path) override; | ||||
|  | ||||
|     [[nodiscard]] auto write(std::uint64_t, const data_buffer &, std::size_t &) | ||||
|         -> api_error override { | ||||
|       return api_error::not_supported; | ||||
|     } | ||||
|   }; | ||||
|  | ||||
|   class upload final { | ||||
|   public: | ||||
|     upload(filesystem_item fsi, i_provider &provider); | ||||
|  | ||||
|     ~upload(); | ||||
|  | ||||
|   public: | ||||
|     upload() = delete; | ||||
|     upload(const upload &) noexcept = delete; | ||||
|     upload(upload &&) noexcept = delete; | ||||
|     auto operator=(upload &&) noexcept -> upload & = delete; | ||||
|     auto operator=(const upload &) noexcept -> upload & = delete; | ||||
|  | ||||
|   private: | ||||
|     filesystem_item fsi_; | ||||
|     i_provider &provider_; | ||||
|  | ||||
|   private: | ||||
|     bool cancelled_ = false; | ||||
|     api_error error_ = api_error::success; | ||||
|     std::unique_ptr<std::thread> thread_; | ||||
|     stop_type stop_requested_ = false; | ||||
|  | ||||
|   private: | ||||
|     void upload_thread(); | ||||
|  | ||||
|   public: | ||||
|     void cancel(); | ||||
|  | ||||
|     [[nodiscard]] auto get_api_error() const -> api_error { return error_; } | ||||
|  | ||||
|     [[nodiscard]] auto get_api_path() const -> std::string { | ||||
|       return fsi_.api_path; | ||||
|     } | ||||
|  | ||||
|     [[nodiscard]] auto get_source_path() const -> std::string { | ||||
|       return fsi_.source_path; | ||||
|     } | ||||
|  | ||||
|     [[nodiscard]] auto is_cancelled() const -> bool { return cancelled_; } | ||||
|  | ||||
|     void stop(); | ||||
|   }; | ||||
|  | ||||
| public: | ||||
|   file_manager(app_config &config, i_provider &provider); | ||||
|  | ||||
|   ~file_manager() override; | ||||
|  | ||||
| public: | ||||
|   file_manager() = delete; | ||||
|   file_manager(const file_manager &) noexcept = delete; | ||||
|   file_manager(file_manager &&) noexcept = delete; | ||||
|   auto operator=(file_manager &&) noexcept -> file_manager & = delete; | ||||
|   auto operator=(const file_manager &) noexcept -> file_manager & = delete; | ||||
|  | ||||
| private: | ||||
|   app_config &config_; | ||||
|   i_provider &provider_; | ||||
|  | ||||
| private: | ||||
|   db::db3_t db_{nullptr}; | ||||
|   std::uint64_t next_handle_{0U}; | ||||
|   mutable std::recursive_mutex open_file_mtx_; | ||||
|   std::unordered_map<std::string, std::shared_ptr<i_closeable_open_file>> | ||||
|       open_file_lookup_; | ||||
|   stop_type stop_requested_{false}; | ||||
|   std::unordered_map<std::string, std::unique_ptr<upload>> upload_lookup_; | ||||
|   mutable std::mutex upload_mtx_; | ||||
|   std::condition_variable upload_notify_; | ||||
|   std::unique_ptr<std::thread> upload_thread_; | ||||
|  | ||||
| private: | ||||
|   void close_timed_out_files(); | ||||
|  | ||||
|   auto get_open_file_by_handle(std::uint64_t handle) const | ||||
|       -> std::shared_ptr<i_closeable_open_file>; | ||||
|  | ||||
|   auto get_open_file_count(const std::string &api_path) const -> std::size_t; | ||||
|  | ||||
|   auto open(const std::string &api_path, bool directory, | ||||
|             const open_file_data &ofd, std::uint64_t &handle, | ||||
|             std::shared_ptr<i_open_file> &file, | ||||
|             std::shared_ptr<i_closeable_open_file> closeable_file) -> api_error; | ||||
|  | ||||
|   void queue_upload(const std::string &api_path, const std::string &source_path, | ||||
|                     bool no_lock); | ||||
|  | ||||
|   void remove_upload(const std::string &api_path, bool no_lock); | ||||
|  | ||||
|   void swap_renamed_items(std::string from_api_path, std::string to_api_path); | ||||
|  | ||||
|   void upload_completed(const file_upload_completed &evt); | ||||
|  | ||||
|   void upload_handler(); | ||||
|  | ||||
| public: | ||||
|   [[nodiscard]] auto get_next_handle() -> std::uint64_t; | ||||
|  | ||||
|   auto handle_file_rename(const std::string &from_api_path, | ||||
|                           const std::string &to_api_path) -> api_error; | ||||
|  | ||||
|   void queue_upload(const i_open_file &file) override; | ||||
|  | ||||
|   void remove_resume(const std::string &api_path, | ||||
|                      const std::string &source_path) override; | ||||
|  | ||||
|   void remove_upload(const std::string &api_path) override; | ||||
|  | ||||
|   void store_resume(const i_open_file &file) override; | ||||
|  | ||||
| public: | ||||
|   void close(std::uint64_t handle); | ||||
|  | ||||
|   void close_all(const std::string &api_path); | ||||
|  | ||||
|   [[nodiscard]] auto create(const std::string &api_path, api_meta_map &meta, | ||||
|                             open_file_data ofd, std::uint64_t &handle, | ||||
|                             std::shared_ptr<i_open_file> &file) -> api_error; | ||||
|  | ||||
|   [[nodiscard]] auto evict_file(const std::string &api_path) -> bool override; | ||||
|  | ||||
|   [[nodiscard]] auto get_directory_items(const std::string &api_path) const | ||||
|       -> directory_item_list override; | ||||
|  | ||||
|   [[nodiscard]] auto get_open_file(std::uint64_t handle, bool write_supported, | ||||
|                                    std::shared_ptr<i_open_file> &file) -> bool; | ||||
|  | ||||
|   [[nodiscard]] auto get_open_file_count() const -> std::size_t; | ||||
|  | ||||
|   [[nodiscard]] auto get_open_files() const | ||||
|       -> std::unordered_map<std::string, std::size_t> override; | ||||
|  | ||||
|   [[nodiscard]] auto get_open_handle_count() const -> std::size_t; | ||||
|  | ||||
|   [[nodiscard]] auto get_stored_downloads() const -> std::vector<json>; | ||||
|  | ||||
|   [[nodiscard]] auto has_no_open_file_handles() const -> bool override; | ||||
|  | ||||
|   [[nodiscard]] auto is_processing(const std::string &api_path) const | ||||
|       -> bool override; | ||||
|  | ||||
| #ifdef PROJECT_TESTING | ||||
|   [[nodiscard]] auto open(std::shared_ptr<i_closeable_open_file> of, | ||||
|                           const open_file_data &ofd, std::uint64_t &handle, | ||||
|                           std::shared_ptr<i_open_file> &file) -> api_error; | ||||
| #endif | ||||
|   [[nodiscard]] auto open(const std::string &api_path, bool directory, | ||||
|                           const open_file_data &ofd, std::uint64_t &handle, | ||||
|                           std::shared_ptr<i_open_file> &file) -> api_error; | ||||
|  | ||||
|   [[nodiscard]] auto remove_file(const std::string &api_path) -> api_error; | ||||
|  | ||||
|   [[nodiscard]] auto rename_directory(const std::string &from_api_path, | ||||
|                                       const std::string &to_api_path) | ||||
|       -> api_error; | ||||
|  | ||||
|   [[nodiscard]] auto rename_file(const std::string &from_api_path, | ||||
|                                  const std::string &to_api_path, bool overwrite) | ||||
|       -> api_error; | ||||
|  | ||||
|   void start(); | ||||
|  | ||||
|   void stop(); | ||||
|  | ||||
|   void update_used_space(std::uint64_t &used_space) const override; | ||||
| }; | ||||
| } // namespace repertory | ||||
|  | ||||
| #endif // INCLUDE_FILE_MANAGER_FILE_MANAGER_HPP_ | ||||
| @@ -0,0 +1,53 @@ | ||||
| /* | ||||
|   Copyright <2018-2024> <scott.e.graves@protonmail.com> | ||||
|  | ||||
|   Permission is hereby granted, free of charge, to any person obtaining a copy | ||||
|   of this software and associated documentation files (the "Software"), to deal | ||||
|   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_FILE_MANAGER_I_FILE_MANAGER_HPP_ | ||||
| #define INCLUDE_FILE_MANAGER_I_FILE_MANAGER_HPP_ | ||||
|  | ||||
| #include "types/repertory.hpp" | ||||
|  | ||||
| namespace repertory { | ||||
| class i_provider; | ||||
|  | ||||
| class i_file_manager { | ||||
|   INTERFACE_SETUP(i_file_manager); | ||||
|  | ||||
| public: | ||||
|   [[nodiscard]] virtual auto evict_file(const std::string &api_path) | ||||
|       -> bool = 0; | ||||
|  | ||||
|   [[nodiscard]] virtual auto | ||||
|   get_directory_items(const std::string &api_path) const | ||||
|       -> directory_item_list = 0; | ||||
|  | ||||
|   [[nodiscard]] virtual auto get_open_files() const | ||||
|       -> std::unordered_map<std::string, std::size_t> = 0; | ||||
|  | ||||
|   [[nodiscard]] virtual auto has_no_open_file_handles() const -> bool = 0; | ||||
|  | ||||
|   [[nodiscard]] virtual auto is_processing(const std::string &api_path) const | ||||
|       -> bool = 0; | ||||
|  | ||||
|   virtual void update_used_space(std::uint64_t &used_space) const = 0; | ||||
| }; | ||||
| } // namespace repertory | ||||
|  | ||||
| #endif // INCLUDE_FILE_MANAGER_I_FILE_MANAGER_HPP_ | ||||
							
								
								
									
										107
									
								
								repertory/librepertory/include/file_manager/i_open_file.hpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										107
									
								
								repertory/librepertory/include/file_manager/i_open_file.hpp
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,107 @@ | ||||
| /* | ||||
|   Copyright <2018-2024> <scott.e.graves@protonmail.com> | ||||
|  | ||||
|   Permission is hereby granted, free of charge, to any person obtaining a copy | ||||
|   of this software and associated documentation files (the "Software"), to deal | ||||
|   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_FILE_MANAGER_I_OPEN_FILE_HPP_ | ||||
| #define INCLUDE_FILE_MANAGER_I_OPEN_FILE_HPP_ | ||||
|  | ||||
| #include "types/repertory.hpp" | ||||
|  | ||||
| namespace repertory { | ||||
| class i_open_file { | ||||
|   INTERFACE_SETUP(i_open_file); | ||||
|  | ||||
| public: | ||||
|   using native_operation_callback = std::function<api_error(native_handle)>; | ||||
|  | ||||
| public: | ||||
|   [[nodiscard]] virtual auto get_api_path() const -> std::string = 0; | ||||
|  | ||||
|   [[nodiscard]] virtual auto get_chunk_size() const -> std::size_t = 0; | ||||
|  | ||||
|   [[nodiscard]] virtual auto get_file_size() const -> std::uint64_t = 0; | ||||
|  | ||||
|   [[nodiscard]] virtual auto get_filesystem_item() const -> filesystem_item = 0; | ||||
|  | ||||
|   [[nodiscard]] virtual auto get_open_data() const | ||||
|       -> std::map<std::uint64_t, open_file_data> = 0; | ||||
|  | ||||
|   [[nodiscard]] virtual auto get_open_data(std::uint64_t handle) const | ||||
|       -> open_file_data = 0; | ||||
|  | ||||
|   [[nodiscard]] virtual auto get_open_file_count() const -> std::size_t = 0; | ||||
|  | ||||
|   [[nodiscard]] virtual auto get_read_state() const | ||||
|       -> boost::dynamic_bitset<> = 0; | ||||
|  | ||||
|   [[nodiscard]] virtual auto get_read_state(std::size_t chunk) const | ||||
|       -> bool = 0; | ||||
|  | ||||
|   [[nodiscard]] virtual auto get_source_path() const -> std::string = 0; | ||||
|  | ||||
|   [[nodiscard]] virtual auto is_directory() const -> bool = 0; | ||||
|  | ||||
|   [[nodiscard]] virtual auto has_handle(std::uint64_t handle) const -> bool = 0; | ||||
|  | ||||
|   [[nodiscard]] virtual auto | ||||
|   native_operation(native_operation_callback callback) -> api_error = 0; | ||||
|  | ||||
|   [[nodiscard]] virtual auto | ||||
|   native_operation(std::uint64_t new_file_size, | ||||
|                    native_operation_callback callback) -> api_error = 0; | ||||
|  | ||||
|   [[nodiscard]] virtual auto read(std::size_t read_size, | ||||
|                                   std::uint64_t read_offset, data_buffer &data) | ||||
|       -> api_error = 0; | ||||
|  | ||||
|   [[nodiscard]] virtual auto resize(std::uint64_t new_file_size) | ||||
|       -> api_error = 0; | ||||
|  | ||||
|   virtual void set_api_path(const std::string &api_path) = 0; | ||||
|  | ||||
|   [[nodiscard]] virtual auto write(std::uint64_t write_offset, | ||||
|                                    const data_buffer &data, | ||||
|                                    std::size_t &bytes_written) -> api_error = 0; | ||||
| }; | ||||
|  | ||||
| class i_closeable_open_file : public i_open_file { | ||||
|   INTERFACE_SETUP(i_closeable_open_file); | ||||
|  | ||||
| public: | ||||
|   virtual void add(std::uint64_t handle, open_file_data ofd) = 0; | ||||
|  | ||||
|   [[nodiscard]] virtual auto can_close() const -> bool = 0; | ||||
|  | ||||
|   virtual auto close() -> bool = 0; | ||||
|  | ||||
|   [[nodiscard]] virtual auto get_handles() const | ||||
|       -> std::vector<std::uint64_t> = 0; | ||||
|  | ||||
|   [[nodiscard]] virtual auto is_complete() const -> bool = 0; | ||||
|  | ||||
|   [[nodiscard]] virtual auto is_modified() const -> bool = 0; | ||||
|  | ||||
|   [[nodiscard]] virtual auto is_write_supported() const -> bool = 0; | ||||
|  | ||||
|   virtual void remove(std::uint64_t handle) = 0; | ||||
| }; | ||||
| } // namespace repertory | ||||
|  | ||||
| #endif // INCLUDE_FILE_MANAGER_I_OPEN_FILE_HPP_ | ||||
| @@ -0,0 +1,43 @@ | ||||
| /* | ||||
|   Copyright <2018-2024> <scott.e.graves@protonmail.com> | ||||
|  | ||||
|   Permission is hereby granted, free of charge, to any person obtaining a copy | ||||
|   of this software and associated documentation files (the "Software"), to deal | ||||
|   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_FILE_MANAGER_I_UPLOAD_MANAGER_HPP_ | ||||
| #define INCLUDE_FILE_MANAGER_I_UPLOAD_MANAGER_HPP_ | ||||
|  | ||||
| namespace repertory { | ||||
| class i_open_file; | ||||
|  | ||||
| class i_upload_manager { | ||||
|   INTERFACE_SETUP(i_upload_manager); | ||||
|  | ||||
| public: | ||||
|   virtual void queue_upload(const i_open_file &o) = 0; | ||||
|  | ||||
|   virtual void remove_resume(const std::string &api_path, | ||||
|                              const std::string &source_path) = 0; | ||||
|  | ||||
|   virtual void remove_upload(const std::string &api_path) = 0; | ||||
|  | ||||
|   virtual void store_resume(const i_open_file &o) = 0; | ||||
| }; | ||||
| } // namespace repertory | ||||
|  | ||||
| #endif // INCLUDE_FILE_MANAGER_I_UPLOAD_MANAGER_HPP_ | ||||
							
								
								
									
										31
									
								
								repertory/librepertory/include/initialize.hpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										31
									
								
								repertory/librepertory/include/initialize.hpp
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,31 @@ | ||||
| /* | ||||
|   Copyright <2018-2024> <scott.e.graves@protonmail.com> | ||||
|  | ||||
|   Permission is hereby granted, free of charge, to any person obtaining a copy | ||||
|   of this software and associated documentation files (the "Software"), to deal | ||||
|   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 LIBREPERTORY_INCLUDE_INITIALIZE_HPP_ | ||||
| #define LIBREPERTORY_INCLUDE_INITIALIZE_HPP_ | ||||
|  | ||||
| namespace repertory { | ||||
| void project_cleanup(); | ||||
|  | ||||
| [[nodiscard]] auto project_initialize() -> bool; | ||||
| } // namespace repertory | ||||
|  | ||||
| #endif // LIBREPERTORY_INCLUDE_INITIALIZE_HPP_ | ||||
							
								
								
									
										28
									
								
								repertory/librepertory/include/platform/platform.hpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										28
									
								
								repertory/librepertory/include/platform/platform.hpp
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,28 @@ | ||||
| /* | ||||
|   Copyright <2018-2024> <scott.e.graves@protonmail.com> | ||||
|  | ||||
|   Permission is hereby granted, free of charge, to any person obtaining a copy | ||||
|   of this software and associated documentation files (the "Software"), to deal | ||||
|   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_ | ||||
							
								
								
									
										81
									
								
								repertory/librepertory/include/platform/unix_platform.hpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										81
									
								
								repertory/librepertory/include/platform/unix_platform.hpp
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,81 @@ | ||||
| /* | ||||
|   Copyright <2018-2024> <scott.e.graves@protonmail.com> | ||||
|  | ||||
|   Permission is hereby granted, free of charge, to any person obtaining a copy | ||||
|   of this software and associated documentation files (the "Software"), to deal | ||||
|   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 "types/repertory.hpp" | ||||
|  | ||||
| namespace repertory { | ||||
| class i_provider; | ||||
|  | ||||
| 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: | ||||
|   [[nodiscard]] static auto get_state_directory() -> std::string; | ||||
|  | ||||
|   [[nodiscard]] static auto get_lock_data_file() -> std::string; | ||||
|  | ||||
|   [[nodiscard]] auto get_lock_file() -> std::string; | ||||
|  | ||||
| private: | ||||
|   [[nodiscard]] static auto wait_for_lock(int fd, | ||||
|                                           std::uint8_t retry_count = 30u) | ||||
|       -> int; | ||||
|  | ||||
| public: | ||||
|   [[nodiscard]] auto get_mount_state(json &mount_state) -> bool; | ||||
|  | ||||
|   [[nodiscard]] auto grab_lock(std::uint8_t retry_count = 30u) -> lock_result; | ||||
|  | ||||
|   [[nodiscard]] auto set_mount_state(bool active, | ||||
|                                      const std::string &mount_location, int pid) | ||||
|       -> bool; | ||||
| }; | ||||
|  | ||||
| [[nodiscard]] auto create_meta_attributes( | ||||
|     std::uint64_t accessed_date, std::uint32_t attributes, | ||||
|     std::uint64_t changed_date, std::uint64_t creation_date, bool directory, | ||||
|     std::uint32_t gid, const std::string &key, std::uint32_t mode, | ||||
|     std::uint64_t modified_date, std::uint32_t osx_backup, | ||||
|     std::uint32_t osx_flags, std::uint64_t size, const std::string &source_path, | ||||
|     std::uint32_t uid, std::uint64_t written_date) -> api_meta_map; | ||||
|  | ||||
| [[nodiscard]] auto provider_meta_handler(i_provider &provider, bool directory, | ||||
|                                          const api_file &file) -> api_error; | ||||
| } // namespace repertory | ||||
|  | ||||
| #endif // _WIN32 | ||||
| #endif // INCLUDE_PLATFORM_UNIXPLATFORM_HPP_ | ||||
							
								
								
									
										86
									
								
								repertory/librepertory/include/platform/win32_platform.hpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										86
									
								
								repertory/librepertory/include/platform/win32_platform.hpp
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,86 @@ | ||||
| /* | ||||
|   Copyright <2018-2024> <scott.e.graves@protonmail.com> | ||||
|  | ||||
|   Permission is hereby granted, free of charge, to any person obtaining a copy | ||||
|   of this software and associated documentation files (the "Software"), to deal | ||||
|   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 "app_config.hpp" | ||||
| #include "types/repertory.hpp" | ||||
|  | ||||
| namespace repertory { | ||||
| class i_provider; | ||||
|  | ||||
| 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: | ||||
|   [[nodiscard]] auto get_mount_state(const provider_type &pt, json &mount_state) | ||||
|       -> bool; | ||||
|  | ||||
|   [[nodiscard]] auto get_mount_state(json &mount_state) -> bool; | ||||
|  | ||||
|   [[nodiscard]] auto get_unique_id() const -> std::string { return unique_id_; } | ||||
|  | ||||
|   [[nodiscard]] auto grab_lock(std::uint8_t retry_count = 30) -> lock_result; | ||||
|  | ||||
|   void release(); | ||||
|  | ||||
|   [[nodiscard]] auto set_mount_state(bool active, | ||||
|                                      const std::string &mount_location, | ||||
|                                      const std::int64_t &pid) -> bool; | ||||
| }; | ||||
|  | ||||
| [[nodiscard]] auto create_meta_attributes( | ||||
|     std::uint64_t accessed_date, std::uint32_t attributes, | ||||
|     std::uint64_t changed_date, std::uint64_t creation_date, bool directory, | ||||
|     std::uint32_t gid, const std::string &key, std::uint32_t mode, | ||||
|     std::uint64_t modified_date, std::uint32_t osx_backup, | ||||
|     std::uint32_t osx_flags, std::uint64_t size, const std::string &source_path, | ||||
|     std::uint32_t uid, std::uint64_t written_date) -> api_meta_map; | ||||
|  | ||||
| [[nodiscard]] auto provider_meta_handler(i_provider &provider, bool directory, | ||||
|                                          const api_file &file) -> api_error; | ||||
| } // namespace repertory | ||||
|  | ||||
| #endif // _WIN32 | ||||
| #endif // INCLUDE_PLATFORM_WINPLATFORM_HPP_ | ||||
							
								
								
									
										201
									
								
								repertory/librepertory/include/providers/base_provider.hpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										201
									
								
								repertory/librepertory/include/providers/base_provider.hpp
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,201 @@ | ||||
| /* | ||||
|   Copyright <2018-2024> <scott.e.graves@protonmail.com> | ||||
|  | ||||
|   Permission is hereby granted, free of charge, to any person obtaining a copy | ||||
|   of this software and associated documentation files (the "Software"), to deal | ||||
|   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 "providers/i_provider.hpp" | ||||
| #include "providers/meta_db.hpp" | ||||
| #include "types/repertory.hpp" | ||||
|  | ||||
| namespace repertory { | ||||
| class app_config; | ||||
| class i_file_manager; | ||||
| class i_http_comm; | ||||
|  | ||||
| class base_provider : public i_provider { | ||||
| public: | ||||
|   base_provider(app_config &config, i_http_comm &comm) | ||||
|       : config_(config), comm_(comm) {} | ||||
|  | ||||
| private: | ||||
|   app_config &config_; | ||||
|   i_http_comm &comm_; | ||||
|  | ||||
| private: | ||||
|   api_item_added_callback api_item_added_; | ||||
|   std::unique_ptr<meta_db> db3_; | ||||
|   i_file_manager *fm_{}; | ||||
|  | ||||
| private: | ||||
|   void remove_deleted_files(); | ||||
|  | ||||
| protected: | ||||
|   [[nodiscard]] static auto create_api_file(std::string path, std::string key, | ||||
|                                             std::uint64_t size) -> api_file; | ||||
|  | ||||
|   [[nodiscard]] static auto create_api_file(std::string path, | ||||
|                                             std::uint64_t size, | ||||
|                                             api_meta_map &meta) -> api_file; | ||||
|  | ||||
|   [[nodiscard]] virtual auto create_directory_impl(const std::string &api_path, | ||||
|                                                    api_meta_map &meta) | ||||
|       -> api_error = 0; | ||||
|  | ||||
|   [[nodiscard]] virtual auto | ||||
|   create_file_extra(const std::string & /* api_path */, | ||||
|                     api_meta_map & /* meta */) -> api_error { | ||||
|     return api_error::success; | ||||
|   } | ||||
|  | ||||
|   [[nodiscard]] auto get_api_item_added() -> api_item_added_callback & { | ||||
|     return api_item_added_; | ||||
|   } | ||||
|  | ||||
|   [[nodiscard]] auto get_api_item_added() const | ||||
|       -> const api_item_added_callback & { | ||||
|     return api_item_added_; | ||||
|   } | ||||
|  | ||||
|   [[nodiscard]] auto get_comm() const -> i_http_comm & { return comm_; } | ||||
|  | ||||
|   [[nodiscard]] auto get_config() -> app_config & { return config_; } | ||||
|  | ||||
|   [[nodiscard]] auto get_config() const -> const app_config & { | ||||
|     return config_; | ||||
|   } | ||||
|  | ||||
|   [[nodiscard]] auto get_db() -> meta_db & { return *db3_; } | ||||
|  | ||||
|   [[nodiscard]] virtual auto | ||||
|   get_directory_items_impl(const std::string &api_path, | ||||
|                            directory_item_list &list) const -> api_error = 0; | ||||
|  | ||||
|   [[nodiscard]] auto get_file_mgr() -> i_file_manager * { return fm_; } | ||||
|  | ||||
|   [[nodiscard]] auto get_file_mgr() const -> const i_file_manager * { | ||||
|     return fm_; | ||||
|   } | ||||
|  | ||||
|   [[nodiscard]] virtual auto get_used_drive_space_impl() const | ||||
|       -> std::uint64_t = 0; | ||||
|  | ||||
|   [[nodiscard]] virtual auto remove_directory_impl(const std::string &api_path) | ||||
|       -> api_error = 0; | ||||
|  | ||||
|   [[nodiscard]] virtual auto remove_file_impl(const std::string &api_path) | ||||
|       -> api_error = 0; | ||||
|  | ||||
|   [[nodiscard]] virtual auto upload_file_impl(const std::string &api_path, | ||||
|                                               const std::string &source_path, | ||||
|                                               stop_type &stop_requested) | ||||
|       -> api_error = 0; | ||||
|  | ||||
| public: | ||||
|   [[nodiscard]] auto | ||||
|   create_directory_clone_source_meta(const std::string &source_api_path, | ||||
|                                      const std::string &api_path) | ||||
|       -> api_error override; | ||||
|  | ||||
|   [[nodiscard]] auto create_directory(const std::string &api_path, | ||||
|                                       api_meta_map &meta) -> api_error override; | ||||
|  | ||||
|   [[nodiscard]] auto create_file(const std::string &api_path, | ||||
|                                  api_meta_map &meta) -> api_error override; | ||||
|  | ||||
|   [[nodiscard]] auto get_api_path_from_source(const std::string &source_path, | ||||
|                                               std::string &api_path) const | ||||
|       -> api_error override; | ||||
|  | ||||
|   [[nodiscard]] auto get_directory_items(const std::string &api_path, | ||||
|                                          directory_item_list &list) const | ||||
|       -> api_error override; | ||||
|  | ||||
|   [[nodiscard]] auto get_file_size(const std::string &api_path, | ||||
|                                    std::uint64_t &file_size) const | ||||
|       -> api_error override; | ||||
|  | ||||
|   [[nodiscard]] auto get_filesystem_item(const std::string &api_path, | ||||
|                                          bool directory, | ||||
|                                          filesystem_item &fsi) const | ||||
|       -> api_error override; | ||||
|  | ||||
|   [[nodiscard]] auto get_filesystem_item_and_file(const std::string &api_path, | ||||
|                                                   api_file &f, | ||||
|                                                   filesystem_item &fsi) const | ||||
|       -> api_error override; | ||||
|  | ||||
|   [[nodiscard]] auto | ||||
|   get_filesystem_item_from_source_path(const std::string &source_path, | ||||
|                                        filesystem_item &fsi) const | ||||
|       -> api_error override; | ||||
|  | ||||
|   [[nodiscard]] auto get_item_meta(const std::string &api_path, | ||||
|                                    api_meta_map &meta) const | ||||
|       -> api_error override; | ||||
|  | ||||
|   [[nodiscard]] auto get_item_meta(const std::string &api_path, | ||||
|                                    const std::string &key, | ||||
|                                    std::string &value) const | ||||
|       -> api_error override; | ||||
|  | ||||
|   [[nodiscard]] auto get_pinned_files() const | ||||
|       -> std::vector<std::string> override; | ||||
|  | ||||
|   [[nodiscard]] auto get_total_item_count() const -> std::uint64_t override; | ||||
|  | ||||
|   [[nodiscard]] auto get_used_drive_space() const -> std::uint64_t override; | ||||
|  | ||||
|   [[nodiscard]] auto is_file_writeable(const std::string &api_path) const | ||||
|       -> bool override; | ||||
|  | ||||
|   [[nodiscard]] auto remove_directory(const std::string &api_path) | ||||
|       -> api_error override; | ||||
|  | ||||
|   [[nodiscard]] auto remove_file(const std::string &api_path) | ||||
|       -> api_error override; | ||||
|  | ||||
|   [[nodiscard]] auto remove_item_meta(const std::string &api_path, | ||||
|                                       const std::string &key) | ||||
|       -> api_error override; | ||||
|  | ||||
|   [[nodiscard]] auto set_item_meta(const std::string &api_path, | ||||
|                                    const std::string &key, | ||||
|                                    const std::string &value) | ||||
|       -> api_error override; | ||||
|  | ||||
|   [[nodiscard]] auto set_item_meta(const std::string &api_path, | ||||
|                                    const api_meta_map &meta) | ||||
|       -> api_error override; | ||||
|  | ||||
|   [[nodiscard]] auto start(api_item_added_callback api_item_added, | ||||
|                            i_file_manager *mgr) -> bool override; | ||||
|  | ||||
|   void stop() override; | ||||
|  | ||||
|   [[nodiscard]] auto upload_file(const std::string &api_path, | ||||
|                                  const std::string &source_path, | ||||
|                                  stop_type &stop_requested) | ||||
|       -> api_error override; | ||||
| }; | ||||
| } // namespace repertory | ||||
|  | ||||
| #endif // INCLUDE_PROVIDERS_BASE_PROVIDER_HPP_ | ||||
| @@ -0,0 +1,226 @@ | ||||
| /* | ||||
|   Copyright <2018-2024> <scott.e.graves@protonmail.com> | ||||
|  | ||||
|   Permission is hereby granted, free of charge, to any person obtaining a copy | ||||
|   of this software and associated documentation files (the "Software"), to deal | ||||
|   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_ENCRYPT_ENCRYPT_PROVIDER_HPP_ | ||||
| #define INCLUDE_PROVIDERS_ENCRYPT_ENCRYPT_PROVIDER_HPP_ | ||||
|  | ||||
| #include "app_config.hpp" | ||||
| #include "database/db_common.hpp" | ||||
| #include "providers/i_provider.hpp" | ||||
| #include "utils/encrypting_reader.hpp" | ||||
|  | ||||
| namespace repertory { | ||||
| class encrypt_provider final : public i_provider { | ||||
| public: | ||||
|   explicit encrypt_provider(app_config &config); | ||||
|  | ||||
|   ~encrypt_provider() override = default; | ||||
|  | ||||
| public: | ||||
|   encrypt_provider(const encrypt_provider &) = delete; | ||||
|   encrypt_provider(encrypt_provider &&) = delete; | ||||
|   auto operator=(const encrypt_provider &) -> encrypt_provider & = delete; | ||||
|   auto operator=(encrypt_provider &&) -> encrypt_provider & = delete; | ||||
|  | ||||
| private: | ||||
|   struct reader_info final { | ||||
|     std::chrono::system_clock::time_point last_access_time = | ||||
|         std::chrono::system_clock::now(); | ||||
|     std::unique_ptr<utils::encryption::encrypting_reader> reader{}; | ||||
|     std::mutex reader_mtx; | ||||
|   }; | ||||
|  | ||||
| private: | ||||
|   app_config &config_; | ||||
|   db::db3_t db_; | ||||
|  | ||||
| private: | ||||
|   i_file_manager *fm_ = nullptr; | ||||
|   std::unordered_map<std::string, std::shared_ptr<reader_info>> | ||||
|       reader_lookup_{}; | ||||
|   std::recursive_mutex reader_lookup_mtx_{}; | ||||
|  | ||||
| private: | ||||
|   static auto create_api_file(const std::string &api_path, bool directory, | ||||
|                               const std::string &source_path) -> api_file; | ||||
|  | ||||
|   static void create_item_meta(api_meta_map &meta, bool directory, | ||||
|                                const api_file &file); | ||||
|  | ||||
|   auto do_fs_operation(const std::string &api_path, bool directory, | ||||
|                        std::function<api_error(const encrypt_config &cfg, | ||||
|                                                const std::string &source_path)> | ||||
|                            callback) const -> api_error; | ||||
|  | ||||
|   auto | ||||
|   process_directory_entry(const std::filesystem::directory_entry &dir_entry, | ||||
|                           const encrypt_config &cfg, | ||||
|                           std::string &api_path) const -> bool; | ||||
|  | ||||
|   void remove_deleted_files(); | ||||
|  | ||||
| public: | ||||
|   [[nodiscard]] auto create_directory(const std::string &api_path, | ||||
|                                       api_meta_map &meta) -> api_error override; | ||||
|  | ||||
|   [[nodiscard]] auto | ||||
|   create_directory_clone_source_meta(const std::string & /*source_api_path*/, | ||||
|                                      const std::string & /*api_path*/) | ||||
|       -> api_error override { | ||||
|     return api_error::not_implemented; | ||||
|   } | ||||
|  | ||||
|   [[nodiscard]] auto create_file(const std::string & /*api_path*/, | ||||
|                                  api_meta_map & /*meta*/) | ||||
|       -> api_error override { | ||||
|     return api_error::not_implemented; | ||||
|   } | ||||
|  | ||||
|   [[nodiscard]] auto | ||||
|   get_api_path_from_source(const std::string & /*source_path*/, | ||||
|                            std::string & /*api_path*/) const | ||||
|       -> api_error override; | ||||
|  | ||||
|   [[nodiscard]] auto get_directory_item_count(const std::string &api_path) const | ||||
|       -> std::uint64_t override; | ||||
|  | ||||
|   [[nodiscard]] auto get_directory_items(const std::string &api_path, | ||||
|                                          directory_item_list &list) const | ||||
|       -> api_error override; | ||||
|  | ||||
|   [[nodiscard]] auto get_file(const std::string &api_path, api_file &file) const | ||||
|       -> api_error override; | ||||
|  | ||||
|   [[nodiscard]] auto get_file_list(api_file_list &list) const | ||||
|       -> api_error override; | ||||
|  | ||||
|   [[nodiscard]] auto get_file_size(const std::string &api_path, | ||||
|                                    std::uint64_t &file_size) const | ||||
|       -> api_error override; | ||||
|  | ||||
|   [[nodiscard]] auto get_filesystem_item(const std::string &api_path, | ||||
|                                          bool directory, | ||||
|                                          filesystem_item &fsi) const | ||||
|       -> api_error override; | ||||
|  | ||||
|   [[nodiscard]] auto get_filesystem_item_and_file(const std::string &api_path, | ||||
|                                                   api_file &file, | ||||
|                                                   filesystem_item &fsi) const | ||||
|       -> api_error override; | ||||
|  | ||||
|   [[nodiscard]] auto | ||||
|   get_filesystem_item_from_source_path(const std::string &source_path, | ||||
|                                        filesystem_item &fsi) const | ||||
|       -> api_error override; | ||||
|  | ||||
|   [[nodiscard]] auto get_pinned_files() const | ||||
|       -> std::vector<std::string> override; | ||||
|  | ||||
|   [[nodiscard]] auto get_item_meta(const std::string &api_path, | ||||
|                                    api_meta_map &meta) const | ||||
|       -> api_error override; | ||||
|  | ||||
|   [[nodiscard]] auto get_item_meta(const std::string &api_path, | ||||
|                                    const std::string &key, | ||||
|                                    std::string &value) const | ||||
|       -> api_error override; | ||||
|  | ||||
|   [[nodiscard]] auto get_total_drive_space() const -> std::uint64_t override; | ||||
|  | ||||
|   [[nodiscard]] auto get_total_item_count() const -> std::uint64_t override; | ||||
|  | ||||
|   [[nodiscard]] auto get_provider_type() const -> provider_type override { | ||||
|     return provider_type::encrypt; | ||||
|   } | ||||
|  | ||||
|   [[nodiscard]] auto get_used_drive_space() const -> std::uint64_t override; | ||||
|  | ||||
|   [[nodiscard]] auto is_direct_only() const -> bool override { return true; } | ||||
|  | ||||
|   [[nodiscard]] auto is_directory(const std::string &api_path, | ||||
|                                   bool &exists) const -> api_error override; | ||||
|  | ||||
|   [[nodiscard]] auto is_file(const std::string &api_path, bool &exists) const | ||||
|       -> api_error override; | ||||
|  | ||||
|   [[nodiscard]] auto is_file_writeable(const std::string &api_path) const | ||||
|       -> bool override; | ||||
|  | ||||
|   [[nodiscard]] auto is_online() const -> bool override; | ||||
|  | ||||
|   [[nodiscard]] auto is_rename_supported() const -> bool override; | ||||
|  | ||||
|   [[nodiscard]] auto read_file_bytes(const std::string &api_path, | ||||
|                                      std::size_t size, std::uint64_t offset, | ||||
|                                      data_buffer &data, | ||||
|                                      stop_type &stop_requested) | ||||
|       -> api_error override; | ||||
|  | ||||
|   [[nodiscard]] auto remove_directory(const std::string & /*api_path*/) | ||||
|       -> api_error override { | ||||
|     return api_error::not_implemented; | ||||
|   } | ||||
|  | ||||
|   [[nodiscard]] auto remove_file(const std::string & /*api_path*/) | ||||
|       -> api_error override { | ||||
|     return api_error::not_implemented; | ||||
|   } | ||||
|  | ||||
|   [[nodiscard]] auto remove_item_meta(const std::string & /*api_path*/, | ||||
|                                       const std::string & /*key*/) | ||||
|       -> api_error override { | ||||
|     return api_error::success; | ||||
|   } | ||||
|  | ||||
|   [[nodiscard]] auto rename_file(const std::string & /*from_api_path*/, | ||||
|                                  const std::string & /*to_api_path*/) | ||||
|       -> api_error override { | ||||
|     return api_error::not_implemented; | ||||
|   } | ||||
|  | ||||
|   [[nodiscard]] auto set_item_meta(const std::string & /*api_path*/, | ||||
|                                    const std::string & /*key*/, | ||||
|                                    const std::string & /*value*/) | ||||
|       -> api_error override { | ||||
|     return api_error::success; | ||||
|   } | ||||
|  | ||||
|   [[nodiscard]] auto set_item_meta(const std::string & /*api_path*/, | ||||
|                                    const api_meta_map & /*meta*/) | ||||
|       -> api_error override { | ||||
|     return api_error::success; | ||||
|   } | ||||
|  | ||||
|   [[nodiscard]] auto start(api_item_added_callback api_item_added, | ||||
|                            i_file_manager *mgr) -> bool override; | ||||
|  | ||||
|   void stop() override; | ||||
|  | ||||
|   [[nodiscard]] auto upload_file(const std::string & /*api_path*/, | ||||
|                                  const std::string & /*source_path*/, | ||||
|                                  stop_type & /*stop_requested*/) | ||||
|       -> api_error override { | ||||
|     return api_error::not_implemented; | ||||
|   } | ||||
| }; | ||||
| } // namespace repertory | ||||
|  | ||||
| #endif // INCLUDE_PROVIDERS_ENCRYPT_ENCRYPT_PROVIDER_HPP_ | ||||
							
								
								
									
										157
									
								
								repertory/librepertory/include/providers/i_provider.hpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										157
									
								
								repertory/librepertory/include/providers/i_provider.hpp
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,157 @@ | ||||
| /* | ||||
|   Copyright <2018-2024> <scott.e.graves@protonmail.com> | ||||
|  | ||||
|   Permission is hereby granted, free of charge, to any person obtaining a copy | ||||
|   of this software and associated documentation files (the "Software"), to deal | ||||
|   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 "types/repertory.hpp" | ||||
|  | ||||
| namespace repertory { | ||||
| class i_file_manager; | ||||
|  | ||||
| class i_provider { | ||||
|   INTERFACE_SETUP(i_provider); | ||||
|  | ||||
| public: | ||||
|   [[nodiscard]] virtual auto create_directory(const std::string &api_path, | ||||
|                                               api_meta_map &meta) | ||||
|       -> api_error = 0; | ||||
|  | ||||
|   [[nodiscard]] virtual auto | ||||
|   create_directory_clone_source_meta(const std::string &source_api_path, | ||||
|                                      const std::string &api_path) | ||||
|       -> api_error = 0; | ||||
|  | ||||
|   [[nodiscard]] virtual auto create_file(const std::string &api_path, | ||||
|                                          api_meta_map &meta) -> api_error = 0; | ||||
|  | ||||
|   [[nodiscard]] virtual auto | ||||
|   get_api_path_from_source(const std::string &source_path, | ||||
|                            std::string &api_path) const -> api_error = 0; | ||||
|  | ||||
|   [[nodiscard]] virtual auto | ||||
|   get_directory_item_count(const std::string &api_path) const | ||||
|       -> std::uint64_t = 0; | ||||
|  | ||||
|   [[nodiscard]] virtual auto | ||||
|   get_directory_items(const std::string &api_path, | ||||
|                       directory_item_list &list) const -> api_error = 0; | ||||
|  | ||||
|   [[nodiscard]] virtual auto get_file(const std::string &api_path, | ||||
|                                       api_file &file) const -> api_error = 0; | ||||
|  | ||||
|   [[nodiscard]] virtual auto get_file_list(api_file_list &list) const | ||||
|       -> api_error = 0; | ||||
|  | ||||
|   [[nodiscard]] virtual auto get_file_size(const std::string &api_path, | ||||
|                                            std::uint64_t &file_size) const | ||||
|       -> api_error = 0; | ||||
|  | ||||
|   [[nodiscard]] virtual auto get_filesystem_item(const std::string &api_path, | ||||
|                                                  bool directory, | ||||
|                                                  filesystem_item &fsi) const | ||||
|       -> api_error = 0; | ||||
|  | ||||
|   [[nodiscard]] virtual auto | ||||
|   get_filesystem_item_and_file(const std::string &api_path, api_file &file, | ||||
|                                filesystem_item &fsi) const -> api_error = 0; | ||||
|  | ||||
|   [[nodiscard]] virtual auto | ||||
|   get_filesystem_item_from_source_path(const std::string &source_path, | ||||
|                                        filesystem_item &fsi) const | ||||
|       -> api_error = 0; | ||||
|  | ||||
|   [[nodiscard]] virtual auto get_item_meta(const std::string &api_path, | ||||
|                                            api_meta_map &meta) const | ||||
|       -> api_error = 0; | ||||
|  | ||||
|   [[nodiscard]] virtual auto get_item_meta(const std::string &api_path, | ||||
|                                            const std::string &key, | ||||
|                                            std::string &value) const | ||||
|       -> api_error = 0; | ||||
|  | ||||
|   [[nodiscard]] virtual auto get_pinned_files() const | ||||
|       -> std::vector<std::string> = 0; | ||||
|  | ||||
|   [[nodiscard]] virtual auto get_provider_type() const -> provider_type = 0; | ||||
|  | ||||
|   [[nodiscard]] virtual auto get_total_drive_space() const -> std::uint64_t = 0; | ||||
|  | ||||
|   [[nodiscard]] virtual auto get_total_item_count() const -> std::uint64_t = 0; | ||||
|  | ||||
|   [[nodiscard]] virtual auto get_used_drive_space() const -> std::uint64_t = 0; | ||||
|  | ||||
|   [[nodiscard]] virtual auto is_direct_only() const -> bool = 0; | ||||
|  | ||||
|   [[nodiscard]] virtual auto is_directory(const std::string &api_path, | ||||
|                                           bool &exists) const -> api_error = 0; | ||||
|  | ||||
|   [[nodiscard]] virtual auto is_file(const std::string &api_path, | ||||
|                                      bool &exists) const -> api_error = 0; | ||||
|  | ||||
|   [[nodiscard]] virtual auto | ||||
|   is_file_writeable(const std::string &api_path) const -> bool = 0; | ||||
|  | ||||
|   [[nodiscard]] virtual auto is_online() const -> bool = 0; | ||||
|  | ||||
|   [[nodiscard]] virtual auto is_rename_supported() const -> bool = 0; | ||||
|  | ||||
|   [[nodiscard]] virtual auto | ||||
|   read_file_bytes(const std::string &api_path, std::size_t size, | ||||
|                   std::uint64_t offset, data_buffer &data, | ||||
|                   stop_type &stop_requested) -> api_error = 0; | ||||
|  | ||||
|   [[nodiscard]] virtual auto remove_directory(const std::string &api_path) | ||||
|       -> api_error = 0; | ||||
|  | ||||
|   [[nodiscard]] virtual auto remove_file(const std::string &api_path) | ||||
|       -> api_error = 0; | ||||
|  | ||||
|   [[nodiscard]] virtual auto remove_item_meta(const std::string &api_path, | ||||
|                                               const std::string &key) | ||||
|       -> api_error = 0; | ||||
|  | ||||
|   [[nodiscard]] virtual auto rename_file(const std::string &from_api_path, | ||||
|                                          const std::string &to_api_path) | ||||
|       -> api_error = 0; | ||||
|  | ||||
|   [[nodiscard]] virtual auto set_item_meta(const std::string &api_path, | ||||
|                                            const std::string &key, | ||||
|                                            const std::string &value) | ||||
|       -> api_error = 0; | ||||
|  | ||||
|   [[nodiscard]] virtual auto set_item_meta(const std::string &api_path, | ||||
|                                            const api_meta_map &meta) | ||||
|       -> api_error = 0; | ||||
|  | ||||
|   [[nodiscard]] virtual auto start(api_item_added_callback api_item_added, | ||||
|                                    i_file_manager *mgr) -> bool = 0; | ||||
|  | ||||
|   virtual void stop() = 0; | ||||
|  | ||||
|   [[nodiscard]] virtual auto upload_file(const std::string &api_path, | ||||
|                                          const std::string &source_path, | ||||
|                                          stop_type &stop_requested) | ||||
|       -> api_error = 0; | ||||
| }; | ||||
| } // namespace repertory | ||||
|  | ||||
| #endif // INCLUDE_PROVIDERS_I_PROVIDER_HPP_ | ||||
							
								
								
									
										84
									
								
								repertory/librepertory/include/providers/meta_db.hpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										84
									
								
								repertory/librepertory/include/providers/meta_db.hpp
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,84 @@ | ||||
| /* | ||||
|   Copyright <2018-2024> <scott.e.graves@protonmail.com> | ||||
|  | ||||
|   Permission is hereby granted, free of charge, to any person obtaining a copy | ||||
|   of this software and associated documentation files (the "Software"), to deal | ||||
|   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_META_DB_HPP_ | ||||
| #define INCLUDE_PROVIDERS_META_DB_HPP_ | ||||
|  | ||||
| #include "database/db_common.hpp" | ||||
| #include "types/repertory.hpp" | ||||
|  | ||||
| namespace repertory { | ||||
| class app_config; | ||||
|  | ||||
| class meta_db final { | ||||
| public: | ||||
|   meta_db(const app_config &cfg); | ||||
|   ~meta_db(); | ||||
|  | ||||
|   meta_db(const meta_db &) = delete; | ||||
|   meta_db(meta_db &&) = delete; | ||||
|   auto operator=(const meta_db &) -> meta_db & = delete; | ||||
|   auto operator=(meta_db &&) -> meta_db & = delete; | ||||
|  | ||||
| private: | ||||
|   db::db3_t db_; | ||||
|   constexpr static const auto table_name = "meta"; | ||||
|  | ||||
| private: | ||||
|   [[nodiscard]] auto update_item_meta(const std::string &api_path, | ||||
|                                       api_meta_map meta) -> api_error; | ||||
|  | ||||
| public: | ||||
|   [[nodiscard]] auto get_api_path(const std::string &source_path, | ||||
|                                   std::string &api_path) -> api_error; | ||||
|  | ||||
|   [[nodiscard]] auto get_api_path_list() -> std::vector<std::string>; | ||||
|  | ||||
|   [[nodiscard]] auto get_item_meta(const std::string &api_path, | ||||
|                                    api_meta_map &meta) -> api_error; | ||||
|  | ||||
|   [[nodiscard]] auto get_item_meta(const std::string &api_path, | ||||
|                                    const std::string &key, | ||||
|                                    std::string &value) const -> api_error; | ||||
|  | ||||
|   [[nodiscard]] auto get_pinned_files() const -> std::vector<std::string>; | ||||
|  | ||||
|   [[nodiscard]] auto get_total_item_count() const -> std::uint64_t; | ||||
|  | ||||
|   void remove_api_path(const std::string &api_path); | ||||
|  | ||||
|   [[nodiscard]] auto remove_item_meta(const std::string &api_path, | ||||
|                                       const std::string &key) -> api_error; | ||||
|  | ||||
|   [[nodiscard]] auto rename_item_meta(const std::string &from_api_path, | ||||
|                                       const std::string &to_api_path) | ||||
|       -> api_error; | ||||
|  | ||||
|   [[nodiscard]] auto set_item_meta(const std::string &api_path, | ||||
|                                    const std::string &key, | ||||
|                                    const std::string &value) -> api_error; | ||||
|  | ||||
|   [[nodiscard]] auto set_item_meta(const std::string &api_path, | ||||
|                                    const api_meta_map &meta) -> api_error; | ||||
| }; | ||||
| } // namespace repertory | ||||
|  | ||||
| #endif // INCLUDE_PROVIDERS_META_DB_HPP_ | ||||
							
								
								
									
										36
									
								
								repertory/librepertory/include/providers/provider.hpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										36
									
								
								repertory/librepertory/include/providers/provider.hpp
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,36 @@ | ||||
| /* | ||||
|   Copyright <2018-2024> <scott.e.graves@protonmail.com> | ||||
|  | ||||
|   Permission is hereby granted, free of charge, to any person obtaining a copy | ||||
|   of this software and associated documentation files (the "Software"), to deal | ||||
|   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 "types/repertory.hpp" | ||||
|  | ||||
| namespace repertory { | ||||
| class app_config; | ||||
| class i_provider; | ||||
|  | ||||
| [[nodiscard]] auto create_provider(const provider_type &prov, | ||||
|                                    app_config &config) | ||||
|     -> std::unique_ptr<i_provider>; | ||||
| } // namespace repertory | ||||
|  | ||||
| #endif // INCLUDE_PROVIDERS_PROVIDER_HPP_ | ||||
							
								
								
									
										145
									
								
								repertory/librepertory/include/providers/s3/s3_provider.hpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										145
									
								
								repertory/librepertory/include/providers/s3/s3_provider.hpp
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,145 @@ | ||||
| /* | ||||
|   Copyright <2018-2024> <scott.e.graves@protonmail.com> | ||||
|  | ||||
|   Permission is hereby granted, free of charge, to any person obtaining a copy | ||||
|   of this software and associated documentation files (the "Software"), to deal | ||||
|   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 "providers/base_provider.hpp" | ||||
| #include "types/repertory.hpp" | ||||
|  | ||||
| namespace repertory { | ||||
| class app_config; | ||||
| class i_file_manager; | ||||
| class i_http_comm; | ||||
| struct head_object_result; | ||||
|  | ||||
| class s3_provider final : public base_provider { | ||||
| public: | ||||
|   s3_provider(app_config &config, i_http_comm &comm); | ||||
|  | ||||
|   ~s3_provider() override = default; | ||||
|  | ||||
| public: | ||||
|   s3_provider(const s3_provider &) = delete; | ||||
|   s3_provider(s3_provider &&) = delete; | ||||
|   auto operator=(const s3_provider &) -> s3_provider & = delete; | ||||
|   auto operator=(s3_provider &&) -> s3_provider & = delete; | ||||
|  | ||||
| private: | ||||
|   [[nodiscard]] auto add_if_not_found(api_file &file, | ||||
|                                       const std::string &object_name) const | ||||
|       -> api_error; | ||||
|  | ||||
|   [[nodiscard]] auto create_file_extra(const std::string &api_path, | ||||
|                                        api_meta_map &meta) | ||||
|       -> api_error override; | ||||
|  | ||||
|   [[nodiscard]] auto create_path_directories(const std::string &api_path, | ||||
|                                              const std::string &key) const | ||||
|       -> api_error; | ||||
|  | ||||
|   [[nodiscard]] auto decrypt_object_name(std::string &object_name) const | ||||
|       -> api_error; | ||||
|  | ||||
|   [[nodiscard]] auto | ||||
|   get_object_info(bool directory, const std::string &api_path, | ||||
|                   bool &is_encrypted, std::string &object_name, | ||||
|                   head_object_result &result) const -> api_error; | ||||
|  | ||||
|   [[nodiscard]] auto | ||||
|   get_object_list(std::string &response_data, long &response_code, | ||||
|                   std::optional<std::string> delimiter = std::nullopt, | ||||
|                   std::optional<std::string> prefix = std::nullopt) const | ||||
|       -> bool; | ||||
|  | ||||
| protected: | ||||
|   [[nodiscard]] auto create_directory_impl(const std::string &api_path, | ||||
|                                            api_meta_map &meta) | ||||
|       -> api_error override; | ||||
|  | ||||
|   [[nodiscard]] auto get_directory_items_impl(const std::string &api_path, | ||||
|                                               directory_item_list &list) const | ||||
|       -> api_error override; | ||||
|  | ||||
|   [[nodiscard]] auto get_used_drive_space_impl() const | ||||
|       -> std::uint64_t override; | ||||
|  | ||||
|   [[nodiscard]] auto remove_directory_impl(const std::string &api_path) | ||||
|       -> api_error override; | ||||
|  | ||||
|   [[nodiscard]] auto remove_file_impl(const std::string &api_path) | ||||
|       -> api_error override; | ||||
|  | ||||
|   [[nodiscard]] auto upload_file_impl(const std::string &api_path, | ||||
|                                       const std::string &source_path, | ||||
|                                       stop_type &stop_requested) | ||||
|       -> api_error override; | ||||
|  | ||||
| public: | ||||
|   [[nodiscard]] auto get_directory_item_count(const std::string &api_path) const | ||||
|       -> std::uint64_t override; | ||||
|  | ||||
|   [[nodiscard]] auto get_file(const std::string &api_path, api_file &file) const | ||||
|       -> api_error override; | ||||
|  | ||||
|   [[nodiscard]] auto get_file_list(api_file_list &list) const | ||||
|       -> api_error override; | ||||
|  | ||||
|   [[nodiscard]] auto get_total_drive_space() const -> std::uint64_t override; | ||||
|  | ||||
|   [[nodiscard]] auto get_provider_type() const -> provider_type override { | ||||
|     return provider_type::s3; | ||||
|   } | ||||
|  | ||||
|   [[nodiscard]] auto is_direct_only() const -> bool override { return false; } | ||||
|  | ||||
|   [[nodiscard]] auto is_directory(const std::string &api_path, | ||||
|                                   bool &exists) const -> api_error override; | ||||
|  | ||||
|   [[nodiscard]] auto is_file(const std::string &api_path, bool &exists) const | ||||
|       -> api_error override; | ||||
|  | ||||
|   [[nodiscard]] auto is_online() const -> bool override; | ||||
|  | ||||
|   [[nodiscard]] auto is_rename_supported() const -> bool override { | ||||
|     return false; | ||||
|   }; | ||||
|  | ||||
|   [[nodiscard]] auto read_file_bytes(const std::string &api_path, | ||||
|                                      std::size_t size, std::uint64_t offset, | ||||
|                                      data_buffer &data, | ||||
|                                      stop_type &stop_requested) | ||||
|       -> api_error override; | ||||
|  | ||||
|   [[nodiscard]] auto rename_file(const std::string &from_api_path, | ||||
|                                  const std::string &to_api_path) | ||||
|       -> api_error override; | ||||
|  | ||||
|   [[nodiscard]] auto start(api_item_added_callback api_item_added, | ||||
|                            i_file_manager *mgr) -> bool override; | ||||
|  | ||||
|   void stop() override; | ||||
| }; | ||||
| } // namespace repertory | ||||
|  | ||||
| #endif // REPERTORY_ENABLE_S3 | ||||
| #endif // INCLUDE_PROVIDERS_S3_S3_PROVIDER_HPP_ | ||||
							
								
								
									
										122
									
								
								repertory/librepertory/include/providers/sia/sia_provider.hpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										122
									
								
								repertory/librepertory/include/providers/sia/sia_provider.hpp
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,122 @@ | ||||
| /* | ||||
|   Copyright <2018-2024> <scott.e.graves@protonmail.com> | ||||
|  | ||||
|   Permission is hereby granted, free of charge, to any person obtaining a copy | ||||
|   of this software and associated documentation files (the "Software"), to deal | ||||
|   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_SIA_PROVIDER_HPP_ | ||||
| #define INCLUDE_PROVIDERS_SIA_SIA_PROVIDER_HPP_ | ||||
|  | ||||
| #include "providers/base_provider.hpp" | ||||
| #include "types/repertory.hpp" | ||||
|  | ||||
| namespace repertory { | ||||
| class app_config; | ||||
| class i_file_manager; | ||||
| class i_http_comm; | ||||
|  | ||||
| class sia_provider : public base_provider { | ||||
| public: | ||||
|   sia_provider(app_config &config, i_http_comm &comm); | ||||
|  | ||||
|   ~sia_provider() override = default; | ||||
|  | ||||
| public: | ||||
|   sia_provider(const sia_provider &) = delete; | ||||
|   sia_provider(sia_provider &&) = delete; | ||||
|   auto operator=(const sia_provider &) -> sia_provider & = delete; | ||||
|   auto operator=(sia_provider &&) -> sia_provider & = delete; | ||||
|  | ||||
| private: | ||||
|   [[nodiscard]] auto get_object_info(const std::string &api_path, | ||||
|                                      json &object_info) const -> api_error; | ||||
|  | ||||
|   [[nodiscard]] auto get_object_list(const std::string &api_path, | ||||
|                                      nlohmann::json &object_list) const -> bool; | ||||
|  | ||||
| protected: | ||||
|   [[nodiscard]] auto create_directory_impl(const std::string &api_path, | ||||
|                                            api_meta_map &meta) | ||||
|       -> api_error override; | ||||
|  | ||||
|   [[nodiscard]] auto get_directory_items_impl(const std::string &api_path, | ||||
|                                               directory_item_list &list) const | ||||
|       -> api_error override; | ||||
|  | ||||
|   [[nodiscard]] auto get_used_drive_space_impl() const | ||||
|       -> std::uint64_t override; | ||||
|  | ||||
|   [[nodiscard]] auto remove_directory_impl(const std::string &api_path) | ||||
|       -> api_error override; | ||||
|  | ||||
|   [[nodiscard]] auto remove_file_impl(const std::string &api_path) | ||||
|       -> api_error override; | ||||
|  | ||||
|   [[nodiscard]] auto upload_file_impl(const std::string &api_path, | ||||
|                                       const std::string &source_path, | ||||
|                                       stop_type &stop_requested) | ||||
|       -> api_error override; | ||||
|  | ||||
| public: | ||||
|   [[nodiscard]] auto get_directory_item_count(const std::string &api_path) const | ||||
|       -> std::uint64_t override; | ||||
|  | ||||
|   [[nodiscard]] auto get_file(const std::string &api_path, api_file &file) const | ||||
|       -> api_error override; | ||||
|  | ||||
|   [[nodiscard]] auto get_file_list(api_file_list &list) const | ||||
|       -> api_error override; | ||||
|  | ||||
|   [[nodiscard]] auto get_provider_type() const -> provider_type override { | ||||
|     return provider_type::sia; | ||||
|   } | ||||
|  | ||||
|   [[nodiscard]] auto get_total_drive_space() const -> std::uint64_t override; | ||||
|  | ||||
|   [[nodiscard]] auto is_direct_only() const -> bool override { return false; } | ||||
|  | ||||
|   [[nodiscard]] auto is_directory(const std::string &api_path, | ||||
|                                   bool &exists) const -> api_error override; | ||||
|  | ||||
|   [[nodiscard]] auto is_file(const std::string &api_path, bool &exists) const | ||||
|       -> api_error override; | ||||
|  | ||||
|   [[nodiscard]] auto is_online() const -> bool override; | ||||
|  | ||||
|   [[nodiscard]] auto is_rename_supported() const -> bool override { | ||||
|     return true; | ||||
|   } | ||||
|  | ||||
|   [[nodiscard]] auto read_file_bytes(const std::string &api_path, | ||||
|                                      std::size_t size, std::uint64_t offset, | ||||
|                                      data_buffer &buffer, | ||||
|                                      stop_type &stop_requested) | ||||
|       -> api_error override; | ||||
|  | ||||
|   [[nodiscard]] auto rename_file(const std::string &from_api_path, | ||||
|                                  const std::string &to_api_path) | ||||
|       -> api_error override; | ||||
|  | ||||
|   [[nodiscard]] auto start(api_item_added_callback api_item_added, | ||||
|                            i_file_manager *mgr) -> bool override; | ||||
|  | ||||
|   void stop() override; | ||||
| }; | ||||
| } // namespace repertory | ||||
|  | ||||
| #endif // INCLUDE_PROVIDERS_SIA_SIA_PROVIDER_HPP_ | ||||
							
								
								
									
										65
									
								
								repertory/librepertory/include/rpc/client/client.hpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										65
									
								
								repertory/librepertory/include/rpc/client/client.hpp
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,65 @@ | ||||
| /* | ||||
|   Copyright <2018-2024> <scott.e.graves@protonmail.com> | ||||
|  | ||||
|   Permission is hereby granted, free of charge, to any person obtaining a copy | ||||
|   of this software and associated documentation files (the "Software"), to deal | ||||
|   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 "types/rpc.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_; | ||||
|  | ||||
| public: | ||||
|   [[nodiscard]] auto get_drive_information() -> rpc_response; | ||||
|  | ||||
|   [[nodiscard]] auto get_config() -> rpc_response; | ||||
|  | ||||
|   [[nodiscard]] auto get_config_value_by_name(const std::string &name) | ||||
|       -> rpc_response; | ||||
|  | ||||
|   [[nodiscard]] auto get_directory_items(const std::string &api_path) | ||||
|       -> rpc_response; | ||||
|  | ||||
|   [[nodiscard]] auto get_open_files() -> rpc_response; | ||||
|  | ||||
|   [[nodiscard]] auto get_pinned_files() -> rpc_response; | ||||
|  | ||||
|   [[nodiscard]] auto pin_file(const std::string &api_file) -> rpc_response; | ||||
|  | ||||
|   [[nodiscard]] auto pinned_status(const std::string &api_file) -> rpc_response; | ||||
|  | ||||
|   [[nodiscard]] auto set_config_value_by_name(const std::string &name, | ||||
|                                               const std::string &value) | ||||
|       -> rpc_response; | ||||
|  | ||||
|   [[nodiscard]] auto unmount() -> rpc_response; | ||||
|  | ||||
|   [[nodiscard]] auto unpin_file(const std::string &api_file) -> rpc_response; | ||||
| }; | ||||
| } // namespace repertory | ||||
|  | ||||
| #endif // INCLUDE_RPC_CLIENT_CLIENT_HPP_ | ||||
							
								
								
									
										67
									
								
								repertory/librepertory/include/rpc/server/full_server.hpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										67
									
								
								repertory/librepertory/include/rpc/server/full_server.hpp
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,67 @@ | ||||
| /* | ||||
|   Copyright <2018-2024> <scott.e.graves@protonmail.com> | ||||
|  | ||||
|   Permission is hereby granted, free of charge, to any person obtaining a copy | ||||
|   of this software and associated documentation files (the "Software"), to deal | ||||
|   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 "rpc/server/server.hpp" | ||||
|  | ||||
| namespace repertory { | ||||
| class i_file_manager; | ||||
| class i_provider; | ||||
|  | ||||
| class full_server final : public server { | ||||
| public: | ||||
|   explicit full_server(app_config &config, i_provider &provider, | ||||
|                        i_file_manager &fm); | ||||
|  | ||||
|   ~full_server() override = default; | ||||
|  | ||||
| private: | ||||
|   i_provider &provider_; | ||||
|   i_file_manager &fm_; | ||||
|  | ||||
| private: | ||||
|   void handle_get_directory_items(const httplib::Request &req, | ||||
|                                   httplib::Response &res); | ||||
|  | ||||
|   void handle_get_drive_information(const httplib::Request &req, | ||||
|                                     httplib::Response &res); | ||||
|  | ||||
|   void handle_get_open_files(const httplib::Request &req, | ||||
|                              httplib::Response &res); | ||||
|  | ||||
|   void handle_get_pinned_files(const httplib::Request &req, | ||||
|                                httplib::Response &res); | ||||
|  | ||||
|   void handle_get_pinned_status(const httplib::Request &req, | ||||
|                                 httplib::Response &res); | ||||
|  | ||||
|   void handle_pin_file(const httplib::Request &req, httplib::Response &res); | ||||
|  | ||||
|   void handle_unpin_file(const httplib::Request &req, httplib::Response &res); | ||||
|  | ||||
| protected: | ||||
|   void initialize(httplib::Server &inst) override; | ||||
| }; | ||||
| } // namespace repertory | ||||
|  | ||||
| #endif // INCLUDE_RPC_SERVER_FULL_SERVER_HPP_ | ||||
							
								
								
									
										75
									
								
								repertory/librepertory/include/rpc/server/server.hpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										75
									
								
								repertory/librepertory/include/rpc/server/server.hpp
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,75 @@ | ||||
| /* | ||||
|   Copyright <2018-2024> <scott.e.graves@protonmail.com> | ||||
|  | ||||
|   Permission is hereby granted, free of charge, to any person obtaining a copy | ||||
|   of this software and associated documentation files (the "Software"), to deal | ||||
|   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 "types/rpc.hpp" | ||||
|  | ||||
| namespace repertory { | ||||
| class app_config; | ||||
|  | ||||
| class server { | ||||
| public: | ||||
|   explicit server(app_config &config); | ||||
|  | ||||
|   virtual ~server() { stop(); } | ||||
|  | ||||
| private: | ||||
|   app_config &config_; | ||||
|   std::unique_ptr<httplib::Server> server_; | ||||
|   std::unique_ptr<std::thread> server_thread_; | ||||
|   std::mutex start_stop_mutex_; | ||||
|   std::atomic<bool> started_ = false; | ||||
|  | ||||
| private: | ||||
|   // [[nodiscard]] bool check_authorization(const httpserver::http_request | ||||
|   // &request); | ||||
|  | ||||
|   [[nodiscard]] auto check_authorization(const httplib::Request &req) -> bool; | ||||
|  | ||||
|   void handle_get_config(const httplib::Request &req, httplib::Response &res); | ||||
|  | ||||
|   void handle_get_config_value_by_name(const httplib::Request &req, | ||||
|                                        httplib::Response &res); | ||||
|  | ||||
|   void handle_set_config_value_by_name(const httplib::Request &req, | ||||
|                                        httplib::Response &res); | ||||
|  | ||||
|   void handle_unmount(const httplib::Request &req, httplib::Response &res); | ||||
|  | ||||
| protected: | ||||
|   [[nodiscard]] auto get_config() -> app_config & { return config_; } | ||||
|  | ||||
|   [[nodiscard]] auto get_config() const -> const app_config & { | ||||
|     return config_; | ||||
|   } | ||||
|  | ||||
|   virtual void initialize(httplib::Server &inst); | ||||
|  | ||||
| public: | ||||
|   void start(); | ||||
|  | ||||
|   void stop(); | ||||
| }; | ||||
| } // namespace repertory | ||||
|  | ||||
| #endif // INCLUDE_RPC_SERVER_SERVER_HPP_ | ||||
							
								
								
									
										160
									
								
								repertory/librepertory/include/types/remote.hpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										160
									
								
								repertory/librepertory/include/types/remote.hpp
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,160 @@ | ||||
| /* | ||||
|   Copyright <2018-2024> <scott.e.graves@protonmail.com> | ||||
|  | ||||
|   Permission is hereby granted, free of charge, to any person obtaining a copy | ||||
|   of this software and associated documentation files (the "Software"), to deal | ||||
|   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_ | ||||
|  | ||||
| #define PACKET_SERVICE_FUSE 1U | ||||
| #define PACKET_SERVICE_WINFSP 2U | ||||
|  | ||||
| #ifdef _WIN32 | ||||
| #define PACKET_SERVICE_FLAGS PACKET_SERVICE_WINFSP | ||||
| #else | ||||
| #define PACKET_SERVICE_FLAGS PACKET_SERVICE_FUSE | ||||
| #endif | ||||
|  | ||||
| namespace repertory::remote { | ||||
| using block_count = std::uint64_t; | ||||
| using block_size = std::uint32_t; | ||||
| using file_handle = std::uint64_t; | ||||
| using file_mode = std::uint16_t; | ||||
| using file_nlink = std::uint16_t; | ||||
| using file_offset = std::uint64_t; | ||||
| using file_size = std::uint64_t; | ||||
| using file_time = std::uint64_t; | ||||
| using group_id = std::uint32_t; | ||||
| using user_id = std::uint32_t; | ||||
|  | ||||
| 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, | ||||
| }; | ||||
|  | ||||
| inline auto operator|(const open_flags &flag_1, const open_flags &flag_2) | ||||
|     -> open_flags { | ||||
|   using t = std::underlying_type_t<open_flags>; | ||||
|   return static_cast<open_flags>(static_cast<t>(flag_1) | | ||||
|                                  static_cast<t>(flag_2)); | ||||
| } | ||||
|  | ||||
| #ifdef __GNUG__ | ||||
| __attribute__((unused)) | ||||
| #endif | ||||
| inline auto | ||||
| operator|=(open_flags &flag_1, const open_flags &flag_2) -> open_flags & { | ||||
|   flag_1 = flag_1 | flag_2; | ||||
|   return flag_1; | ||||
| } | ||||
|  | ||||
| #ifdef __GNUG__ | ||||
| __attribute__((unused)) | ||||
| #endif | ||||
| inline auto | ||||
| operator&(const open_flags &flag_1, const open_flags &flag_2) -> open_flags { | ||||
|   using t = std::underlying_type_t<open_flags>; | ||||
|   return static_cast<open_flags>(static_cast<t>(flag_1) & | ||||
|                                  static_cast<t>(flag_2)); | ||||
| } | ||||
|  | ||||
| #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 | ||||
| [[nodiscard]] auto create_open_flags(std::uint32_t flags) -> open_flags; | ||||
|  | ||||
| [[nodiscard]] auto create_os_open_flags(const open_flags &flags) | ||||
|     -> std::uint32_t; | ||||
| #endif | ||||
| } // namespace repertory::remote | ||||
|  | ||||
| #endif // INCLUDE_TYPES_REMOTE_HPP_ | ||||
							
								
								
									
										302
									
								
								repertory/librepertory/include/types/repertory.hpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										302
									
								
								repertory/librepertory/include/types/repertory.hpp
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,302 @@ | ||||
| /* | ||||
|   Copyright <2018-2023> <scott.e.graves@protonmail.com> | ||||
|  | ||||
|   Permission is hereby granted, free of charge, to any person obtaining a copy | ||||
|   of this software and associated documentation files (the "Software"), to deal | ||||
|   in the Software without restriction, including without limitation the rights | ||||
|   to use, copy, modify, merge, publish, distribute, sublicense, and/or sell | ||||
|   copies of the Software, and to permit persons to whom the Software is | ||||
|   furnished to do so, subject to the following conditions: | ||||
|  | ||||
|   The above copyright notice and this permission notice shall be included in all | ||||
|   copies or substantial portions of the Software. | ||||
|  | ||||
|   THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||||
|   IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||||
|   FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE | ||||
|   AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | ||||
|   LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | ||||
|   OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE | ||||
|   SOFTWARE. | ||||
| */ | ||||
| #ifndef INCLUDE_TYPES_REPERTORY_HPP_ | ||||
| #define INCLUDE_TYPES_REPERTORY_HPP_ | ||||
|  | ||||
| namespace repertory { | ||||
| constexpr const auto max_time = 0xFFFFFFFFFFFFFFFFULL; | ||||
|  | ||||
| const std::string META_ACCESSED = "accessed"; | ||||
| const std::string META_ATTRIBUTES = "attributes"; | ||||
| const std::string META_BACKUP = "backup"; | ||||
| const std::string META_CHANGED = "changed"; | ||||
| const std::string META_CREATION = "creation"; | ||||
| const std::string META_DIRECTORY = "directory"; | ||||
| const std::string META_GID = "gid"; | ||||
| const std::string META_KEY = "key"; | ||||
| const std::string META_MODE = "mode"; | ||||
| const std::string META_MODIFIED = "modified"; | ||||
| const std::string META_OSXFLAGS = "flags"; | ||||
| const std::string META_PINNED = "pinned"; | ||||
| const std::string META_SIZE = "size"; | ||||
| const std::string META_SOURCE = "source"; | ||||
| const std::string META_UID = "uid"; | ||||
| const std::string META_WRITTEN = "written"; | ||||
|  | ||||
| const std::vector<std::string> META_USED_NAMES = { | ||||
|     META_ACCESSED, META_ATTRIBUTES, META_BACKUP,   META_CHANGED, | ||||
|     META_CREATION, META_DIRECTORY,  META_GID,      META_KEY, | ||||
|     META_MODE,     META_MODIFIED,   META_OSXFLAGS, META_PINNED, | ||||
|     META_SIZE,     META_SOURCE,     META_UID,      META_WRITTEN, | ||||
| }; | ||||
|  | ||||
| using api_meta_map = std::map<std::string, std::string>; | ||||
|  | ||||
| using stop_type = std::atomic<bool>; | ||||
|  | ||||
| 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, | ||||
|   empty_ring_buffer_chunk_size, | ||||
|   empty_ring_buffer_size, | ||||
|   error, | ||||
|   file_in_use, | ||||
|   file_size_mismatch, | ||||
|   incompatible_version, | ||||
|   invalid_handle, | ||||
|   invalid_operation, | ||||
|   invalid_ring_buffer_multiple, | ||||
|   invalid_ring_buffer_size, | ||||
|   invalid_version, | ||||
|   item_exists, | ||||
|   item_not_found, | ||||
|   no_disk_space, | ||||
|   not_implemented, | ||||
|   not_supported, | ||||
|   os_error, | ||||
|   out_of_memory, | ||||
|   permission_denied, | ||||
|   upload_failed, | ||||
|   upload_stopped, | ||||
|   xattr_buffer_small, | ||||
|   xattr_exists, | ||||
|   xattr_not_found, | ||||
|   xattr_too_big, | ||||
|   ERROR_COUNT | ||||
| }; | ||||
|  | ||||
| [[nodiscard]] auto api_error_from_string(std::string_view s) -> api_error; | ||||
|  | ||||
| [[nodiscard]] auto api_error_to_string(const api_error &error) | ||||
|     -> const std::string &; | ||||
|  | ||||
| enum class download_type { direct, fallback, ring_buffer }; | ||||
|  | ||||
| enum class exit_code : std::int32_t { | ||||
|   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, | ||||
|   init_failed = -18, | ||||
| }; | ||||
|  | ||||
| enum http_error_codes : std::int32_t { | ||||
|   ok = 200, | ||||
|   multiple_choices = 300, | ||||
|   not_found = 404, | ||||
| }; | ||||
|  | ||||
| enum class lock_result { | ||||
|   success, | ||||
|   locked, | ||||
|   failure, | ||||
| }; | ||||
|  | ||||
| enum class provider_type : std::size_t { | ||||
|   sia, | ||||
|   remote, | ||||
|   s3, | ||||
|   encrypt, | ||||
|   unknown, | ||||
| }; | ||||
|  | ||||
| #ifdef _WIN32 | ||||
| struct open_file_data { | ||||
|   void *directory_buffer{}; | ||||
| }; | ||||
| #else | ||||
| using open_file_data = int; | ||||
| #endif | ||||
|  | ||||
| struct api_file { | ||||
|   std::string api_path; | ||||
|   std::string api_parent; | ||||
|   std::uint64_t accessed_date{}; | ||||
|   std::uint64_t changed_date{}; | ||||
|   std::uint64_t creation_date{}; | ||||
|   std::uint64_t file_size{}; | ||||
|   std::string key; | ||||
|   std::uint64_t modified_date{}; | ||||
|   std::string source_path; | ||||
| }; | ||||
|  | ||||
| struct directory_item { | ||||
|   std::string api_path; | ||||
|   std::string api_parent; | ||||
|   bool directory{false}; | ||||
|   std::uint64_t size{}; | ||||
|   api_meta_map meta{}; | ||||
|   bool resolved{false}; | ||||
|  | ||||
|   [[nodiscard]] static auto from_json(const json &item) -> directory_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<api_meta_map>(); | ||||
|     return ret; | ||||
|   } | ||||
|  | ||||
|   [[nodiscard]] auto to_json() const -> json { | ||||
|     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 directory{false}; | ||||
|   std::uint64_t size{}; | ||||
|   std::string source_path; | ||||
| }; | ||||
|  | ||||
| struct host_config { | ||||
|   std::string agent_string; | ||||
|   std::string api_password; | ||||
|   std::string api_user; | ||||
|   std::uint16_t api_port{}; | ||||
|   std::string host_name_or_ip{"localhost"}; | ||||
|   std::string path{}; | ||||
|   std::string protocol{"http"}; | ||||
|   std::uint32_t timeout_ms{60000U}; | ||||
|  | ||||
|   auto operator==(const host_config &hc) const noexcept -> bool { | ||||
|     if (&hc != this) { | ||||
|       return agent_string == hc.agent_string && | ||||
|              api_password == hc.api_password && api_user == hc.api_user && | ||||
|              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; | ||||
|     } | ||||
|     return true; | ||||
|   } | ||||
|  | ||||
|   auto operator!=(const host_config &hc) const noexcept -> bool { | ||||
|     if (&hc != this) { | ||||
|       return not(hc == *this); | ||||
|     } | ||||
|     return false; | ||||
|   } | ||||
| }; | ||||
|  | ||||
| #ifdef __GNUG__ | ||||
| __attribute__((unused)) | ||||
| #endif | ||||
| static void | ||||
| to_json(json &j, const host_config &hc) { | ||||
|   j = json{{"AgentString", hc.agent_string}, | ||||
|            {"ApiPassword", hc.api_password}, | ||||
|            {"ApiPort", hc.api_port}, | ||||
|            {"ApiUser", hc.api_user}, | ||||
|            {"HostNameOrIp", hc.host_name_or_ip}, | ||||
|            {"Path", hc.path}, | ||||
|            {"Protocol", hc.protocol}, | ||||
|            {"TimeoutMs", hc.timeout_ms}}; | ||||
| } | ||||
|  | ||||
| #ifdef __GNUG__ | ||||
| __attribute__((unused)) | ||||
| #endif | ||||
| 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("AuthUser").get_to(hc.api_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; | ||||
|   std::uint64_t end; | ||||
| }; | ||||
|  | ||||
| struct encrypt_config { | ||||
|   std::string encryption_token; | ||||
|   std::string path; | ||||
| }; | ||||
|  | ||||
| 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; | ||||
|   bool use_path_style{false}; | ||||
|   bool use_region_in_url{false}; | ||||
| }; | ||||
|  | ||||
| using data_buffer = std::vector<char>; | ||||
|  | ||||
| using api_file_list = std::vector<api_file>; | ||||
| using api_file_provider_callback = std::function<void(api_file &)>; | ||||
| using api_item_added_callback = std::function<api_error(bool, api_file &)>; | ||||
| using directory_item_list = std::vector<directory_item>; | ||||
| using http_headers = std::unordered_map<std::string, std::string>; | ||||
| using http_parameters = std::unordered_map<std::string, std::string>; | ||||
| using http_ranges = std::vector<http_range>; | ||||
| using meta_provider_callback = std::function<void(directory_item &)>; | ||||
| using mutex_lock = std::lock_guard<std::mutex>; | ||||
| using query_parameters = std::map<std::string, std::string>; | ||||
| using recur_mutex_lock = std::lock_guard<std::recursive_mutex>; | ||||
| using unique_mutex_lock = std::unique_lock<std::mutex>; | ||||
| using unique_recur_mutex_lock = std::unique_lock<std::recursive_mutex>; | ||||
| } // namespace repertory | ||||
|  | ||||
| #endif // INCLUDE_TYPES_REPERTORY_HPP_ | ||||
							
								
								
									
										59
									
								
								repertory/librepertory/include/types/rpc.hpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										59
									
								
								repertory/librepertory/include/types/rpc.hpp
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,59 @@ | ||||
| /* | ||||
|   Copyright <2018-2024> <scott.e.graves@protonmail.com> | ||||
|  | ||||
|   Permission is hereby granted, free of charge, to any person obtaining a copy | ||||
|   of this software and associated documentation files (the "Software"), to deal | ||||
|   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_ | ||||
|  | ||||
| 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, | ||||
|   http_error, | ||||
| }; | ||||
|  | ||||
| struct rpc_response { | ||||
|   rpc_response_type response_type; | ||||
|   json data; | ||||
| }; | ||||
|  | ||||
| namespace rpc_method { | ||||
| const std::string get_config = "get_config"; | ||||
| const std::string get_config_value_by_name = "get_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 pin_file = "pin_file"; | ||||
| const std::string pinned_status = "pinned_status"; | ||||
| const std::string set_config_value_by_name = "set_config_value_by_name"; | ||||
| const std::string unmount = "unmount"; | ||||
| const std::string unpin_file = "unpin_file"; | ||||
| } // namespace rpc_method | ||||
| } // namespace repertory | ||||
|  | ||||
| #endif // INCLUDE_TYPES_RPC_HPP_ | ||||
							
								
								
									
										93
									
								
								repertory/librepertory/include/types/s3.hpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										93
									
								
								repertory/librepertory/include/types/s3.hpp
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,93 @@ | ||||
| /* | ||||
|   Copyright <2018-2024> <scott.e.graves@protonmail.com> | ||||
|  | ||||
|   Permission is hereby granted, free of charge, to any person obtaining a copy | ||||
|   of this software and associated documentation files (the "Software"), to deal | ||||
|   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_S3_HPP_ | ||||
| #define INCLUDE_TYPES_S3_HPP_ | ||||
| #if defined(REPERTORY_ENABLE_S3) | ||||
|  | ||||
| #include "types/repertory.hpp" | ||||
| #include "utils/string_utils.hpp" | ||||
| #include "utils/utils.hpp" | ||||
|  | ||||
| namespace repertory { | ||||
| namespace utils::aws { | ||||
| #if _WIN32 | ||||
| [[nodiscard]] inline auto format_time(std::uint64_t t) -> std::uint64_t { | ||||
|   FILETIME ft{}; | ||||
|   utils::unix_time_to_filetime(t, ft); | ||||
|   return static_cast<std::uint64_t>(ft.dwHighDateTime) << 32u | | ||||
|          ft.dwLowDateTime; | ||||
| } | ||||
| #else  // _WIN32 | ||||
| [[nodiscard]] inline auto format_time(std::uint64_t t) -> std::uint64_t { | ||||
|   return t; | ||||
| } | ||||
| #endif // _WIN32 | ||||
| } // namespace utils::aws | ||||
|  | ||||
| using get_key_callback = std::function<std::string()>; | ||||
|  | ||||
| using get_api_file_token_callback = | ||||
|     std::function<std::string(const std::string &api_path)>; | ||||
|  | ||||
| using get_name_callback = std::function<std::string( | ||||
|     const std::string &key, const std::string &object_name)>; | ||||
|  | ||||
| using get_size_callback = std::function<std::uint64_t()>; | ||||
|  | ||||
| using get_token_callback = std::function<std::string()>; | ||||
|  | ||||
| using set_key_callback = std::function<api_error(const std::string &key)>; | ||||
|  | ||||
| using list_directories_result = api_file_list; | ||||
|  | ||||
| using list_files_result = api_file_list; | ||||
|  | ||||
| using list_objects_result = std::vector<directory_item>; | ||||
|  | ||||
| struct head_object_result { | ||||
|   std::uint64_t content_length{}; | ||||
|   std::string content_type{}; | ||||
|   std::uint64_t last_modified{}; | ||||
|  | ||||
|   inline auto from_headers(http_headers headers) -> head_object_result & { | ||||
|     content_length = utils::string::to_uint64(headers["content-length"]); | ||||
|     content_type = headers["content-type"]; | ||||
|     auto date = headers["last-modified"]; | ||||
|     if (not date.empty()) { | ||||
|       struct tm tm1 {}; | ||||
|       // Mon, 17 Dec 2012 02:14:10 GMT | ||||
| #ifdef _WIN32 | ||||
|       utils::strptime(date.c_str(), "%a, %d %b %Y %H:%M:%S %Z", &tm1); | ||||
| #else | ||||
|       strptime(date.c_str(), "%a, %d %b %Y %H:%M:%S %Z", &tm1); | ||||
| #endif | ||||
|       last_modified = | ||||
|           static_cast<std::uint64_t>(mktime(&tm1)) * NANOS_PER_SECOND; | ||||
|     } | ||||
|     return *this; | ||||
|   } | ||||
| }; | ||||
|  | ||||
| } // namespace repertory | ||||
|  | ||||
| #endif | ||||
| #endif // INCLUDE_TYPES_S3_HPP_ | ||||
							
								
								
									
										33
									
								
								repertory/librepertory/include/types/startup_exception.hpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										33
									
								
								repertory/librepertory/include/types/startup_exception.hpp
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,33 @@ | ||||
| /* | ||||
|   Copyright <2018-2024> <scott.e.graves@protonmail.com> | ||||
|  | ||||
|   Permission is hereby granted, free of charge, to any person obtaining a copy | ||||
|   of this software and associated documentation files (the "Software"), to deal | ||||
|   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_ | ||||
|  | ||||
| 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_ | ||||
							
								
								
									
										162
									
								
								repertory/librepertory/include/utils/Base64.hpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										162
									
								
								repertory/librepertory/include/utils/Base64.hpp
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,162 @@ | ||||
| // NOLINTBEGIN | ||||
| #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. | ||||
|  */ | ||||
|  | ||||
| #ifdef __clang__ | ||||
| #pragma clang diagnostic push | ||||
| #pragma clang diagnostic ignored "-Wunknown-warning-option" | ||||
| #endif | ||||
|  | ||||
| #ifdef __GNUC__ | ||||
| #pragma GCC diagnostic push | ||||
| #pragma GCC diagnostic ignored "-Wconversion" | ||||
| #pragma GCC diagnostic ignored "-Wold-style-cast" | ||||
| #pragma GCC diagnostic ignored "-Wuseless-cast" | ||||
| #endif | ||||
|  | ||||
| #include <string> | ||||
| #include <vector> | ||||
|  | ||||
| namespace macaron::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; | ||||
| } | ||||
|  | ||||
| [[maybe_unused]] static std::string Encode(const std::string &data) { | ||||
|   return Encode(&data[0], data.size()); | ||||
| } | ||||
|  | ||||
| [[maybe_unused]] 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 macaron::Base64 | ||||
|  | ||||
| #ifdef __GNUC__ | ||||
| #pragma GCC diagnostic pop | ||||
| #endif | ||||
|  | ||||
| #ifdef __clang__ | ||||
| #pragma clang diagnostic pop | ||||
| #endif | ||||
|  | ||||
| #endif /* _MACARON_BASE64_H_ */ | ||||
|  | ||||
| // NOLINTEND | ||||
							
								
								
									
										49
									
								
								repertory/librepertory/include/utils/action_queue.hpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										49
									
								
								repertory/librepertory/include/utils/action_queue.hpp
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,49 @@ | ||||
| /* | ||||
|   Copyright <2018-2024> <scott.e.graves@protonmail.com> | ||||
|  | ||||
|   Permission is hereby granted, free of charge, to any person obtaining a copy | ||||
|   of this software and associated documentation files (the "Software"), to deal | ||||
|   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_ACTION_QUEUE_HPP_ | ||||
| #define INCLUDE_UTILS_ACTION_QUEUE_HPP_ | ||||
|  | ||||
| #include "utils/single_thread_service_base.hpp" | ||||
|  | ||||
| namespace repertory::utils::action_queue { | ||||
| class action_queue final : single_thread_service_base { | ||||
|   explicit action_queue(const std::string &id, | ||||
|                         std::uint8_t max_concurrent_actions = 5u); | ||||
|  | ||||
| private: | ||||
|   std::string id_; | ||||
|   std::uint8_t max_concurrent_actions_; | ||||
|  | ||||
| private: | ||||
|   std::deque<std::function<void()>> queue_; | ||||
|   mutable std::mutex queue_mtx_; | ||||
|   std::condition_variable queue_notify_; | ||||
|  | ||||
| protected: | ||||
|   void service_function() override; | ||||
|  | ||||
| public: | ||||
|   void push(std::function<void()> action); | ||||
| }; | ||||
| } // namespace repertory::utils::action_queue | ||||
|  | ||||
| #endif // INCLUDE_UTILS_ACTION_QUEUE_HPP_ | ||||
							
								
								
									
										117
									
								
								repertory/librepertory/include/utils/cli_utils.hpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										117
									
								
								repertory/librepertory/include/utils/cli_utils.hpp
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,117 @@ | ||||
| /* | ||||
|   Copyright <2018-2024> <scott.e.graves@protonmail.com> | ||||
|  | ||||
|   Permission is hereby granted, free of charge, to any person obtaining a copy | ||||
|   of this software and associated documentation files (the "Software"), to deal | ||||
|   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 "types/repertory.hpp" | ||||
|  | ||||
| namespace repertory::utils::cli { | ||||
| using option = std::array<std::string, 2>; | ||||
|  | ||||
| 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 encrypt_option = {"-en", "--encrypt"}; | ||||
| static const option drive_information_option = {"-di", "--drive_information"}; | ||||
| #if defined(REPERTORY_ENABLE_S3) | ||||
| static const option name_option = {"-na", "--name"}; | ||||
| static const option s3_option = {"-s3", "--s3"}; | ||||
| #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 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"}; | ||||
| 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, | ||||
|     encrypt_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, | ||||
|     open_files_option, | ||||
|     password_option, | ||||
|     pin_file_option, | ||||
|     pinned_status_option, | ||||
|     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 &prov, | ||||
|                                  const std::string &data_directory); | ||||
|  | ||||
| [[nodiscard]] auto get_provider_type_from_args(std::vector<const char *> args) | ||||
|     -> provider_type; | ||||
|  | ||||
| [[nodiscard]] auto has_option(std::vector<const char *> args, | ||||
|                               const std::string &option_name) -> bool; | ||||
|  | ||||
| [[nodiscard]] auto has_option(std::vector<const char *> args, const option &opt) | ||||
|     -> bool; | ||||
|  | ||||
| [[nodiscard]] auto parse_option(std::vector<const char *> args, | ||||
|                                 const std::string &option_name, | ||||
|                                 std::uint8_t count) -> std::vector<std::string>; | ||||
|  | ||||
| [[nodiscard]] auto parse_string_option(std::vector<const char *> args, | ||||
|                                        const option &opt, std::string &value) | ||||
|     -> exit_code; | ||||
|  | ||||
| [[nodiscard]] auto parse_drive_options(std::vector<const char *> args, | ||||
|                                        provider_type &prov, | ||||
|                                        std::string &data_directory) | ||||
|     -> std::vector<std::string>; | ||||
| } // namespace repertory::utils::cli | ||||
|  | ||||
| #endif // INCLUDE_UTILS_CLI_UTILS_HPP_ | ||||
							
								
								
									
										45
									
								
								repertory/librepertory/include/utils/com_init_wrapper.hpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										45
									
								
								repertory/librepertory/include/utils/com_init_wrapper.hpp
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,45 @@ | ||||
| /* | ||||
|   Copyright <2018-2024> <scott.e.graves@protonmail.com> | ||||
|  | ||||
|   Permission is hereby granted, free of charge, to any person obtaining a copy | ||||
|   of this software and associated documentation files (the "Software"), to deal | ||||
|   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 | ||||
|  | ||||
| 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_ | ||||
							
								
								
									
										145
									
								
								repertory/librepertory/include/utils/encrypting_reader.hpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										145
									
								
								repertory/librepertory/include/utils/encrypting_reader.hpp
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,145 @@ | ||||
| /* | ||||
|   Copyright <2018-2024> <scott.e.graves@protonmail.com> | ||||
|  | ||||
|   Permission is hereby granted, free of charge, to any person obtaining a copy | ||||
|   of this software and associated documentation files (the "Software"), to deal | ||||
|   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 "types/repertory.hpp" | ||||
| #include "utils/file_utils.hpp" | ||||
|  | ||||
| namespace repertory::utils::encryption { | ||||
| using key_type = std::array<unsigned char, 32U>; | ||||
|  | ||||
| class encrypting_reader final { | ||||
| public: | ||||
|   encrypting_reader(const std::string &file_name, | ||||
|                     const std::string &source_path, stop_type &stop_requested, | ||||
|                     const std::string &token, | ||||
|                     std::optional<std::string> relative_parent_path, | ||||
|                     std::size_t error_return = 0U); | ||||
|  | ||||
|   encrypting_reader(const std::string &encrypted_file_path, | ||||
|                     const std::string &source_path, stop_type &stop_requested, | ||||
|                     const std::string &token, std::size_t error_return = 0U); | ||||
|  | ||||
|   encrypting_reader( | ||||
|       const std::string &encrypted_file_path, const std::string &source_path, | ||||
|       stop_type &stop_requested, const std::string &token, | ||||
|       std::vector<std::array<unsigned char, | ||||
|                              crypto_aead_xchacha20poly1305_IETF_NPUBBYTES>> | ||||
|           iv_list, | ||||
|       std::size_t error_return = 0U); | ||||
|  | ||||
|   encrypting_reader(const encrypting_reader &reader); | ||||
|   encrypting_reader(encrypting_reader &&) = delete; | ||||
|  | ||||
|   auto operator=(const encrypting_reader &) -> encrypting_reader & = delete; | ||||
|   auto operator=(encrypting_reader &&) -> encrypting_reader & = delete; | ||||
|  | ||||
|   ~encrypting_reader(); | ||||
|  | ||||
| public: | ||||
|   using iostream = std::basic_iostream<char, std::char_traits<char>>; | ||||
|   using streambuf = std::basic_streambuf<char, std::char_traits<char>>; | ||||
|  | ||||
| private: | ||||
|   const key_type key_; | ||||
|   stop_type &stop_requested_; | ||||
|   const size_t error_return_; | ||||
|   std::unordered_map<std::size_t, data_buffer> chunk_buffers_; | ||||
|   std::string encrypted_file_name_; | ||||
|   std::string encrypted_file_path_; | ||||
|   std::vector< | ||||
|       std::array<unsigned char, crypto_aead_xchacha20poly1305_IETF_NPUBBYTES>> | ||||
|       iv_list_; | ||||
|   std::size_t last_data_chunk_{}; | ||||
|   std::size_t last_data_chunk_size_{}; | ||||
|   std::uint64_t read_offset_{}; | ||||
|   native_file_ptr source_file_; | ||||
|   std::uint64_t total_size_{}; | ||||
|  | ||||
| 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: | ||||
|   auto reader_function(char *buffer, size_t size, size_t nitems) -> size_t; | ||||
|  | ||||
| public: | ||||
|   [[nodiscard]] static auto calculate_decrypted_size(std::uint64_t total_size) | ||||
|       -> std::uint64_t; | ||||
|  | ||||
|   [[nodiscard]] static auto | ||||
|   calculate_encrypted_size(const std::string &source_path) -> std::uint64_t; | ||||
|  | ||||
|   [[nodiscard]] auto create_iostream() const -> std::shared_ptr<iostream>; | ||||
|  | ||||
|   [[nodiscard]] static constexpr auto get_encrypted_chunk_size() | ||||
|       -> std::size_t { | ||||
|     return encrypted_chunk_size_; | ||||
|   } | ||||
|  | ||||
|   [[nodiscard]] static constexpr auto get_data_chunk_size() -> std::size_t { | ||||
|     return data_chunk_size_; | ||||
|   } | ||||
|  | ||||
|   [[nodiscard]] auto get_encrypted_file_name() const -> std::string { | ||||
|     return encrypted_file_name_; | ||||
|   } | ||||
|  | ||||
|   [[nodiscard]] auto get_encrypted_file_path() const -> std::string { | ||||
|     return encrypted_file_path_; | ||||
|   } | ||||
|  | ||||
|   [[nodiscard]] auto get_error_return() const -> std::size_t { | ||||
|     return error_return_; | ||||
|   } | ||||
|  | ||||
|   [[nodiscard]] static constexpr auto get_header_size() -> std::size_t { | ||||
|     return header_size_; | ||||
|   } | ||||
|  | ||||
|   [[nodiscard]] auto get_iv_list() -> std::vector< | ||||
|       std::array<unsigned char, crypto_aead_xchacha20poly1305_IETF_NPUBBYTES>> { | ||||
|     return iv_list_; | ||||
|   } | ||||
|  | ||||
|   [[nodiscard]] auto get_stop_requested() const -> bool { | ||||
|     return stop_requested_; | ||||
|   } | ||||
|  | ||||
|   [[nodiscard]] auto get_total_size() const -> std::uint64_t { | ||||
|     return total_size_; | ||||
|   } | ||||
|  | ||||
|   [[nodiscard]] static auto reader_function(char *buffer, size_t size, | ||||
|                                             size_t nitems, void *instream) | ||||
|       -> size_t { | ||||
|     return reinterpret_cast<encrypting_reader *>(instream)->reader_function( | ||||
|         buffer, size, nitems); | ||||
|   } | ||||
|  | ||||
|   void set_read_position(std::uint64_t position) { read_offset_ = position; } | ||||
| }; | ||||
| } // namespace repertory::utils::encryption | ||||
|  | ||||
| #endif // INCLUDE_UTILS_ENCRYPTING_READER_HPP_ | ||||
							
								
								
									
										160
									
								
								repertory/librepertory/include/utils/encryption.hpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										160
									
								
								repertory/librepertory/include/utils/encryption.hpp
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,160 @@ | ||||
| /* | ||||
|   Copyright <2018-2024> <scott.e.graves@protonmail.com> | ||||
|  | ||||
|   Permission is hereby granted, free of charge, to any person obtaining a copy | ||||
|   of this software and associated documentation files (the "Software"), to deal | ||||
|   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_ENCRYPTION_HPP_ | ||||
| #define INCLUDE_UTILS_ENCRYPTION_HPP_ | ||||
|  | ||||
| #include "types/repertory.hpp" | ||||
| #include "utils/encrypting_reader.hpp" | ||||
|  | ||||
| namespace repertory::utils::encryption { | ||||
| using reader_func = std::function<api_error(data_buffer &cypher_text, | ||||
|                                             std::uint64_t start_offset, | ||||
|                                             std::uint64_t end_offset)>; | ||||
| // Prototypes | ||||
| [[nodiscard]] auto decrypt_file_path(const std::string &encryption_token, | ||||
|                                      std::string &file_path) -> api_error; | ||||
|  | ||||
| [[nodiscard]] auto decrypt_file_name(const std::string &encryption_token, | ||||
|                                      std::string &file_name) -> api_error; | ||||
|  | ||||
| [[nodiscard]] auto generate_key(const std::string &encryption_token) | ||||
|     -> key_type; | ||||
|  | ||||
| [[nodiscard]] auto read_encrypted_range(const http_range &range, | ||||
|                                         const key_type &key, reader_func reader, | ||||
|                                         std::uint64_t total_size, | ||||
|                                         data_buffer &data) -> api_error; | ||||
|  | ||||
| // Implementations | ||||
| template <typename result> | ||||
| [[nodiscard]] inline auto decrypt_data(const key_type &key, const char *buffer, | ||||
|                                        std::size_t buffer_size, result &res) | ||||
|     -> bool { | ||||
|   const auto header_size = | ||||
|       static_cast<std::uint32_t>(encrypting_reader::get_header_size()); | ||||
|   if (buffer_size > header_size) { | ||||
|     const std::uint32_t size = | ||||
|         boost::endian::native_to_big(static_cast<std::uint32_t>(buffer_size)); | ||||
|     res.resize(buffer_size - header_size); | ||||
|     return crypto_aead_xchacha20poly1305_ietf_decrypt_detached( | ||||
|                reinterpret_cast<unsigned char *>(&res[0u]), nullptr, | ||||
|                reinterpret_cast<const unsigned char *>(&buffer[header_size]), | ||||
|                res.size(), | ||||
|                reinterpret_cast<const unsigned char *>( | ||||
|                    &buffer[crypto_aead_xchacha20poly1305_IETF_NPUBBYTES]), | ||||
|                reinterpret_cast<const unsigned char *>(&size), sizeof(size), | ||||
|                reinterpret_cast<const unsigned char *>(buffer), | ||||
|                key.data()) == 0; | ||||
|   } | ||||
|  | ||||
|   return false; | ||||
| } | ||||
|  | ||||
| template <typename buffer, typename result> | ||||
| [[nodiscard]] inline auto decrypt_data(const key_type &key, const buffer &buf, | ||||
|                                        result &res) -> bool { | ||||
|   return decrypt_data<result>(key, &buf[0u], buf.size(), res); | ||||
| } | ||||
|  | ||||
| template <typename buffer, typename result> | ||||
| [[nodiscard]] inline auto decrypt_data(const std::string &encryption_token, | ||||
|                                        const buffer &buf, result &res) -> bool { | ||||
|   return decrypt_data<buffer, result>(generate_key(encryption_token), buf, res); | ||||
| } | ||||
|  | ||||
| template <typename result> | ||||
| [[nodiscard]] inline auto decrypt_data(const std::string &encryption_token, | ||||
|                                        const char *buffer, | ||||
|                                        std::size_t buffer_size, result &res) | ||||
|     -> bool { | ||||
|   return decrypt_data<result>(generate_key(encryption_token), buffer, | ||||
|                               buffer_size, res); | ||||
| } | ||||
|  | ||||
| template <typename result> | ||||
| inline void | ||||
| encrypt_data(const std::array<unsigned char, | ||||
|                               crypto_aead_xchacha20poly1305_IETF_NPUBBYTES> &iv, | ||||
|              const key_type &key, const char *buffer, std::size_t buffer_size, | ||||
|              result &res) { | ||||
|   std::array<unsigned char, crypto_aead_xchacha20poly1305_IETF_ABYTES> mac{}; | ||||
|  | ||||
|   const auto header_size = | ||||
|       static_cast<std::uint32_t>(encrypting_reader::get_header_size()); | ||||
|  | ||||
|   const std::uint32_t size = boost::endian::native_to_big( | ||||
|       static_cast<std::uint32_t>(buffer_size + header_size)); | ||||
|  | ||||
|   res.resize(buffer_size + header_size); | ||||
|  | ||||
|   unsigned long long mac_length{}; | ||||
|   if (crypto_aead_xchacha20poly1305_ietf_encrypt_detached( | ||||
|           reinterpret_cast<unsigned char *>(&res[header_size]), mac.data(), | ||||
|           &mac_length, reinterpret_cast<const unsigned char *>(buffer), | ||||
|           buffer_size, reinterpret_cast<const unsigned char *>(&size), | ||||
|           sizeof(size), nullptr, iv.data(), key.data()) != 0) { | ||||
|     throw std::runtime_error("encryption failed"); | ||||
|   } | ||||
|  | ||||
|   std::memcpy(&res[0u], &iv[0u], iv.size()); | ||||
|   std::memcpy(&res[iv.size()], &mac[0u], mac.size()); | ||||
| } | ||||
|  | ||||
| template <typename result> | ||||
| inline void encrypt_data(const key_type &key, const char *buffer, | ||||
|                          std::size_t buffer_size, result &res) { | ||||
|   std::array<unsigned char, crypto_aead_xchacha20poly1305_IETF_NPUBBYTES> iv{}; | ||||
|   randombytes_buf(iv.data(), iv.size()); | ||||
|  | ||||
|   encrypt_data<result>(iv, key, buffer, buffer_size, res); | ||||
| } | ||||
|  | ||||
| template <typename result> | ||||
| inline void encrypt_data(const std::string &encryption_token, | ||||
|                          const char *buffer, std::size_t buffer_size, | ||||
|                          result &res) { | ||||
|   encrypt_data<result>(generate_key(encryption_token), buffer, buffer_size, | ||||
|                        res); | ||||
| } | ||||
|  | ||||
| template <typename buffer, typename result> | ||||
| inline void encrypt_data(const std::string &encryption_token, const buffer &buf, | ||||
|                          result &res) { | ||||
|   encrypt_data<result>(generate_key(encryption_token), &buf[0u], buf.size(), | ||||
|                        res); | ||||
| } | ||||
|  | ||||
| template <typename buffer, typename result> | ||||
| inline void encrypt_data(const key_type &key, const buffer &buf, result &res) { | ||||
|   encrypt_data<result>(key, &buf[0u], buf.size(), res); | ||||
| } | ||||
|  | ||||
| template <typename buffer, typename result> | ||||
| inline void | ||||
| encrypt_data(const std::array<unsigned char, | ||||
|                               crypto_aead_xchacha20poly1305_IETF_NPUBBYTES> &iv, | ||||
|              const key_type &key, const buffer &buf, result &res) { | ||||
|   encrypt_data<result>(iv, key, &buf[0u], buf.size(), res); | ||||
| } | ||||
| } // namespace repertory::utils::encryption | ||||
|  | ||||
| #endif // INCLUDE_UTILS_ENCRYPTION_HPP_ | ||||
							
								
								
									
										84
									
								
								repertory/librepertory/include/utils/error_utils.hpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										84
									
								
								repertory/librepertory/include/utils/error_utils.hpp
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,84 @@ | ||||
| /* | ||||
|   Copyright <2018-2024> <scott.e.graves@protonmail.com> | ||||
|  | ||||
|   Permission is hereby granted, free of charge, to any person obtaining a copy | ||||
|   of this software and associated documentation files (the "Software"), to deal | ||||
|   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_ERROR_UTILS_HPP_ | ||||
| #define INCLUDE_UTILS_ERROR_UTILS_HPP_ | ||||
|  | ||||
| #include "types/repertory.hpp" | ||||
|  | ||||
| namespace repertory::utils::error { | ||||
| void raise_error(std::string function, std::string_view msg); | ||||
|  | ||||
| void raise_error(std::string function, const api_error &err, | ||||
|                  std::string_view msg); | ||||
|  | ||||
| void raise_error(std::string function, const std::exception &exception, | ||||
|                  std::string_view msg); | ||||
|  | ||||
| void raise_error(std::string function, std::int64_t err, std::string_view msg); | ||||
|  | ||||
| void raise_error(std::string function, const json &err, std::string_view msg); | ||||
|  | ||||
| void raise_error(std::string function, const api_error &err, | ||||
|                  std::string_view file_path, std::string_view msg); | ||||
|  | ||||
| void raise_error(std::string function, std::int64_t err, | ||||
|                  std::string_view file_path, std::string_view msg); | ||||
|  | ||||
| void raise_error(std::string function, const std::exception &exception, | ||||
|                  std::string_view file_path, std::string_view msg); | ||||
|  | ||||
| void raise_api_path_error(std::string function, std::string_view api_path, | ||||
|                           const api_error &err, std::string_view msg); | ||||
|  | ||||
| void raise_api_path_error(std::string function, std::string_view api_path, | ||||
|                           const std::exception &exception, | ||||
|                           std::string_view msg); | ||||
|  | ||||
| void raise_api_path_error(std::string function, std::string_view api_path, | ||||
|                           std::int64_t err, std::string_view msg); | ||||
|  | ||||
| void raise_api_path_error(std::string function, std::string_view api_path, | ||||
|                           const json &err, std::string_view msg); | ||||
|  | ||||
| void raise_api_path_error(std::string function, std::string_view api_path, | ||||
|                           std::string_view source_path, const api_error &err, | ||||
|                           std::string_view msg); | ||||
|  | ||||
| void raise_api_path_error(std::string function, std::string_view api_path, | ||||
|                           std::string_view source_path, std::int64_t err, | ||||
|                           std::string_view msg); | ||||
|  | ||||
| void raise_api_path_error(std::string function, std::string_view api_path, | ||||
|                           std::string_view source_path, | ||||
|                           const std::exception &exception, | ||||
|                           std::string_view msg); | ||||
|  | ||||
| void raise_url_error(std::string function, std::string_view url, CURLcode err, | ||||
|                      std::string_view msg); | ||||
|  | ||||
| void raise_url_error(std::string function, std::string_view url, | ||||
|                      std::string_view source_path, | ||||
|                      const std::exception &exception, std::string_view msg); | ||||
|  | ||||
| } // namespace repertory::utils::error | ||||
|  | ||||
| #endif // INCLUDE_UTILS_ERROR_UTILS_HPP_ | ||||
							
								
								
									
										96
									
								
								repertory/librepertory/include/utils/file_utils.hpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										96
									
								
								repertory/librepertory/include/utils/file_utils.hpp
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,96 @@ | ||||
| /* | ||||
|   Copyright <2018-2024> <scott.e.graves@protonmail.com> | ||||
|  | ||||
|   Permission is hereby granted, free of charge, to any person obtaining a copy | ||||
|   of this software and associated documentation files (the "Software"), to deal | ||||
|   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_FILE_UTILS_HPP_ | ||||
| #define INCLUDE_UTILS_FILE_UTILS_HPP_ | ||||
|  | ||||
| #include "types/repertory.hpp" | ||||
| #include "utils/native_file.hpp" | ||||
|  | ||||
| namespace repertory::utils::file { | ||||
| // Prototypes | ||||
| [[nodiscard]] auto calculate_used_space(std::string path, bool recursive) | ||||
|     -> std::uint64_t; | ||||
|  | ||||
| void change_to_process_directory(); | ||||
|  | ||||
| [[nodiscard]] auto copy_directory_recursively(std::string from_path, | ||||
|                                               std::string to_path) -> bool; | ||||
|  | ||||
| [[nodiscard]] auto copy_file(std::string from_path, std::string to_path) | ||||
|     -> bool; | ||||
|  | ||||
| [[nodiscard]] auto create_full_directory_path(std::string path) -> bool; | ||||
|  | ||||
| [[nodiscard]] auto delete_directory(std::string path, bool recursive = false) | ||||
|     -> bool; | ||||
|  | ||||
| [[nodiscard]] auto delete_directory_recursively(std::string path) -> bool; | ||||
|  | ||||
| [[nodiscard]] auto delete_file(std::string path) -> bool; | ||||
|  | ||||
| [[nodiscard]] auto generate_sha256(const std::string &file_path) -> std::string; | ||||
|  | ||||
| [[nodiscard]] auto get_accessed_time(const std::string &path, | ||||
|                                      std::uint64_t &accessed) -> bool; | ||||
|  | ||||
| [[nodiscard]] auto get_directory_files(std::string path, bool oldest_first, | ||||
|                                        bool recursive = false) | ||||
|     -> std::deque<std::string>; | ||||
|  | ||||
| [[nodiscard]] auto get_free_drive_space(const std::string &path) | ||||
|     -> std::uint64_t; | ||||
|  | ||||
| [[nodiscard]] auto get_total_drive_space(const std::string &path) | ||||
|     -> std::uint64_t; | ||||
|  | ||||
| [[nodiscard]] auto get_file_size(std::string path, std::uint64_t &file_size) | ||||
|     -> bool; | ||||
|  | ||||
| [[nodiscard]] auto get_modified_time(const std::string &path, | ||||
|                                      std::uint64_t &modified) -> bool; | ||||
|  | ||||
| [[nodiscard]] auto is_directory(const std::string &path) -> bool; | ||||
|  | ||||
| [[nodiscard]] auto is_file(const std::string &path) -> bool; | ||||
|  | ||||
| [[nodiscard]] auto is_modified_date_older_than(const std::string &path, | ||||
|                                                const std::chrono::hours &hours) | ||||
|     -> bool; | ||||
|  | ||||
| [[nodiscard]] auto move_file(std::string from, std::string to) -> bool; | ||||
|  | ||||
| [[nodiscard]] auto read_file_lines(const std::string &path) | ||||
|     -> std::vector<std::string>; | ||||
|  | ||||
| [[nodiscard]] auto read_json_file(const std::string &path, json &data) -> bool; | ||||
|  | ||||
| [[nodiscard]] auto reset_modified_time(const std::string &path) -> bool; | ||||
|  | ||||
| [[nodiscard]] auto retry_delete_directory(const std::string &dir) -> bool; | ||||
|  | ||||
| [[nodiscard]] auto retry_delete_file(const std::string &file) -> bool; | ||||
|  | ||||
| [[nodiscard]] auto write_json_file(const std::string &path, const json &j) | ||||
|     -> bool; | ||||
| } // namespace repertory::utils::file | ||||
|  | ||||
| #endif // INCLUDE_UTILS_FILE_UTILS_HPP_ | ||||
							
								
								
									
										115
									
								
								repertory/librepertory/include/utils/native_file.hpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										115
									
								
								repertory/librepertory/include/utils/native_file.hpp
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,115 @@ | ||||
| /* | ||||
|   Copyright <2018-2024> <scott.e.graves@protonmail.com> | ||||
|  | ||||
|   Permission is hereby granted, free of charge, to any person obtaining a copy | ||||
|   of this software and associated documentation files (the "Software"), to deal | ||||
|   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_NATIVEFILE_HPP_ | ||||
| #define INCLUDE_UTILS_NATIVEFILE_HPP_ | ||||
|  | ||||
| #include "types/repertory.hpp" | ||||
|  | ||||
| namespace repertory { | ||||
| class native_file final { | ||||
| public: | ||||
|   native_file(const native_file &) = delete; | ||||
|   native_file(native_file &&) = delete; | ||||
|   auto operator=(const native_file &) -> native_file & = delete; | ||||
|   auto operator=(native_file &&) -> native_file & = delete; | ||||
|  | ||||
|   using native_file_ptr = std::shared_ptr<native_file>; | ||||
|  | ||||
| public: | ||||
|   [[nodiscard]] static auto attach(native_handle handle) -> native_file_ptr { | ||||
|     return std::shared_ptr<native_file>(new native_file(handle)); | ||||
|   } | ||||
|  | ||||
|   [[nodiscard]] static auto clone(const native_file_ptr &ptr) | ||||
|       -> native_file_ptr; | ||||
|  | ||||
|   [[nodiscard]] static auto create_or_open(const std::string &source_path, | ||||
|                                            bool read_only, native_file_ptr &ptr) | ||||
|       -> api_error; | ||||
|  | ||||
|   [[nodiscard]] static auto create_or_open(const std::string &source_path, | ||||
|                                            native_file_ptr &ptr) -> api_error; | ||||
|  | ||||
|   [[nodiscard]] static auto open(const std::string &source_path, | ||||
|                                  native_file_ptr &ptr) -> api_error; | ||||
|  | ||||
|   [[nodiscard]] static auto open(const std::string &source_path, bool read_only, | ||||
|                                  native_file_ptr &ptr) -> api_error; | ||||
|  | ||||
| private: | ||||
|   explicit native_file(const native_handle &handle) : handle_(handle) {} | ||||
|  | ||||
| public: | ||||
|   ~native_file(); | ||||
|  | ||||
| private: | ||||
|   native_handle handle_; | ||||
|  | ||||
| private: | ||||
|   bool auto_close{false}; | ||||
| #ifdef _WIN32 | ||||
|   std::recursive_mutex read_write_mutex_; | ||||
| #endif | ||||
|  | ||||
| public: | ||||
|   [[nodiscard]] auto allocate(std::uint64_t file_size) -> bool; | ||||
|  | ||||
|   void close(); | ||||
|  | ||||
|   [[nodiscard]] auto copy_from(const native_file_ptr &ptr) -> bool; | ||||
|  | ||||
|   [[nodiscard]] auto copy_from(const std::string &path) -> bool; | ||||
|  | ||||
|   void flush(); | ||||
|  | ||||
|   [[nodiscard]] auto get_file_size(std::uint64_t &file_size) -> bool; | ||||
|  | ||||
|   [[nodiscard]] auto get_handle() -> native_handle; | ||||
|  | ||||
| #ifdef _WIN32 | ||||
|   [[nodiscard]] auto read_bytes(char *buffer, std::size_t read_size, | ||||
|                                 std::uint64_t read_offset, | ||||
|                                 std::size_t &bytes_read) -> bool; | ||||
| #else | ||||
|   [[nodiscard]] auto read_bytes(char *buffer, std::size_t read_size, | ||||
|                                 std::uint64_t read_offset, | ||||
|                                 std::size_t &bytes_read) -> bool; | ||||
| #endif | ||||
|   void set_auto_close(bool b) { auto_close = b; } | ||||
|  | ||||
|   [[nodiscard]] auto truncate(std::uint64_t file_size) -> bool; | ||||
|  | ||||
| #ifdef _WIN32 | ||||
|   [[nodiscard]] auto write_bytes(const char *buffer, std::size_t write_size, | ||||
|                                  std::uint64_t write_offset, | ||||
|                                  std::size_t &bytes_written) -> bool; | ||||
| #else | ||||
|   [[nodiscard]] auto write_bytes(const char *buffer, std::size_t write_size, | ||||
|                                  std::uint64_t write_offset, | ||||
|                                  std::size_t &bytes_written) -> bool; | ||||
| #endif | ||||
| }; | ||||
|  | ||||
| using native_file_ptr = native_file::native_file_ptr; | ||||
| } // namespace repertory | ||||
|  | ||||
| #endif // INCLUDE_UTILS_NATIVEFILE_HPP_ | ||||
							
								
								
									
										67
									
								
								repertory/librepertory/include/utils/path_utils.hpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										67
									
								
								repertory/librepertory/include/utils/path_utils.hpp
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,67 @@ | ||||
| /* | ||||
|   Copyright <2018-2024> <scott.e.graves@protonmail.com> | ||||
|  | ||||
|   Permission is hereby granted, free of charge, to any person obtaining a copy | ||||
|   of this software and associated documentation files (the "Software"), to deal | ||||
|   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_PATH_UTILS_HPP_ | ||||
| #define INCLUDE_UTILS_PATH_UTILS_HPP_ | ||||
|  | ||||
| namespace repertory::utils::path { | ||||
| #ifdef _WIN32 | ||||
| static const std::string directory_seperator = "\\"; | ||||
| static const std::string not_directory_seperator = "/"; | ||||
| #else | ||||
| static const std::string directory_seperator = "/"; | ||||
| static const std::string not_directory_seperator = "\\"; | ||||
| #endif | ||||
|  | ||||
| // Prototypes | ||||
| [[nodiscard]] auto absolute(std::string path) -> std::string; | ||||
|  | ||||
| [[nodiscard]] auto combine(std::string path, | ||||
|                            const std::vector<std::string> &paths) | ||||
|     -> std::string; | ||||
|  | ||||
| [[nodiscard]] auto create_api_path(std::string path) -> std::string; | ||||
|  | ||||
| [[nodiscard]] auto finalize(std::string path) -> std::string; | ||||
|  | ||||
| auto format_path(std::string &path, const std::string &sep, | ||||
|                  const std::string ¬_sep) -> std::string &; | ||||
|  | ||||
| [[nodiscard]] auto get_parent_api_path(const std::string &path) -> std::string; | ||||
|  | ||||
| #ifndef _WIN32 | ||||
| [[nodiscard]] auto get_parent_directory(std::string path) -> std::string; | ||||
| #endif | ||||
|  | ||||
| [[nodiscard]] auto is_ads_file_path(const std::string &path) -> bool; | ||||
|  | ||||
| [[nodiscard]] auto is_trash_directory(std::string path) -> bool; | ||||
|  | ||||
| [[nodiscard]] auto remove_file_name(std::string path) -> std::string; | ||||
|  | ||||
| #ifndef _WIN32 | ||||
| [[nodiscard]] auto resolve(std::string path) -> std::string; | ||||
| #endif | ||||
|  | ||||
| [[nodiscard]] auto strip_to_file_name(std::string path) -> std::string; | ||||
| } // namespace repertory::utils::path | ||||
|  | ||||
| #endif // INCLUDE_UTILS_PATH_UTILS_HPP_ | ||||
							
								
								
									
										86
									
								
								repertory/librepertory/include/utils/polling.hpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										86
									
								
								repertory/librepertory/include/utils/polling.hpp
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,86 @@ | ||||
| /* | ||||
|   Copyright <2018-2024> <scott.e.graves@protonmail.com> | ||||
|  | ||||
|   Permission is hereby granted, free of charge, to any person obtaining a copy | ||||
|   of this software and associated documentation files (the "Software"), to deal | ||||
|   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_POLLING_HPP_ | ||||
| #define INCLUDE_UTILS_POLLING_HPP_ | ||||
|  | ||||
| #include "types/repertory.hpp" | ||||
|  | ||||
| namespace repertory { | ||||
| class app_config; | ||||
| class polling final { | ||||
| public: | ||||
|   enum struct frequency { | ||||
|     high, | ||||
|     low, | ||||
|     second, | ||||
|   }; | ||||
|  | ||||
|   struct polling_item { | ||||
|     std::string name; | ||||
|     frequency freq; | ||||
|     std::function<void()> action; | ||||
|   }; | ||||
|  | ||||
| public: | ||||
|   polling(const polling &) = delete; | ||||
|   polling(polling &&) = delete; | ||||
|   auto operator=(const polling &) -> polling & = delete; | ||||
|   auto operator=(polling &&) -> polling & = delete; | ||||
|  | ||||
| private: | ||||
|   polling() = default; | ||||
|  | ||||
|   ~polling() { stop(); } | ||||
|  | ||||
| private: | ||||
|   static polling instance_; | ||||
|  | ||||
| public: | ||||
|   static auto instance() -> polling & { return instance_; } | ||||
|  | ||||
| private: | ||||
|   app_config *config_ = nullptr; | ||||
|   std::unique_ptr<std::thread> high_frequency_thread_; | ||||
|   std::unordered_map<std::string, polling_item> items_; | ||||
|   std::unique_ptr<std::thread> low_frequency_thread_; | ||||
|   std::mutex mutex_; | ||||
|   std::condition_variable notify_; | ||||
|   std::unique_ptr<std::thread> second_frequency_thread_; | ||||
|   std::mutex start_stop_mutex_; | ||||
|   stop_type stop_requested_ = false; | ||||
|  | ||||
| private: | ||||
|   void frequency_thread(std::function<std::uint32_t()> get_frequency_seconds, | ||||
|                         frequency freq); | ||||
|  | ||||
| public: | ||||
|   void remove_callback(const std::string &name); | ||||
|  | ||||
|   void set_callback(const polling_item &item); | ||||
|  | ||||
|   void start(app_config *config); | ||||
|  | ||||
|   void stop(); | ||||
| }; | ||||
| } // namespace repertory | ||||
|  | ||||
| #endif // INCLUDE_UTILS_POLLING_HPP_ | ||||
| @@ -0,0 +1,68 @@ | ||||
| /* | ||||
|   Copyright <2018-2024> <scott.e.graves@protonmail.com> | ||||
|  | ||||
|   Permission is hereby granted, free of charge, to any person obtaining a copy | ||||
|   of this software and associated documentation files (the "Software"), to deal | ||||
|   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_SINGLE_THREAD_SERVICE_BASE_HPP_ | ||||
| #define INCLUDE_UTILS_SINGLE_THREAD_SERVICE_BASE_HPP_ | ||||
|  | ||||
| #include "types/repertory.hpp" | ||||
|  | ||||
| namespace repertory { | ||||
| class single_thread_service_base { | ||||
| public: | ||||
|   explicit single_thread_service_base(std::string service_name) | ||||
|       : service_name_(std::move(service_name)) {} | ||||
|  | ||||
|   virtual ~single_thread_service_base() { stop(); } | ||||
|  | ||||
| private: | ||||
|   const std::string service_name_; | ||||
|   mutable std::mutex mtx_; | ||||
|   mutable std::condition_variable notify_; | ||||
|   stop_type stop_requested_ = false; | ||||
|   std::unique_ptr<std::thread> thread_; | ||||
|  | ||||
| protected: | ||||
|   [[nodiscard]] auto get_mutex() const -> std::mutex & { return mtx_; } | ||||
|  | ||||
|   [[nodiscard]] auto get_notify() const -> std::condition_variable & { | ||||
|     return notify_; | ||||
|   } | ||||
|  | ||||
|   [[nodiscard]] auto get_stop_requested() const -> bool { | ||||
|     return stop_requested_; | ||||
|   } | ||||
|  | ||||
|   void notify_all() const; | ||||
|  | ||||
|   virtual void on_start() {} | ||||
|  | ||||
|   virtual void on_stop() {} | ||||
|  | ||||
|   virtual void service_function() = 0; | ||||
|  | ||||
| public: | ||||
|   void start(); | ||||
|  | ||||
|   void stop(); | ||||
| }; | ||||
| } // namespace repertory | ||||
|  | ||||
| #endif // INCLUDE_UTILS_SINGLE_THREAD_SERVICE_BASE_HPP_ | ||||
							
								
								
									
										115
									
								
								repertory/librepertory/include/utils/string_utils.hpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										115
									
								
								repertory/librepertory/include/utils/string_utils.hpp
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,115 @@ | ||||
| /* | ||||
|   Copyright <2018-2024> <scott.e.graves@protonmail.com> | ||||
|  | ||||
|   Permission is hereby granted, free of charge, to any person obtaining a copy | ||||
|   of this software and associated documentation files (the "Software"), to deal | ||||
|   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_STRING_UTILS_HPP_ | ||||
| #define INCLUDE_UTILS_STRING_UTILS_HPP_ | ||||
|  | ||||
| namespace repertory::utils::string { | ||||
| // Prototypes | ||||
| constexpr auto begins_with(std::string_view str, std::string_view val) -> bool { | ||||
|   return (str.find(val) == 0U); | ||||
| } | ||||
|  | ||||
| constexpr auto contains(std::string_view str, std::string_view search) -> bool { | ||||
|   return (str.find(search) != std::string_view::npos); | ||||
| } | ||||
|  | ||||
| [[nodiscard]] /* constexpr c++20 */ auto ends_with(std::string_view str, | ||||
|                                                    std::string_view val) | ||||
|     -> bool; | ||||
|  | ||||
| [[nodiscard]] auto from_bool(bool val) -> std::string; | ||||
|  | ||||
| [[nodiscard]] auto from_dynamic_bitset(const boost::dynamic_bitset<> &bitset) | ||||
|     -> std::string; | ||||
|  | ||||
| [[nodiscard]] auto from_utf8(const std::string &str) -> std::wstring; | ||||
|  | ||||
| [[nodiscard]] /* constexpr c++20 */ auto is_numeric(std::string_view str) | ||||
|     -> bool; | ||||
|  | ||||
| [[nodiscard]] auto join(const std::vector<std::string> &arr, const char &delim) | ||||
|     -> std::string; | ||||
|  | ||||
| auto left_trim(std::string &str) -> std::string &; | ||||
|  | ||||
| auto left_trim(std::string &str, const char &trim_ch) -> std::string &; | ||||
|  | ||||
| auto replace(std::string &src, const char &character, const char &with) | ||||
|     -> std::string &; | ||||
|  | ||||
| auto replace(std::string &src, const std::string &find, const std::string &with, | ||||
|              size_t start_pos = 0) -> std::string &; | ||||
|  | ||||
| [[nodiscard]] auto replace_copy(std::string src, const char &character, | ||||
|                                 const char &with) -> std::string; | ||||
|  | ||||
| [[nodiscard]] auto replace_copy(std::string src, const std::string &find, | ||||
|                                 const std::string &with, size_t start_pos = 0) | ||||
|     -> std::string; | ||||
|  | ||||
| auto right_trim(std::string &str) -> std::string &; | ||||
|  | ||||
| auto right_trim(std::string &str, const char &trim_ch) -> std::string &; | ||||
|  | ||||
| [[nodiscard]] auto split(const std::string &str, const char &delim, | ||||
|                          bool should_trim = true) -> std::vector<std::string>; | ||||
|  | ||||
| [[nodiscard]] auto to_bool(std::string val) -> bool; | ||||
|  | ||||
| [[nodiscard]] auto to_double(const std::string &str) -> double; | ||||
|  | ||||
| [[nodiscard]] auto to_dynamic_bitset(const std::string &val) | ||||
|     -> boost::dynamic_bitset<>; | ||||
|  | ||||
| [[nodiscard]] auto to_lower(std::string str) -> std::string; | ||||
|  | ||||
| [[nodiscard]] auto to_int32(const std::string &val) -> std::int32_t; | ||||
|  | ||||
| [[nodiscard]] auto to_int64(const std::string &val) -> std::int64_t; | ||||
|  | ||||
| [[nodiscard]] auto to_size_t(const std::string &val) -> std::size_t; | ||||
|  | ||||
| [[nodiscard]] auto to_uint8(const std::string &val) -> std::uint8_t; | ||||
|  | ||||
| [[nodiscard]] auto to_uint16(const std::string &val) -> std::uint16_t; | ||||
|  | ||||
| [[nodiscard]] auto to_uint32(const std::string &val) -> std::uint32_t; | ||||
|  | ||||
| [[nodiscard]] auto to_uint64(const std::string &val) -> std::uint64_t; | ||||
|  | ||||
| [[nodiscard]] auto to_upper(std::string str) -> std::string; | ||||
|  | ||||
| [[nodiscard]] auto to_utf8(std::string str) -> std::string; | ||||
|  | ||||
| [[nodiscard]] auto to_utf8(const std::wstring &str) -> std::string; | ||||
|  | ||||
| auto trim(std::string &str) -> std::string &; | ||||
|  | ||||
| auto trim(std::string &str, const char &trim_ch) -> std::string &; | ||||
|  | ||||
| [[nodiscard]] auto trim_copy(std::string str) -> std::string; | ||||
|  | ||||
| [[nodiscard]] auto trim_copy(std::string str, const char &trim_ch) | ||||
|     -> std::string; | ||||
| } // namespace repertory::utils::string | ||||
|  | ||||
| #endif // INCLUDE_UTILS_STRING_UTILS_HPP_ | ||||
							
								
								
									
										59
									
								
								repertory/librepertory/include/utils/throttle.hpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										59
									
								
								repertory/librepertory/include/utils/throttle.hpp
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,59 @@ | ||||
| /* | ||||
|   Copyright <2018-2024> <scott.e.graves@protonmail.com> | ||||
|  | ||||
|   Permission is hereby granted, free of charge, to any person obtaining a copy | ||||
|   of this software and associated documentation files (the "Software"), to deal | ||||
|   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_THROTTLE_HPP_ | ||||
| #define INCLUDE_UTILS_THROTTLE_HPP_ | ||||
|  | ||||
| namespace repertory { | ||||
| class throttle final { | ||||
| public: | ||||
|   throttle() : max_size_(10u) {} | ||||
|  | ||||
|   explicit throttle(std::size_t max_size) : max_size_(max_size) {} | ||||
|  | ||||
| public: | ||||
|   throttle(const throttle &) noexcept = delete; | ||||
|   throttle(throttle &&) noexcept = delete; | ||||
|   auto operator=(const throttle &) -> throttle & = delete; | ||||
|   auto operator=(throttle &&) -> throttle & = delete; | ||||
|  | ||||
| public: | ||||
|   ~throttle() { shutdown(); } | ||||
|  | ||||
| private: | ||||
|   const std::size_t max_size_; | ||||
|   std::size_t count_ = 0u; | ||||
|   bool shutdown_ = false; | ||||
|   std::mutex mutex_; | ||||
|   std::condition_variable notify_; | ||||
|  | ||||
| public: | ||||
|   void decrement(); | ||||
|  | ||||
|   void increment_or_wait(); | ||||
|  | ||||
|   void reset(); | ||||
|  | ||||
|   void shutdown(); | ||||
| }; | ||||
| } // namespace repertory | ||||
|  | ||||
| #endif // INCLUDE_UTILS_THROTTLE_HPP_ | ||||
							
								
								
									
										50
									
								
								repertory/librepertory/include/utils/timeout.hpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										50
									
								
								repertory/librepertory/include/utils/timeout.hpp
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,50 @@ | ||||
| /* | ||||
|   Copyright <2018-2024> <scott.e.graves@protonmail.com> | ||||
|  | ||||
|   Permission is hereby granted, free of charge, to any person obtaining a copy | ||||
|   of this software and associated documentation files (the "Software"), to deal | ||||
|   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_TIMEOUT_HPP_ | ||||
| #define INCLUDE_UTILS_TIMEOUT_HPP_ | ||||
|  | ||||
| namespace repertory { | ||||
| class timeout final { | ||||
| public: | ||||
|   timeout(const timeout &) noexcept = delete; | ||||
|   timeout(timeout &&) noexcept = delete; | ||||
|   auto operator=(const timeout &) noexcept -> timeout & = delete; | ||||
|   auto operator=(timeout &&) noexcept -> timeout & = delete; | ||||
|  | ||||
| public: | ||||
|   timeout(std::function<void()> timeout_callback, | ||||
|           const std::chrono::system_clock::duration &duration = 10s); | ||||
|  | ||||
|   ~timeout() { disable(); } | ||||
|  | ||||
| private: | ||||
|   bool timeout_killed_; | ||||
|   std::unique_ptr<std::thread> timeout_thread_; | ||||
|   std::mutex timeout_mutex_; | ||||
|   std::condition_variable timeout_notify_; | ||||
|  | ||||
| public: | ||||
|   void disable(); | ||||
| }; | ||||
| } // namespace repertory | ||||
|  | ||||
| #endif // INCLUDE_UTILS_TIMEOUT_HPP_ | ||||
							
								
								
									
										83
									
								
								repertory/librepertory/include/utils/unix/unix_utils.hpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										83
									
								
								repertory/librepertory/include/utils/unix/unix_utils.hpp
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,83 @@ | ||||
| /* | ||||
|   Copyright <2018-2024> <scott.e.graves@protonmail.com> | ||||
|  | ||||
|   Permission is hereby granted, free of charge, to any person obtaining a copy | ||||
|   of this software and associated documentation files (the "Software"), to deal | ||||
|   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_UNIX_UNIX_UTILS_HPP_ | ||||
| #define INCLUDE_UTILS_UNIX_UNIX_UTILS_HPP_ | ||||
| #ifndef _WIN32 | ||||
|  | ||||
| #include "types/remote.hpp" | ||||
| #include "types/repertory.hpp" | ||||
|  | ||||
| namespace repertory::utils { | ||||
| #if __linux__ | ||||
| inline const std::array<std::string, 4U> attribute_namespaces = { | ||||
|     "security", | ||||
|     "system", | ||||
|     "trusted", | ||||
|     "user", | ||||
| }; | ||||
| #endif | ||||
|  | ||||
| #if __APPLE__ | ||||
| template <typename t> | ||||
| [[nodiscard]] auto convert_to_uint64(const t *ptr) -> std::uint64_t; | ||||
| #else | ||||
| [[nodiscard]] auto convert_to_uint64(const pthread_t &thread) -> std::uint64_t; | ||||
| #endif | ||||
|  | ||||
| [[nodiscard]] auto from_api_error(const api_error &err) -> int; | ||||
|  | ||||
| [[nodiscard]] auto get_last_error_code() -> int; | ||||
|  | ||||
| [[nodiscard]] auto get_thread_id() -> std::uint64_t; | ||||
|  | ||||
| [[nodiscard]] auto is_uid_member_of_group(const uid_t &uid, const gid_t &gid) | ||||
|     -> bool; | ||||
|  | ||||
| void set_last_error_code(int error_code); | ||||
|  | ||||
| [[nodiscard]] auto to_api_error(int err) -> api_error; | ||||
|  | ||||
| [[nodiscard]] auto unix_error_to_windows(int err) -> std::int32_t; | ||||
|  | ||||
| [[nodiscard]] auto unix_time_to_windows_time(const remote::file_time &file_time) | ||||
|     -> UINT64; | ||||
|  | ||||
| void use_getpwuid(uid_t uid, std::function<void(struct passwd *pass)> callback); | ||||
|  | ||||
| void windows_create_to_unix(const UINT32 &create_options, | ||||
|                             const UINT32 &granted_access, std::uint32_t &flags, | ||||
|                             remote::file_mode &mode); | ||||
|  | ||||
| [[nodiscard]] auto windows_time_to_unix_time(std::uint64_t win_time) | ||||
|     -> remote::file_time; | ||||
|  | ||||
| // template implementations | ||||
| #if __APPLE__ | ||||
| template <typename t> | ||||
| [[nodiscard]] auto convert_to_uint64(const t *v) -> std::uint64_t { | ||||
|   return static_cast<std::uint64_t>(reinterpret_cast<std::uintptr_t>(v)); | ||||
| } | ||||
| #endif | ||||
| } // namespace repertory::utils | ||||
|  | ||||
| #endif // !_WIN32 | ||||
| #endif // INCLUDE_UTILS_UNIX_UNIX_UTILS_HPP_ | ||||
							
								
								
									
										181
									
								
								repertory/librepertory/include/utils/utils.hpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										181
									
								
								repertory/librepertory/include/utils/utils.hpp
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,181 @@ | ||||
| /* | ||||
|   Copyright <2018-2024> <scott.e.graves@protonmail.com> | ||||
|  | ||||
|   Permission is hereby granted, free of charge, to any person obtaining a copy | ||||
|   of this software and associated documentation files (the "Software"), to deal | ||||
|   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_UTILS_HPP_ | ||||
| #define INCLUDE_UTILS_UTILS_HPP_ | ||||
|  | ||||
| #include "types/remote.hpp" | ||||
| #include "types/repertory.hpp" | ||||
| #include "utils/unix/unix_utils.hpp" | ||||
| #include "utils/windows/windows_utils.hpp" | ||||
|  | ||||
| namespace repertory::utils { | ||||
| void calculate_allocation_size(bool directory, std::uint64_t file_size, | ||||
|                                UINT64 allocation_size, | ||||
|                                std::string &allocation_meta_size); | ||||
|  | ||||
| [[nodiscard]] auto calculate_read_size(const uint64_t &total_size, | ||||
|                                        std::size_t read_size, | ||||
|                                        const uint64_t &offset) -> std::size_t; | ||||
|  | ||||
| template <typename t> | ||||
| [[nodiscard]] auto collection_excludes(t collection, | ||||
|                                        const typename t::value_type &val) | ||||
|     -> bool; | ||||
|  | ||||
| template <typename t> | ||||
| [[nodiscard]] auto collection_includes(t collection, | ||||
|                                        const typename t::value_type &val) | ||||
|     -> bool; | ||||
|  | ||||
| [[nodiscard]] auto compare_version_strings(std::string version1, | ||||
|                                            std::string version2) -> int; | ||||
|  | ||||
| [[nodiscard]] auto convert_api_date(const std::string &date) -> std::uint64_t; | ||||
|  | ||||
| [[nodiscard]] auto create_curl() -> CURL *; | ||||
|  | ||||
| [[nodiscard]] auto create_uuid_string() -> std::string; | ||||
|  | ||||
| [[nodiscard]] auto create_volume_label(const provider_type &prov) | ||||
|     -> std::string; | ||||
|  | ||||
| template <typename t> | ||||
| [[nodiscard]] auto divide_with_ceiling(const t &n, const t &d) -> t; | ||||
|  | ||||
| [[nodiscard]] auto download_type_from_string(std::string type, | ||||
|                                              const download_type &default_type) | ||||
|     -> download_type; | ||||
|  | ||||
| [[nodiscard]] auto download_type_to_string(const download_type &type) | ||||
|     -> std::string; | ||||
|  | ||||
| template <typename t> | ||||
| [[nodiscard]] auto from_hex_string(const std::string &str, t &val) -> bool; | ||||
|  | ||||
| [[nodiscard]] auto generate_random_string(std::uint16_t length) -> std::string; | ||||
|  | ||||
| [[nodiscard]] auto get_attributes_from_meta(const api_meta_map &meta) -> DWORD; | ||||
|  | ||||
| [[nodiscard]] auto get_environment_variable(const std::string &variable) | ||||
|     -> std::string; | ||||
|  | ||||
| [[nodiscard]] auto get_file_time_now() -> std::uint64_t; | ||||
|  | ||||
| void get_local_time_now(struct tm &local_time); | ||||
|  | ||||
| [[nodiscard]] auto get_next_available_port(std::uint16_t first_port, | ||||
|                                            std::uint16_t &available_port) | ||||
|     -> bool; | ||||
|  | ||||
| [[nodiscard]] auto get_time_now() -> std::uint64_t; | ||||
|  | ||||
| template <typename data_type> | ||||
| [[nodiscard]] auto random_between(const data_type &begin, const data_type &end) | ||||
|     -> data_type; | ||||
|  | ||||
| template <typename t> | ||||
| void remove_element_from(t &collection, const typename t::value_type &val); | ||||
|  | ||||
| [[nodiscard]] auto reset_curl(CURL *curl_handle) -> CURL *; | ||||
|  | ||||
| [[nodiscard]] auto retryable_action(const std::function<bool()> &action) | ||||
|     -> bool; | ||||
|  | ||||
| void spin_wait_for_mutex(std::function<bool()> complete, | ||||
|                          std::condition_variable &cond, std::mutex &mtx, | ||||
|                          const std::string &text = ""); | ||||
|  | ||||
| void spin_wait_for_mutex(bool &complete, std::condition_variable &cond, | ||||
|                          std::mutex &mtx, const std::string &text = ""); | ||||
|  | ||||
| template <typename collection_t> | ||||
| [[nodiscard]] auto to_hex_string(const collection_t &collection) -> std::string; | ||||
|  | ||||
| // template implementations | ||||
| template <typename t> | ||||
| [[nodiscard]] auto collection_excludes(t collection, | ||||
|                                        const typename t::value_type &val) | ||||
|     -> bool { | ||||
|   return std::find(collection.begin(), collection.end(), val) == | ||||
|          collection.end(); | ||||
| } | ||||
|  | ||||
| template <typename t> | ||||
| [[nodiscard]] auto collection_includes(t collection, | ||||
|                                        const typename t::value_type &val) | ||||
|     -> bool { | ||||
|   return std::find(collection.begin(), collection.end(), val) != | ||||
|          collection.end(); | ||||
| } | ||||
|  | ||||
| template <typename t> | ||||
| [[nodiscard]] auto divide_with_ceiling(const t &n, const t &d) -> t { | ||||
|   return n ? (n / d) + (n % d != 0) : 0; | ||||
| } | ||||
|  | ||||
| template <typename t> | ||||
| [[nodiscard]] auto from_hex_string(const std::string &str, t &val) -> bool { | ||||
|   static constexpr const auto base16 = 16; | ||||
|  | ||||
|   val.clear(); | ||||
|   if (not(str.length() % 2U)) { | ||||
|     for (std::size_t i = 0U; i < str.length(); i += 2U) { | ||||
|       val.emplace_back(static_cast<typename t::value_type>( | ||||
|           strtol(str.substr(i, 2U).c_str(), nullptr, base16))); | ||||
|     } | ||||
|     return true; | ||||
|   } | ||||
|  | ||||
|   return false; | ||||
| } | ||||
|  | ||||
| template <typename data_type> | ||||
| [[nodiscard]] auto random_between(const data_type &begin, const data_type &end) | ||||
|     -> data_type { | ||||
|   return begin + repertory_rand<data_type>() % ((end + data_type{1}) - begin); | ||||
| } | ||||
|  | ||||
| template <typename collection_t> | ||||
| void remove_element_from(collection_t &collection, | ||||
|                          const typename collection_t::value_type &value) { | ||||
|   collection.erase(std::remove(collection.begin(), collection.end(), value), | ||||
|                    collection.end()); | ||||
| } | ||||
|  | ||||
| template <typename collection_t> | ||||
| [[nodiscard]] auto to_hex_string(const collection_t &collection) | ||||
|     -> std::string { | ||||
|   static_assert(sizeof(typename collection_t::value_type) == 1U, | ||||
|                 "value_type must be 1 byte in size"); | ||||
|   static constexpr const auto mask = 0xFF; | ||||
|  | ||||
|   std::stringstream stream; | ||||
|   for (const auto &val : collection) { | ||||
|     stream << std::setfill('0') << std::setw(2) << std::hex | ||||
|            << (static_cast<std::uint32_t>(val) & mask); | ||||
|   } | ||||
|  | ||||
|   return stream.str(); | ||||
| } | ||||
| } // namespace repertory::utils | ||||
|  | ||||
| #endif // INCLUDE_UTILS_UTILS_HPP_ | ||||
| @@ -0,0 +1,75 @@ | ||||
| /* | ||||
|   Copyright <2018-2024> <scott.e.graves@protonmail.com> | ||||
|  | ||||
|   Permission is hereby granted, free of charge, to any person obtaining a copy | ||||
|   of this software and associated documentation files (the "Software"), to deal | ||||
|   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_WINDOWS_WINDOWS_UTILS_HPP_ | ||||
| #define INCLUDE_UTILS_WINDOWS_WINDOWS_UTILS_HPP_ | ||||
| #ifdef _WIN32 | ||||
|  | ||||
| #include "types/remote.hpp" | ||||
| #include "types/repertory.hpp" | ||||
|  | ||||
| namespace repertory::utils { | ||||
| [[nodiscard]] auto filetime_to_unix_time(const FILETIME &ft) | ||||
|     -> remote::file_time; | ||||
|  | ||||
| [[nodiscard]] auto get_last_error_code() -> DWORD; | ||||
|  | ||||
| [[nodiscard]] auto get_local_app_data_directory() -> const std::string &; | ||||
|  | ||||
| [[nodiscard]] auto get_accessed_time_from_meta(const api_meta_map &meta) | ||||
|     -> std::uint64_t; | ||||
|  | ||||
| [[nodiscard]] auto get_changed_time_from_meta(const api_meta_map &meta) | ||||
|     -> std::uint64_t; | ||||
|  | ||||
| [[nodiscard]] auto get_creation_time_from_meta(const api_meta_map &meta) | ||||
|     -> std::uint64_t; | ||||
|  | ||||
| [[nodiscard]] auto get_written_time_from_meta(const api_meta_map &meta) | ||||
|     -> std::uint64_t; | ||||
|  | ||||
| [[nodiscard]] auto get_thread_id() -> std::uint64_t; | ||||
|  | ||||
| [[nodiscard]] auto is_process_elevated() -> bool; | ||||
|  | ||||
| [[nodiscard]] auto run_process_elevated(std::vector<const char *> args) -> int; | ||||
|  | ||||
| void set_last_error_code(DWORD errorCode); | ||||
|  | ||||
| [[nodiscard]] auto from_api_error(const api_error &e) -> NTSTATUS; | ||||
|  | ||||
| auto strptime(const char *s, const char *f, struct tm *tm) -> const char *; | ||||
|  | ||||
| [[nodiscard]] auto unix_access_mask_to_windows(std::int32_t mask) -> int; | ||||
|  | ||||
| [[nodiscard]] auto | ||||
| unix_open_flags_to_flags_and_perms(const remote::file_mode &mode, | ||||
|                                    const remote::open_flags &flags, | ||||
|                                    std::int32_t &perms) -> int; | ||||
|  | ||||
| void unix_time_to_filetime(const remote::file_time &ts, FILETIME &ft); | ||||
|  | ||||
| [[nodiscard]] auto time64_to_unix_time(const __time64_t &t) | ||||
|     -> remote::file_time; | ||||
| } // namespace repertory::utils | ||||
|  | ||||
| #endif // _WIN32 | ||||
| #endif // INCLUDE_UTILS_WINDOWS_WINDOWS_UTILS_HPP_ | ||||
							
								
								
									
										940
									
								
								repertory/librepertory/src/app_config.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										940
									
								
								repertory/librepertory/src/app_config.cpp
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,940 @@ | ||||
| /* | ||||
|   Copyright <2018-2024> <scott.e.graves@protonmail.com> | ||||
|  | ||||
|   Permission is hereby granted, free of charge, to any person obtaining a copy | ||||
|   of this software and associated documentation files (the "Software"), to deal | ||||
|   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 "app_config.hpp" | ||||
|  | ||||
| #include "types/startup_exception.hpp" | ||||
| #include "utils/error_utils.hpp" | ||||
| #include "utils/file_utils.hpp" | ||||
| #include "utils/path_utils.hpp" | ||||
| #include "utils/unix/unix_utils.hpp" | ||||
| #include "utils/utils.hpp" | ||||
|  | ||||
| namespace { | ||||
| constexpr const auto default_api_auth_size = 48U; | ||||
| constexpr const auto default_download_timeout_ces = 30U; | ||||
| constexpr const auto default_eviction_delay_mins = 10U; | ||||
| constexpr const auto default_high_freq_interval_secs = 30U; | ||||
| constexpr const auto default_low_freq_interval_secs = 60U * 60U; | ||||
| constexpr const auto default_max_cache_size_bytes = | ||||
|     20ULL * 1024ULL * 1024ULL * 1024ULL; | ||||
| constexpr const auto default_max_upload_count = 5U; | ||||
| constexpr const auto default_min_download_timeout_secs = 5U; | ||||
| constexpr const auto default_online_check_retry_secs = 60U; | ||||
| constexpr const auto default_orphaned_file_retention_days = 15U; | ||||
| constexpr const auto default_read_ahead_count = 4U; | ||||
| constexpr const auto default_remote_client_pool_size = 10U; | ||||
| constexpr const auto default_remote_host_name_or_ip = ""; | ||||
| constexpr const auto default_remote_max_connections = 20U; | ||||
| constexpr const auto default_remote_receive_timeout_secs = 120U; | ||||
| constexpr const auto default_remote_send_timeout_secs = 30U; | ||||
| constexpr const auto default_remote_token = ""; | ||||
| constexpr const auto default_retry_read_count = 6U; | ||||
| constexpr const auto default_ring_buffer_file_size = 512U; | ||||
| constexpr const auto retry_save_count = 5U; | ||||
| } // namespace | ||||
|  | ||||
| namespace repertory { | ||||
| app_config::app_config(const provider_type &prov, | ||||
|                        const std::string &data_directory) | ||||
|     : prov_(prov), | ||||
|       api_auth_(utils::generate_random_string(default_api_auth_size)), | ||||
|       api_port_(default_rpc_port(prov)), | ||||
|       api_user_(REPERTORY), | ||||
|       config_changed_(false), | ||||
|       data_directory_(data_directory.empty() | ||||
|                           ? default_data_directory(prov) | ||||
|                           : utils::path::absolute(data_directory)), | ||||
|       download_timeout_secs_(default_download_timeout_ces), | ||||
|       enable_chunk_downloader_timeout_(true), | ||||
|       enable_comm_duration_events_(false), | ||||
|       enable_drive_events_(false), | ||||
|       enable_max_cache_size_(false), | ||||
| #ifdef _WIN32 | ||||
|       enable_mount_manager_(false), | ||||
| #endif | ||||
|       enable_remote_mount_(false), | ||||
|       event_level_(event_level::normal), | ||||
|       eviction_delay_mins_(default_eviction_delay_mins), | ||||
|       eviction_uses_accessed_time_(false), | ||||
|       high_freq_interval_secs_(default_high_freq_interval_secs), | ||||
|       is_remote_mount_(false), | ||||
|       low_freq_interval_secs_(default_low_freq_interval_secs), | ||||
|       max_cache_size_bytes_(default_max_cache_size_bytes), | ||||
|       max_upload_count_(default_max_upload_count), | ||||
|       min_download_timeout_secs_(default_min_download_timeout_secs), | ||||
|       online_check_retry_secs_(default_online_check_retry_secs), | ||||
|       orphaned_file_retention_days_(default_orphaned_file_retention_days), | ||||
|       preferred_download_type_( | ||||
|           utils::download_type_to_string(download_type::fallback)), | ||||
|       read_ahead_count_(default_read_ahead_count), | ||||
|       remote_client_pool_size_(default_remote_client_pool_size), | ||||
|       remote_host_name_or_ip_(default_remote_host_name_or_ip), | ||||
|       remote_max_connections_(default_remote_max_connections), | ||||
|       remote_port_(default_remote_port(prov)), | ||||
|       remote_receive_timeout_secs_(default_remote_receive_timeout_secs), | ||||
|       remote_send_timeout_secs_(default_remote_send_timeout_secs), | ||||
|       remote_token_(default_remote_token), | ||||
|       retry_read_count_(default_retry_read_count), | ||||
|       ring_buffer_file_size_(default_ring_buffer_file_size) { | ||||
|   cache_directory_ = utils::path::combine(data_directory_, {"cache"}); | ||||
|   log_directory_ = utils::path::combine(data_directory_, {"logs"}); | ||||
|  | ||||
|   hc_.agent_string = default_agent_name(prov_); | ||||
|   hc_.api_password = get_provider_api_password(prov_); | ||||
|   hc_.api_port = default_api_port(prov_); | ||||
|  | ||||
|   if (not utils::file::create_full_directory_path(data_directory_)) { | ||||
|     throw startup_exception("unable to create: " + data_directory_); | ||||
|   } | ||||
|  | ||||
|   if (not utils::file::create_full_directory_path(cache_directory_)) { | ||||
|     throw startup_exception("unable to create: " + cache_directory_); | ||||
|   } | ||||
|  | ||||
|   if (not utils::file::create_full_directory_path(log_directory_)) { | ||||
|     throw startup_exception("unable to create: " + log_directory_); | ||||
|   } | ||||
|  | ||||
|   if (not load()) { | ||||
|     save(); | ||||
|   } | ||||
| } | ||||
|  | ||||
| auto app_config::get_config_file_path() const -> std::string { | ||||
|   return utils::path::combine(data_directory_, {"config.json"}); | ||||
| } | ||||
|  | ||||
| auto app_config::default_agent_name(const provider_type &prov) -> std::string { | ||||
|   static const std::array<std::string, | ||||
|                           static_cast<std::size_t>(provider_type::unknown)> | ||||
|       PROVIDER_AGENT_NAMES = { | ||||
|           "Sia-Agent", | ||||
|           "", | ||||
|           "", | ||||
|           "", | ||||
|       }; | ||||
|  | ||||
|   return PROVIDER_AGENT_NAMES.at(static_cast<std::size_t>(prov)); | ||||
| } | ||||
|  | ||||
| auto app_config::default_api_port(const provider_type &prov) -> std::uint16_t { | ||||
|   static const std::array<std::uint16_t, | ||||
|                           static_cast<std::size_t>(provider_type::unknown)> | ||||
|       PROVIDER_API_PORTS = { | ||||
|           9980U, | ||||
|           0U, | ||||
|           0U, | ||||
|           0U, | ||||
|       }; | ||||
|   return PROVIDER_API_PORTS.at(static_cast<std::size_t>(prov)); | ||||
| } | ||||
|  | ||||
| auto app_config::default_data_directory(const provider_type &prov) | ||||
|     -> std::string { | ||||
| #ifdef _WIN32 | ||||
|   auto data_directory = utils::path::combine( | ||||
|       utils::get_local_app_data_directory(), | ||||
|       {REPERTORY_DATA_NAME, app_config::get_provider_name(prov)}); | ||||
| #else | ||||
| #ifdef __APPLE__ | ||||
|   auto data_directory = utils::path::resolve( | ||||
|       std::string("~/Library/Application Support/") + REPERTORY_DATA_NAME + | ||||
|       '/' + app_config::get_provider_name(prov)); | ||||
| #else | ||||
|   auto data_directory = | ||||
|       utils::path::resolve(std::string("~/.local/") + REPERTORY_DATA_NAME + | ||||
|                            '/' + app_config::get_provider_name(prov)); | ||||
| #endif | ||||
| #endif | ||||
|   return data_directory; | ||||
| } | ||||
|  | ||||
| auto app_config::default_remote_port(const provider_type &prov) | ||||
|     -> std::uint16_t { | ||||
|   static const std::array<std::uint16_t, | ||||
|                           static_cast<std::size_t>(provider_type::unknown)> | ||||
|       PROVIDER_REMOTE_PORTS = { | ||||
|           20000U, | ||||
|           20010U, | ||||
|           20100U, | ||||
|           20001U, | ||||
|       }; | ||||
|   return PROVIDER_REMOTE_PORTS.at(static_cast<std::size_t>(prov)); | ||||
| } | ||||
| auto app_config::default_rpc_port(const provider_type &prov) -> std::uint16_t { | ||||
|   static const std::array<std::uint16_t, | ||||
|                           static_cast<std::size_t>(provider_type::unknown)> | ||||
|       PROVIDER_RPC_PORTS = { | ||||
|           10000U, | ||||
|           10010U, | ||||
|           10100U, | ||||
|           10002U, | ||||
|       }; | ||||
|   return PROVIDER_RPC_PORTS.at(static_cast<std::size_t>(prov)); | ||||
| } | ||||
|  | ||||
| auto app_config::get_json() const -> json { | ||||
|   json ret = { | ||||
|       {"ApiAuth", api_auth_}, | ||||
|       {"ApiPort", api_port_}, | ||||
|       {"ApiUser", api_user_}, | ||||
|       {"ChunkDownloaderTimeoutSeconds", download_timeout_secs_}, | ||||
|       {"EnableChunkDownloaderTimeout", enable_chunk_downloader_timeout_}, | ||||
|       {"EnableCommDurationEvents", enable_comm_duration_events_}, | ||||
|       {"EnableDriveEvents", enable_drive_events_}, | ||||
| #ifdef _WIN32 | ||||
|       {"EnableMountManager", enable_mount_manager_}, | ||||
| #endif | ||||
|       {"EnableMaxCacheSize", enable_max_cache_size_}, | ||||
|       {"EncryptConfig", | ||||
|        { | ||||
|            {"EncryptionToken", encrypt_config_.encryption_token}, | ||||
|            {"Path", encrypt_config_.path}, | ||||
|        }}, | ||||
|       {"EventLevel", event_level_to_string(event_level_)}, | ||||
|       {"EvictionDelayMinutes", eviction_delay_mins_}, | ||||
|       {"EvictionUsesAccessedTime", eviction_uses_accessed_time_}, | ||||
|       {"HighFreqIntervalSeconds", high_freq_interval_secs_}, | ||||
|       {"HostConfig", | ||||
|        { | ||||
|            {"AgentString", hc_.agent_string}, | ||||
|            {"ApiPassword", hc_.api_password}, | ||||
|            {"ApiPort", hc_.api_port}, | ||||
|            {"HostNameOrIp", hc_.host_name_or_ip}, | ||||
|            {"TimeoutMs", hc_.timeout_ms}, | ||||
|        }}, | ||||
|       {"LowFreqIntervalSeconds", low_freq_interval_secs_}, | ||||
|       {"MaxCacheSizeBytes", max_cache_size_bytes_}, | ||||
|       {"MaxUploadCount", max_upload_count_}, | ||||
|       {"OnlineCheckRetrySeconds", online_check_retry_secs_}, | ||||
|       {"OrphanedFileRetentionDays", orphaned_file_retention_days_}, | ||||
|       {"PreferredDownloadType", preferred_download_type_}, | ||||
|       {"ReadAheadCount", read_ahead_count_}, | ||||
|       { | ||||
|           "RemoteMount", | ||||
|           { | ||||
|               {"EnableRemoteMount", enable_remote_mount_}, | ||||
|               {"IsRemoteMount", is_remote_mount_}, | ||||
|               {"RemoteClientPoolSize", remote_client_pool_size_}, | ||||
|               {"RemoteMaxConnections", remote_max_connections_}, | ||||
|               {"RemoteHostNameOrIp", remote_host_name_or_ip_}, | ||||
|               {"RemotePort", remote_port_}, | ||||
|               {"RemoteReceiveTimeoutSeconds", remote_receive_timeout_secs_}, | ||||
|               {"RemoteSendTimeoutSeconds", remote_send_timeout_secs_}, | ||||
|               {"RemoteToken", remote_token_}, | ||||
|           }, | ||||
|       }, | ||||
|       {"RetryReadCount", retry_read_count_}, | ||||
|       {"RingBufferFileSize", ring_buffer_file_size_}, | ||||
|       {"S3Config", | ||||
|        { | ||||
|            {"AccessKey", s3_config_.access_key}, | ||||
|            {"Bucket", s3_config_.bucket}, | ||||
|            {"CacheTimeoutSeconds", s3_config_.cache_timeout_secs}, | ||||
|            {"EncryptionToken", s3_config_.encryption_token}, | ||||
|            {"Region", s3_config_.region}, | ||||
|            {"SecretKey", s3_config_.secret_key}, | ||||
|            {"TimeoutMs", s3_config_.timeout_ms}, | ||||
|            {"URL", s3_config_.url}, | ||||
|            {"UsePathStyle", s3_config_.use_path_style}, | ||||
|            {"UseRegionInURL", s3_config_.use_region_in_url}, | ||||
|        }}, | ||||
|       {"Version", version_}}; | ||||
|  | ||||
|   if (prov_ == provider_type::encrypt) { | ||||
|     ret.erase("ChunkDownloaderTimeoutSeconds"); | ||||
|     ret.erase("EnableChunkDownloaderTimeout"); | ||||
|     ret.erase("EnableMaxCacheSize"); | ||||
|     ret.erase("EvictionDelayMinutes"); | ||||
|     ret.erase("EvictionUsesAccessedTime"); | ||||
|     ret.erase("HostConfig"); | ||||
|     ret.erase("MaxCacheSizeBytes"); | ||||
|     ret.erase("MaxUploadCount"); | ||||
|     ret.erase("OnlineCheckRetrySeconds"); | ||||
|     ret.erase("OrphanedFileRetentionDays"); | ||||
|     ret.erase("PreferredDownloadType"); | ||||
|     ret.erase("ReadAheadCount"); | ||||
|     ret.erase("RetryReadCount"); | ||||
|     ret.erase("RingBufferFileSize"); | ||||
|     ret.erase("S3Config"); | ||||
|   } else if (prov_ == provider_type::s3) { | ||||
|     ret.erase("EncryptConfig"); | ||||
|     ret.erase("HostConfig"); | ||||
|   } else if (prov_ == provider_type::sia) { | ||||
|     ret.erase("EncryptConfig"); | ||||
|     ret.erase("S3Config"); | ||||
|   } else if (prov_ == provider_type::remote) { | ||||
|     ret.erase("ChunkDownloaderTimeoutSeconds"); | ||||
|     ret.erase("EnableChunkDownloaderTimeout"); | ||||
|     ret.erase("EnableChunkDownloaderTimeout"); | ||||
|     ret.erase("EnableMaxCacheSize"); | ||||
|     ret.erase("EncryptConfig"); | ||||
|     ret.erase("EvictionDelayMinutes"); | ||||
|     ret.erase("HighFreqIntervalSeconds"); | ||||
|     ret.erase("HostConfig"); | ||||
|     ret.erase("LowFreqIntervalSeconds"); | ||||
|     ret.erase("MaxCacheSizeBytes"); | ||||
|     ret.erase("MaxUploadCount"); | ||||
|     ret.erase("OnlineCheckRetrySeconds"); | ||||
|     ret.erase("OrphanedFileRetentionDays"); | ||||
|     ret.erase("PreferredDownloadType"); | ||||
|     ret.erase("ReadAheadCount"); | ||||
|     ret.erase("RetryReadCount"); | ||||
|     ret.erase("RingBufferFileSize"); | ||||
|     ret.erase("S3Config"); | ||||
|   } | ||||
|  | ||||
|   return ret; | ||||
| } | ||||
|  | ||||
| auto app_config::get_max_cache_size_bytes() const -> std::uint64_t { | ||||
|   const auto max_space = | ||||
|       std::max(static_cast<std::uint64_t>(100ULL * 1024ULL * 1024ULL), | ||||
|                max_cache_size_bytes_); | ||||
|   return std::min(utils::file::get_free_drive_space(get_cache_directory()), | ||||
|                   max_space); | ||||
| } | ||||
|  | ||||
| auto app_config::get_provider_api_password(const provider_type &prov) | ||||
|     -> std::string { | ||||
| #ifdef _WIN32 | ||||
|   auto api_file = | ||||
|       utils::path::combine(utils::get_local_app_data_directory(), | ||||
|                            {get_provider_display_name(prov), "apipassword"}); | ||||
| #else | ||||
| #ifdef __APPLE__ | ||||
|   auto api_file = | ||||
|       utils::path::combine(utils::path::resolve("~"), | ||||
|                            {"/Library/Application Support", | ||||
|                             get_provider_display_name(prov), "apipassword"}); | ||||
| #else | ||||
|   auto api_file = utils::path::combine( | ||||
|       utils::path::resolve("~/."), {get_provider_name(prov), "apipassword"}); | ||||
| #endif | ||||
| #endif | ||||
|   auto lines = utils::file::read_file_lines(api_file); | ||||
|   return lines.empty() ? "" : utils::string::trim(lines[0U]); | ||||
| } | ||||
|  | ||||
| auto app_config::get_provider_display_name(const provider_type &prov) | ||||
|     -> std::string { | ||||
|   static const std::array<std::string, | ||||
|                           static_cast<std::size_t>(provider_type::unknown)> | ||||
|       PROVIDER_DISPLAY_NAMES = { | ||||
|           "Sia", | ||||
|           "Remote", | ||||
|           "S3", | ||||
|           "Encrypt", | ||||
|       }; | ||||
|   return PROVIDER_DISPLAY_NAMES.at(static_cast<std::size_t>(prov)); | ||||
| } | ||||
|  | ||||
| auto app_config::get_provider_name(const provider_type &prov) -> std::string { | ||||
|   static const std::array<std::string, | ||||
|                           static_cast<std::size_t>(provider_type::unknown)> | ||||
|       PROVIDER_NAMES = { | ||||
|           "sia", | ||||
|           "remote", | ||||
|           "s3", | ||||
|           "encrypt", | ||||
|       }; | ||||
|   return PROVIDER_NAMES.at(static_cast<std::size_t>(prov)); | ||||
| } | ||||
|  | ||||
| auto app_config::get_value_by_name(const std::string &name) -> std::string { | ||||
|   constexpr const auto *function_name = static_cast<const char *>(__FUNCTION__); | ||||
|  | ||||
|   try { | ||||
|     if (name == "ApiAuth") { | ||||
|       return api_auth_; | ||||
|     } | ||||
|     if (name == "ApiPort") { | ||||
|       return std::to_string(get_api_port()); | ||||
|     } | ||||
|     if (name == "ApiUser") { | ||||
|       return api_user_; | ||||
|     } | ||||
|     if (name == "ChunkDownloaderTimeoutSeconds") { | ||||
|       return std::to_string(get_chunk_downloader_timeout_secs()); | ||||
|     } | ||||
|     if (name == "EnableChunkDownloaderTimeout") { | ||||
|       return utils::string::from_bool(get_enable_chunk_download_timeout()); | ||||
|     } | ||||
|     if (name == "GetEnableCommDurationEvents") { | ||||
|       return utils::string::from_bool(get_enable_comm_duration_events()); | ||||
|     } | ||||
|     if (name == "EnableDriveEvents") { | ||||
|       return utils::string::from_bool(get_enable_drive_events()); | ||||
|     } | ||||
|     if (name == "EnableMaxCacheSize") { | ||||
|       return utils::string::from_bool(get_enable_max_cache_size()); | ||||
| #ifdef _WIN32 | ||||
|     } | ||||
|     if (name == "EnableMountManager") { | ||||
|       return std::to_string(get_enable_mount_manager()); | ||||
| #endif | ||||
|     } | ||||
|     if (name == "EncryptConfig.Path") { | ||||
|       return utils::path::absolute(encrypt_config_.path); | ||||
|     } | ||||
|     if (name == "EncryptConfig.EncryptionToken") { | ||||
|       return encrypt_config_.encryption_token; | ||||
|     } | ||||
|     if (name == "EventLevel") { | ||||
|       return event_level_to_string(get_event_level()); | ||||
|     } | ||||
|     if (name == "EvictionDelayMinutes") { | ||||
|       return std::to_string(get_eviction_delay_mins()); | ||||
|     } | ||||
|     if (name == "EvictionUsesAccessedTime") { | ||||
|       return utils::string::from_bool(get_eviction_uses_accessed_time()); | ||||
|     } | ||||
|     if (name == "HighFreqIntervalSeconds") { | ||||
|       return std::to_string(get_high_frequency_interval_secs()); | ||||
|     } | ||||
|     if (name == "HostConfig.AgentString") { | ||||
|       return hc_.agent_string; | ||||
|     } | ||||
|     if (name == "HostConfig.ApiPassword") { | ||||
|       return hc_.api_password; | ||||
|     } | ||||
|     if (name == "HostConfig.ApiPort") { | ||||
|       return std::to_string(hc_.api_port); | ||||
|     } | ||||
|     if (name == "HostConfig.HostNameOrIp") { | ||||
|       return hc_.host_name_or_ip; | ||||
|     } | ||||
|     if (name == "HostConfig.TimeoutMs") { | ||||
|       return std::to_string(hc_.timeout_ms); | ||||
|     } | ||||
|     if (name == "LowFreqIntervalSeconds") { | ||||
|       return std::to_string(get_low_frequency_interval_secs()); | ||||
|     } | ||||
|     if (name == "MaxCacheSizeBytes") { | ||||
|       return std::to_string(get_max_cache_size_bytes()); | ||||
|     } | ||||
|     if (name == "MaxUploadCount") { | ||||
|       return std::to_string(get_max_upload_count()); | ||||
|     } | ||||
|     if (name == "OnlineCheckRetrySeconds") { | ||||
|       return std::to_string(get_online_check_retry_secs()); | ||||
|     } | ||||
|     if (name == "OrphanedFileRetentionDays") { | ||||
|       return std::to_string(get_orphaned_file_retention_days()); | ||||
|     } | ||||
|     if (name == "PreferredDownloadType") { | ||||
|       return utils::download_type_to_string(utils::download_type_from_string( | ||||
|           preferred_download_type_, download_type::fallback)); | ||||
|     } | ||||
|     if (name == "ReadAheadCount") { | ||||
|       return std::to_string(get_read_ahead_count()); | ||||
|     } | ||||
|     if (name == "RemoteMount.EnableRemoteMount") { | ||||
|       return utils::string::from_bool(get_enable_remote_mount()); | ||||
|     } | ||||
|     if (name == "RemoteMount.IsRemoteMount") { | ||||
|       return utils::string::from_bool(get_is_remote_mount()); | ||||
|     } | ||||
|     if (name == "RemoteMount.RemoteClientPoolSize") { | ||||
|       return std::to_string(get_remote_client_pool_size()); | ||||
|     } | ||||
|     if (name == "RemoteMount.RemoteHostNameOrIp") { | ||||
|       return get_remote_host_name_or_ip(); | ||||
|     } | ||||
|     if (name == "RemoteMount.RemoteMaxConnections") { | ||||
|       return std::to_string(get_remote_max_connections()); | ||||
|     } | ||||
|     if (name == "RemoteMount.RemotePort") { | ||||
|       return std::to_string(get_remote_port()); | ||||
|     } | ||||
|     if (name == "RemoteMount.RemoteReceiveTimeoutSeconds") { | ||||
|       return std::to_string(get_remote_receive_timeout_secs()); | ||||
|     } | ||||
|     if (name == "RemoteMount.RemoteSendTimeoutSeconds") { | ||||
|       return std::to_string(get_remote_send_timeout_secs()); | ||||
|     } | ||||
|     if (name == "RemoteMount.RemoteToken") { | ||||
|       return get_remote_token(); | ||||
|     } | ||||
|     if (name == "RetryReadCount") { | ||||
|       return std::to_string(get_retry_read_count()); | ||||
|     } | ||||
|     if (name == "RingBufferFileSize") { | ||||
|       return std::to_string(get_ring_buffer_file_size()); | ||||
|     } | ||||
|     if (name == "S3Config.AccessKey") { | ||||
|       return s3_config_.access_key; | ||||
|     } | ||||
|     if (name == "S3Config.Bucket") { | ||||
|       return s3_config_.bucket; | ||||
|     } | ||||
|     if (name == "S3Config.EncryptionToken") { | ||||
|       return s3_config_.encryption_token; | ||||
|     } | ||||
|     if (name == "S3Config.CacheTimeoutSeconds") { | ||||
|       return std::to_string(s3_config_.cache_timeout_secs); | ||||
|     } | ||||
|     if (name == "S3Config.Region") { | ||||
|       return s3_config_.region; | ||||
|     } | ||||
|     if (name == "S3Config.SecretKey") { | ||||
|       return s3_config_.secret_key; | ||||
|     } | ||||
|     if (name == "S3Config.URL") { | ||||
|       return s3_config_.url; | ||||
|     } | ||||
|     if (name == "S3Config.UsePathStyle") { | ||||
|       return utils::string::from_bool(s3_config_.use_path_style); | ||||
|     } | ||||
|     if (name == "S3Config.UseRegionInURL") { | ||||
|       return utils::string::from_bool(s3_config_.use_region_in_url); | ||||
|     } | ||||
|     if (name == "S3Config.TimeoutMs") { | ||||
|       return std::to_string(s3_config_.timeout_ms); | ||||
|     } | ||||
|   } catch (const std::exception &e) { | ||||
|     utils::error::raise_error(function_name, e, "exception occurred"); | ||||
|   } | ||||
|   return ""; | ||||
| } | ||||
|  | ||||
| auto app_config::load() -> bool { | ||||
|   constexpr const auto *function_name = static_cast<const char *>(__FUNCTION__); | ||||
|  | ||||
|   auto ret = false; | ||||
|  | ||||
|   const auto config_file_path = get_config_file_path(); | ||||
|   recur_mutex_lock lock(read_write_mutex_); | ||||
|   if (utils::file::is_file(config_file_path)) { | ||||
|     try { | ||||
|       std::ifstream config_file(config_file_path.data()); | ||||
|       if (config_file.is_open()) { | ||||
|         std::stringstream stream; | ||||
|         stream << config_file.rdbuf(); | ||||
|         const auto json_text = stream.str(); | ||||
|         config_file.close(); | ||||
|         ret = not json_text.empty(); | ||||
|         if (ret) { | ||||
|           const auto json_document = json::parse(json_text); | ||||
|  | ||||
|           get_value(json_document, "ApiAuth", api_auth_, ret); | ||||
|           get_value(json_document, "ApiPort", api_port_, ret); | ||||
|           get_value(json_document, "ApiUser", api_user_, ret); | ||||
|           get_value(json_document, "ChunkDownloaderTimeoutSeconds", | ||||
|                     download_timeout_secs_, ret); | ||||
|           get_value(json_document, "EvictionDelayMinutes", eviction_delay_mins_, | ||||
|                     ret); | ||||
|           get_value(json_document, "EvictionUsesAccessedTime", | ||||
|                     eviction_uses_accessed_time_, ret); | ||||
|           get_value(json_document, "EnableChunkDownloaderTimeout", | ||||
|                     enable_chunk_downloader_timeout_, ret); | ||||
|           get_value(json_document, "EnableCommDurationEvents", | ||||
|                     enable_comm_duration_events_, ret); | ||||
|           get_value(json_document, "EnableDriveEvents", enable_drive_events_, | ||||
|                     ret); | ||||
|  | ||||
|           if (json_document.find("EncryptConfig") != json_document.end()) { | ||||
|             auto encrypt_config_json = json_document["EncryptConfig"]; | ||||
|             auto encrypt = encrypt_config_; | ||||
|             get_value(encrypt_config_json, "Path", encrypt.path, ret); | ||||
|             encrypt_config_.path = utils::path::absolute(encrypt_config_.path); | ||||
|             get_value(encrypt_config_json, "EncryptionToken", | ||||
|                       encrypt.encryption_token, ret); | ||||
|             encrypt_config_ = encrypt; | ||||
|           } else { | ||||
|             ret = false; | ||||
|           } | ||||
|  | ||||
|           std::string level; | ||||
|           if (get_value(json_document, "EventLevel", level, ret)) { | ||||
|             event_level_ = event_level_from_string(level); | ||||
|           } | ||||
|  | ||||
|           if (json_document.find("HostConfig") != json_document.end()) { | ||||
|             auto host_config_json = json_document["HostConfig"]; | ||||
|             auto cfg = hc_; | ||||
|             get_value(host_config_json, "AgentString", cfg.agent_string, ret); | ||||
|             get_value(host_config_json, "ApiPassword", cfg.api_password, ret); | ||||
|             get_value(host_config_json, "ApiPort", cfg.api_port, ret); | ||||
|             get_value(host_config_json, "HostNameOrIp", cfg.host_name_or_ip, | ||||
|                       ret); | ||||
|             get_value(host_config_json, "TimeoutMs", cfg.timeout_ms, ret); | ||||
|             hc_ = cfg; | ||||
|           } else { | ||||
|             ret = false; | ||||
|           } | ||||
|  | ||||
|           if (hc_.api_password.empty()) { | ||||
|             hc_.api_password = get_provider_api_password(prov_); | ||||
|             if (hc_.api_password.empty()) { | ||||
|               ret = false; | ||||
|             } | ||||
|           } | ||||
|  | ||||
|           if (json_document.find("S3Config") != json_document.end()) { | ||||
|             auto s3_config_json = json_document["S3Config"]; | ||||
|             auto s3_cfg = s3_config_; | ||||
|             get_value(s3_config_json, "AccessKey", s3_cfg.access_key, ret); | ||||
|             get_value(s3_config_json, "Bucket", s3_cfg.bucket, ret); | ||||
|             get_value(s3_config_json, "CacheTimeoutSeconds", | ||||
|                       s3_cfg.cache_timeout_secs, ret); | ||||
|             get_value(s3_config_json, "EncryptionToken", | ||||
|                       s3_cfg.encryption_token, ret); | ||||
|             get_value(s3_config_json, "Region", s3_cfg.region, ret); | ||||
|             get_value(s3_config_json, "SecretKey", s3_cfg.secret_key, ret); | ||||
|             get_value(s3_config_json, "TimeoutMs", s3_cfg.timeout_ms, ret); | ||||
|             get_value(s3_config_json, "URL", s3_cfg.url, ret); | ||||
|             get_value(s3_config_json, "UsePathStyle", s3_cfg.use_path_style, | ||||
|                       ret); | ||||
|             get_value(s3_config_json, "UseRegionInURL", | ||||
|                       s3_cfg.use_region_in_url, ret); | ||||
|             s3_config_ = s3_cfg; | ||||
|           } else { | ||||
|             ret = false; | ||||
|           } | ||||
|  | ||||
|           get_value(json_document, "ReadAheadCount", read_ahead_count_, ret); | ||||
|           get_value(json_document, "RingBufferFileSize", ring_buffer_file_size_, | ||||
|                     ret); | ||||
|           get_value(json_document, "EnableMaxCacheSize", enable_max_cache_size_, | ||||
|                     ret); | ||||
| #ifdef _WIN32 | ||||
|           get_value(json_document, "EnableMountManager", enable_mount_manager_, | ||||
|                     ret); | ||||
| #endif | ||||
|           get_value(json_document, "MaxCacheSizeBytes", max_cache_size_bytes_, | ||||
|                     ret); | ||||
|           get_value(json_document, "MaxUploadCount", max_upload_count_, ret); | ||||
|           get_value(json_document, "OnlineCheckRetrySeconds", | ||||
|                     online_check_retry_secs_, ret); | ||||
|           get_value(json_document, "HighFreqIntervalSeconds", | ||||
|                     high_freq_interval_secs_, ret); | ||||
|           get_value(json_document, "LowFreqIntervalSeconds", | ||||
|                     low_freq_interval_secs_, ret); | ||||
|           get_value(json_document, "OrphanedFileRetentionDays", | ||||
|                     orphaned_file_retention_days_, ret); | ||||
|           get_value(json_document, "PreferredDownloadType", | ||||
|                     preferred_download_type_, ret); | ||||
|           get_value(json_document, "RetryReadCount", retry_read_count_, ret); | ||||
|           if (json_document.find("RemoteMount") != json_document.end()) { | ||||
|             auto remoteMount = json_document["RemoteMount"]; | ||||
|             get_value(remoteMount, "EnableRemoteMount", enable_remote_mount_, | ||||
|                       ret); | ||||
|             get_value(remoteMount, "IsRemoteMount", is_remote_mount_, ret); | ||||
|             get_value(remoteMount, "RemoteClientPoolSize", | ||||
|                       remote_client_pool_size_, ret); | ||||
|             get_value(remoteMount, "RemoteHostNameOrIp", | ||||
|                       remote_host_name_or_ip_, ret); | ||||
|             get_value(remoteMount, "RemoteMaxConnections", | ||||
|                       remote_max_connections_, ret); | ||||
|             get_value(remoteMount, "RemotePort", remote_port_, ret); | ||||
|             get_value(remoteMount, "RemoteReceiveTimeoutSeconds", | ||||
|                       remote_receive_timeout_secs_, ret); | ||||
|             get_value(remoteMount, "RemoteSendTimeoutSeconds", | ||||
|                       remote_send_timeout_secs_, ret); | ||||
|             get_value(remoteMount, "RemoteToken", remote_token_, ret); | ||||
|           } else { | ||||
|             ret = false; | ||||
|           } | ||||
|  | ||||
|           std::uint64_t version{}; | ||||
|           get_value(json_document, "Version", version, ret); | ||||
|  | ||||
|           // Handle configuration defaults for new config versions | ||||
|           if (version != REPERTORY_CONFIG_VERSION) { | ||||
|             if (version > REPERTORY_CONFIG_VERSION) { | ||||
|               version = 0U; | ||||
|             } | ||||
|  | ||||
|             version_ = version; | ||||
|             ret = false; | ||||
|           } | ||||
|         } | ||||
|       } | ||||
|  | ||||
|       if (not ret) { | ||||
|         config_changed_ = true; | ||||
|       } | ||||
|     } catch (const std::exception &ex) { | ||||
|       utils::error::raise_error(function_name, ex, "exception occurred"); | ||||
|       ret = false; | ||||
|     } | ||||
|   } | ||||
|  | ||||
|   return ret; | ||||
| } | ||||
|  | ||||
| void app_config::save() { | ||||
|   constexpr const auto *function_name = static_cast<const char *>(__FUNCTION__); | ||||
|  | ||||
|   const auto file_path = get_config_file_path(); | ||||
|   recur_mutex_lock lock(read_write_mutex_); | ||||
|   if (config_changed_ || not utils::file::is_file(file_path)) { | ||||
|     if (not utils::file::is_directory(data_directory_)) { | ||||
|       if (not utils::file::create_full_directory_path(data_directory_)) { | ||||
|         utils::error::raise_error( | ||||
|             function_name, "failed to create directory|sp|" + data_directory_ + | ||||
|                                "|err|" + | ||||
|                                std::to_string(utils::get_last_error_code())); | ||||
|       } | ||||
|     } | ||||
|     config_changed_ = false; | ||||
|     json data = get_json(); | ||||
|     auto success = false; | ||||
|     for (auto i = 0U; not success && (i < retry_save_count); i++) { | ||||
|       success = utils::file::write_json_file(file_path, data); | ||||
|       if (not success) { | ||||
|         std::this_thread::sleep_for(1s); | ||||
|       } | ||||
|     } | ||||
|   } | ||||
| } | ||||
|  | ||||
| void app_config::set_enable_remote_mount(bool enable_remote_mount) { | ||||
|   recur_mutex_lock remote_lock(remote_mount_mutex_); | ||||
|   if (get_is_remote_mount()) { | ||||
|     set_value(enable_remote_mount_, false); | ||||
|   } else { | ||||
|     set_value(enable_remote_mount_, enable_remote_mount); | ||||
|   } | ||||
| } | ||||
|  | ||||
| void app_config::set_is_remote_mount(bool is_remote_mount) { | ||||
|   recur_mutex_lock remote_lock(remote_mount_mutex_); | ||||
|  | ||||
|   if (get_enable_remote_mount()) { | ||||
|     set_value(is_remote_mount_, false); | ||||
|     return; | ||||
|   } | ||||
|  | ||||
|   set_value(is_remote_mount_, is_remote_mount); | ||||
| } | ||||
|  | ||||
| auto app_config::set_value_by_name(const std::string &name, | ||||
|                                    const std::string &value) -> std::string { | ||||
|   constexpr const auto *function_name = static_cast<const char *>(__FUNCTION__); | ||||
|  | ||||
|   try { | ||||
|     if (name == "ApiAuth") { | ||||
|       set_api_auth(value); | ||||
|       return get_api_auth(); | ||||
|     } | ||||
|     if (name == "ApiPort") { | ||||
|       set_api_port(utils::string::to_uint16(value)); | ||||
|       return std::to_string(get_api_port()); | ||||
|     } | ||||
|     if (name == "ApiUser") { | ||||
|       set_api_user(value); | ||||
|       return get_api_user(); | ||||
|     } | ||||
|     if (name == "ChunkDownloaderTimeoutSeconds") { | ||||
|       set_chunk_downloader_timeout_secs(utils::string::to_uint8(value)); | ||||
|       return std::to_string(get_chunk_downloader_timeout_secs()); | ||||
|     } | ||||
|     if (name == "EnableChunkDownloaderTimeout") { | ||||
|       set_enable_chunk_downloader_timeout(utils::string::to_bool(value)); | ||||
|       return utils::string::from_bool(get_enable_chunk_download_timeout()); | ||||
|     } | ||||
|     if (name == "EnableCommDurationEvents") { | ||||
|       set_enable_comm_duration_events(utils::string::to_bool(value)); | ||||
|       return utils::string::from_bool(get_enable_comm_duration_events()); | ||||
|     } | ||||
|     if (name == "EnableDriveEvents") { | ||||
|       set_enable_drive_events(utils::string::to_bool(value)); | ||||
|       return utils::string::from_bool(get_enable_drive_events()); | ||||
|     } | ||||
|     if (name == "EnableMaxCacheSize") { | ||||
|       set_enable_max_cache_size(utils::string::to_bool(value)); | ||||
|       return utils::string::from_bool(get_enable_max_cache_size()); | ||||
| #ifdef _WIN32 | ||||
|     } | ||||
|     if (name == "EnableMountManager") { | ||||
|       set_enable_mount_manager(utils::string::to_bool(value)); | ||||
|       return std::to_string(get_enable_mount_manager()); | ||||
| #endif | ||||
|     } | ||||
|     if (name == "EncryptConfig.EncryptionToken") { | ||||
|       set_value(encrypt_config_.encryption_token, value); | ||||
|       return encrypt_config_.encryption_token; | ||||
|     } | ||||
|     if (name == "EncryptConfig.Path") { | ||||
|       set_value(encrypt_config_.path, utils::path::absolute(value)); | ||||
|       return encrypt_config_.path; | ||||
|     } | ||||
|     if (name == "EventLevel") { | ||||
|       set_event_level(event_level_from_string(value)); | ||||
|       return event_level_to_string(get_event_level()); | ||||
|     } | ||||
|     if (name == "EvictionDelayMinutes") { | ||||
|       set_eviction_delay_mins(utils::string::to_uint32(value)); | ||||
|       return std::to_string(get_eviction_delay_mins()); | ||||
|     } | ||||
|     if (name == "EvictionUsesAccessedTime") { | ||||
|       set_eviction_uses_accessed_time(utils::string::to_bool(value)); | ||||
|       return utils::string::from_bool(get_eviction_uses_accessed_time()); | ||||
|     } | ||||
|     if (name == "HighFreqIntervalSeconds") { | ||||
|       set_high_frequency_interval_secs(utils::string::to_uint8(value)); | ||||
|       return std::to_string(get_high_frequency_interval_secs()); | ||||
|     } | ||||
|     if (name == "HostConfig.AgentString") { | ||||
|       set_value(hc_.agent_string, value); | ||||
|       return hc_.agent_string; | ||||
|     } | ||||
|     if (name == "HostConfig.ApiPassword") { | ||||
|       set_value(hc_.api_password, value); | ||||
|       return hc_.api_password; | ||||
|     } | ||||
|     if (name == "HostConfig.ApiPort") { | ||||
|       set_value(hc_.api_port, utils::string::to_uint16(value)); | ||||
|       return std::to_string(hc_.api_port); | ||||
|     } | ||||
|     if (name == "HostConfig.HostNameOrIp") { | ||||
|       set_value(hc_.host_name_or_ip, value); | ||||
|       return hc_.host_name_or_ip; | ||||
|     } | ||||
|     if (name == "HostConfig.TimeoutMs") { | ||||
|       set_value(hc_.timeout_ms, utils::string::to_uint32(value)); | ||||
|       return std::to_string(hc_.timeout_ms); | ||||
|     } | ||||
|     if (name == "LowFreqIntervalSeconds") { | ||||
|       set_low_frequency_interval_secs(utils::string::to_uint32(value)); | ||||
|       return std::to_string(get_low_frequency_interval_secs()); | ||||
|     } | ||||
|     if (name == "MaxCacheSizeBytes") { | ||||
|       set_max_cache_size_bytes(utils::string::to_uint64(value)); | ||||
|       return std::to_string(get_max_cache_size_bytes()); | ||||
|     } | ||||
|     if (name == "MaxUploadCount") { | ||||
|       set_max_upload_count(utils::string::to_uint8(value)); | ||||
|       return std::to_string(get_max_upload_count()); | ||||
|     } | ||||
|     if (name == "OnlineCheckRetrySeconds") { | ||||
|       set_online_check_retry_secs(utils::string::to_uint16(value)); | ||||
|       return std::to_string(get_online_check_retry_secs()); | ||||
|     } | ||||
|     if (name == "OrphanedFileRetentionDays") { | ||||
|       set_orphaned_file_retention_days(utils::string::to_uint16(value)); | ||||
|       return std::to_string(get_orphaned_file_retention_days()); | ||||
|     } | ||||
|     if (name == "PreferredDownloadType") { | ||||
|       set_preferred_download_type( | ||||
|           utils::download_type_from_string(value, download_type::fallback)); | ||||
|       return utils::download_type_to_string(get_preferred_download_type()); | ||||
|     } | ||||
|     if (name == "ReadAheadCount") { | ||||
|       set_read_ahead_count(utils::string::to_uint8(value)); | ||||
|       return std::to_string(get_read_ahead_count()); | ||||
|     } | ||||
|     if (name == "RemoteMount.EnableRemoteMount") { | ||||
|       set_enable_remote_mount(utils::string::to_bool(value)); | ||||
|       return utils::string::from_bool(get_enable_remote_mount()); | ||||
|     } | ||||
|     if (name == "RemoteMount.IsRemoteMount") { | ||||
|       set_is_remote_mount(utils::string::to_bool(value)); | ||||
|       return utils::string::from_bool(get_is_remote_mount()); | ||||
|     } | ||||
|     if (name == "RemoteMount.RemoteClientPoolSize") { | ||||
|       set_remote_client_pool_size(utils::string::to_uint8(value)); | ||||
|       return std::to_string(get_remote_client_pool_size()); | ||||
|     } | ||||
|     if (name == "RemoteMount.RemoteHostNameOrIp") { | ||||
|       set_remote_host_name_or_ip(value); | ||||
|       return get_remote_host_name_or_ip(); | ||||
|     } | ||||
|     if (name == "RemoteMount.RemoteMaxConnections") { | ||||
|       set_remote_max_connections(utils::string::to_uint8(value)); | ||||
|       return std::to_string(get_remote_max_connections()); | ||||
|     } | ||||
|     if (name == "RemoteMount.RemotePort") { | ||||
|       set_remote_port(utils::string::to_uint16(value)); | ||||
|       return std::to_string(get_remote_port()); | ||||
|     } | ||||
|     if (name == "RemoteMount.RemoteReceiveTimeoutSeconds") { | ||||
|       set_remote_receive_timeout_secs(utils::string::to_uint16(value)); | ||||
|       return std::to_string(get_remote_receive_timeout_secs()); | ||||
|     } | ||||
|     if (name == "RemoteMount.RemoteSendTimeoutSeconds") { | ||||
|       set_remote_send_timeout_secs(utils::string::to_uint16(value)); | ||||
|       return std::to_string(get_remote_send_timeout_secs()); | ||||
|     } | ||||
|     if (name == "RemoteMount.RemoteToken") { | ||||
|       set_remote_token(value); | ||||
|       return get_remote_token(); | ||||
|     } | ||||
|     if (name == "RetryReadCount") { | ||||
|       set_retry_read_count(utils::string::to_uint16(value)); | ||||
|       return std::to_string(get_retry_read_count()); | ||||
|     } | ||||
|     if (name == "RingBufferFileSize") { | ||||
|       set_ring_buffer_file_size(utils::string::to_uint16(value)); | ||||
|       return std::to_string(get_ring_buffer_file_size()); | ||||
|     } | ||||
|     if (name == "S3Config.AccessKey") { | ||||
|       set_value(s3_config_.access_key, value); | ||||
|       return s3_config_.access_key; | ||||
|     } | ||||
|     if (name == "S3Config.Bucket") { | ||||
|       set_value(s3_config_.bucket, value); | ||||
|       return s3_config_.bucket; | ||||
|     } | ||||
|     if (name == "S3Config.CacheTimeoutSeconds") { | ||||
|       const auto timeout = | ||||
|           std::max(std::uint16_t(5U), utils::string::to_uint16(value)); | ||||
|       set_value(s3_config_.cache_timeout_secs, timeout); | ||||
|       return std::to_string(s3_config_.cache_timeout_secs); | ||||
|     } | ||||
|     if (name == "S3Config.Region") { | ||||
|       set_value(s3_config_.region, value); | ||||
|       return s3_config_.region; | ||||
|     } | ||||
|     if (name == "S3Config.SecretKey") { | ||||
|       set_value(s3_config_.secret_key, value); | ||||
|       return s3_config_.secret_key; | ||||
|     } | ||||
|     if (name == "S3Config.URL") { | ||||
|       set_value(s3_config_.url, value); | ||||
|       return s3_config_.url; | ||||
|     } | ||||
|     if (name == "S3Config.UsePathStyle") { | ||||
|       set_value(s3_config_.use_path_style, utils::string::to_bool(value)); | ||||
|       return utils::string::from_bool(s3_config_.use_path_style); | ||||
|     } | ||||
|     if (name == "S3Config.UseRegionInURL") { | ||||
|       set_value(s3_config_.use_region_in_url, utils::string::to_bool(value)); | ||||
|       return utils::string::from_bool(s3_config_.use_region_in_url); | ||||
|     } | ||||
|     if (name == "S3Config.TimeoutMs") { | ||||
|       set_value(s3_config_.timeout_ms, utils::string::to_uint32(value)); | ||||
|       return std::to_string(s3_config_.timeout_ms); | ||||
|     } | ||||
|     if (name == "S3Config.EncryptionToken") { | ||||
|       set_value(s3_config_.encryption_token, value); | ||||
|       return s3_config_.encryption_token; | ||||
|     } | ||||
|   } catch (const std::exception &e) { | ||||
|     utils::error::raise_error(function_name, e, "exception occurred"); | ||||
|   } | ||||
|  | ||||
|   return ""; | ||||
| } | ||||
| } // namespace repertory | ||||
							
								
								
									
										190
									
								
								repertory/librepertory/src/comm/curl/curl_comm.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										190
									
								
								repertory/librepertory/src/comm/curl/curl_comm.cpp
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,190 @@ | ||||
| /* | ||||
|   Copyright <2018-2024> <scott.e.graves@protonmail.com> | ||||
|  | ||||
|   Permission is hereby granted, free of charge, to any person obtaining a copy | ||||
|   of this software and associated documentation files (the "Software"), to deal | ||||
|   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 "comm/curl/curl_comm.hpp" | ||||
|  | ||||
| #include "types/repertory.hpp" | ||||
| #include "utils/path_utils.hpp" | ||||
| #include "utils/string_utils.hpp" | ||||
|  | ||||
| namespace repertory { | ||||
| const curl_comm::write_callback curl_comm::write_data = | ||||
|     static_cast<curl_comm::write_callback>([](char *buffer, size_t size, | ||||
|                                               size_t nitems, | ||||
|                                               void *outstream) -> size_t { | ||||
|       auto &info = *reinterpret_cast<read_write_info *>(outstream); | ||||
|       std::copy(buffer, buffer + (size * nitems), | ||||
|                 std::back_inserter(info.data)); | ||||
|       return info.stop_requested ? 0 : size * nitems; | ||||
|     }); | ||||
|  | ||||
| const curl_comm::write_callback curl_comm::write_headers = | ||||
|     static_cast<curl_comm::write_callback>([](char *buffer, size_t size, | ||||
|                                               size_t nitems, | ||||
|                                               void *outstream) -> size_t { | ||||
|       auto &headers = *reinterpret_cast<http_headers *>(outstream); | ||||
|       const auto header = std::string(buffer, size * nitems); | ||||
|       const auto parts = utils::string::split(header, ':'); | ||||
|       if (parts.size() > 1U) { | ||||
|         auto data = header.substr(parts[0U].size() + 1U); | ||||
|         utils::string::left_trim(data); | ||||
|         utils::string::right_trim(data, '\r'); | ||||
|         utils::string::right_trim(data, '\n'); | ||||
|         utils::string::right_trim(data, '\r'); | ||||
|         headers[utils::string::to_lower(parts[0U])] = data; | ||||
|       } | ||||
|       return size * nitems; | ||||
|     }); | ||||
|  | ||||
| curl_comm::curl_comm(host_config cfg) | ||||
|     : host_config_(std::move(cfg)), s3_config_(std::nullopt) {} | ||||
|  | ||||
| curl_comm::curl_comm(s3_config cfg) | ||||
|     : host_config_(std::nullopt), s3_config_(std::move(cfg)) {} | ||||
|  | ||||
| auto curl_comm::construct_url(CURL *curl, const std::string &relative_path, | ||||
|                               const host_config &cfg) -> std::string { | ||||
|   static constexpr const auto http = 80U; | ||||
|   static constexpr const auto https = 443U; | ||||
|  | ||||
|   auto custom_port = (((cfg.protocol == "http") && | ||||
|                        (cfg.api_port == http || cfg.api_port == 0U)) || | ||||
|                       ((cfg.protocol == "https") && | ||||
|                        (cfg.api_port == https || cfg.api_port == 0U))) | ||||
|                          ? "" | ||||
|                          : ":" + std::to_string(cfg.api_port); | ||||
|   auto url = cfg.protocol + "://" + | ||||
|              utils::string::trim_copy(cfg.host_name_or_ip) + custom_port; | ||||
|  | ||||
|   static const auto complete_url = [](const std::string ¤t_path, | ||||
|                                       const std::string &parent_path, | ||||
|                                       std::string &final_url) -> std::string & { | ||||
|     final_url += utils::path::create_api_path(current_path); | ||||
|     if (utils::string::ends_with(parent_path, "/")) { | ||||
|       final_url += '/'; | ||||
|     } | ||||
|     return final_url; | ||||
|   }; | ||||
|  | ||||
|   auto path = utils::path::combine("/", {cfg.path}); | ||||
|   return relative_path.empty() | ||||
|              ? complete_url(path, cfg.path, url) | ||||
|              : complete_url(utils::path::combine( | ||||
|                                 path, {url_encode(curl, relative_path, true)}), | ||||
|                             relative_path, url); | ||||
| } | ||||
|  | ||||
| auto curl_comm::create_host_config(const s3_config &cfg, bool use_s3_path_style) | ||||
|     -> host_config { | ||||
|   host_config host_cfg{}; | ||||
|   host_cfg.api_password = cfg.secret_key; | ||||
|   host_cfg.api_user = cfg.access_key; | ||||
|  | ||||
|   auto pos = cfg.url.find(':'); | ||||
|   host_cfg.host_name_or_ip = cfg.url.substr(pos + 3U); | ||||
|   if (cfg.use_region_in_url && not cfg.region.empty()) { | ||||
|     auto parts = utils::string::split(host_cfg.host_name_or_ip, '.', false); | ||||
|     if (parts.size() > 1U) { | ||||
|       parts.insert(parts.begin() + 1U, cfg.region); | ||||
|       host_cfg.host_name_or_ip = utils::string::join(parts, '.'); | ||||
|     } | ||||
|   } | ||||
|  | ||||
|   if (not use_s3_path_style) { | ||||
|     host_cfg.host_name_or_ip = cfg.bucket + '.' + host_cfg.host_name_or_ip; | ||||
|   } | ||||
|  | ||||
|   host_cfg.protocol = cfg.url.substr(0U, pos); | ||||
|   if (use_s3_path_style) { | ||||
|     host_cfg.path = '/' + cfg.bucket; | ||||
|   } | ||||
|  | ||||
|   return host_cfg; | ||||
| } | ||||
|  | ||||
| void curl_comm::enable_s3_path_style(bool enable) { | ||||
|   use_s3_path_style_ = enable; | ||||
| } | ||||
|  | ||||
| auto curl_comm::make_request(const curl::requests::http_delete &del, | ||||
|                              long &response_code, | ||||
|                              stop_type &stop_requested) const -> bool { | ||||
|   return make_request( | ||||
|       s3_config_.has_value() | ||||
|           ? create_host_config(s3_config_.value(), use_s3_path_style_) | ||||
|           : host_config_.value_or(host_config{}), | ||||
|       del, response_code, stop_requested); | ||||
| } | ||||
|  | ||||
| auto curl_comm::make_request(const curl::requests::http_get &get, | ||||
|                              long &response_code, | ||||
|                              stop_type &stop_requested) const -> bool { | ||||
|   return make_request( | ||||
|       s3_config_.has_value() | ||||
|           ? create_host_config(s3_config_.value(), use_s3_path_style_) | ||||
|           : host_config_.value_or(host_config{}), | ||||
|       get, response_code, stop_requested); | ||||
| } | ||||
|  | ||||
| auto curl_comm::make_request(const curl::requests::http_head &head, | ||||
|                              long &response_code, | ||||
|                              stop_type &stop_requested) const -> bool { | ||||
|   return make_request( | ||||
|       s3_config_.has_value() | ||||
|           ? create_host_config(s3_config_.value(), use_s3_path_style_) | ||||
|           : host_config_.value_or(host_config{}), | ||||
|       head, response_code, stop_requested); | ||||
| } | ||||
|  | ||||
| auto curl_comm::make_request(const curl::requests::http_post &post, | ||||
|                              long &response_code, | ||||
|                              stop_type &stop_requested) const -> bool { | ||||
|   return make_request( | ||||
|       s3_config_.has_value() | ||||
|           ? create_host_config(s3_config_.value(), use_s3_path_style_) | ||||
|           : host_config_.value_or(host_config{}), | ||||
|       post, response_code, stop_requested); | ||||
| } | ||||
|  | ||||
| auto curl_comm::make_request(const curl::requests::http_put_file &put_file, | ||||
|                              long &response_code, | ||||
|                              stop_type &stop_requested) const -> bool { | ||||
|   return make_request( | ||||
|       s3_config_.has_value() | ||||
|           ? create_host_config(s3_config_.value(), use_s3_path_style_) | ||||
|           : host_config_.value_or(host_config{}), | ||||
|       put_file, response_code, stop_requested); | ||||
| } | ||||
|  | ||||
| auto curl_comm::url_encode(CURL *curl, const std::string &data, | ||||
|                            bool allow_slash) -> std::string { | ||||
|   auto *value = | ||||
|       curl_easy_escape(curl, data.c_str(), static_cast<int>(data.size())); | ||||
|   std::string ret = value; | ||||
|   curl_free(value); | ||||
|  | ||||
|   if (allow_slash) { | ||||
|     utils::string::replace(ret, "%2F", "/"); | ||||
|   } | ||||
|  | ||||
|   return ret; | ||||
| } | ||||
| } // namespace repertory | ||||
							
								
								
									
										68
									
								
								repertory/librepertory/src/comm/curl/multi_request.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										68
									
								
								repertory/librepertory/src/comm/curl/multi_request.cpp
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,68 @@ | ||||
| /* | ||||
|   Copyright <2018-2024> <scott.e.graves@protonmail.com> | ||||
|  | ||||
|   Permission is hereby granted, free of charge, to any person obtaining a copy | ||||
|   of this software and associated documentation files (the "Software"), to deal | ||||
|   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 "comm/curl/multi_request.hpp" | ||||
|  | ||||
| #include "utils/utils.hpp" | ||||
|  | ||||
| namespace repertory { | ||||
| multi_request::multi_request(CURL *curl_handle, stop_type &stop_requested) | ||||
|     : curl_handle_(curl_handle), | ||||
|       stop_requested_(stop_requested), | ||||
|       multi_handle_(curl_multi_init()) { | ||||
|   curl_multi_add_handle(multi_handle_, curl_handle); | ||||
| } | ||||
|  | ||||
| multi_request::~multi_request() { | ||||
|   curl_multi_remove_handle(multi_handle_, curl_handle_); | ||||
|   curl_easy_cleanup(curl_handle_); | ||||
|   curl_multi_cleanup(multi_handle_); | ||||
| } | ||||
|  | ||||
| void multi_request::get_result(CURLcode &curl_code, long &http_code) { | ||||
|   static constexpr const auto timeout_ms = 100; | ||||
|  | ||||
|   curl_code = CURLcode::CURLE_ABORTED_BY_CALLBACK; | ||||
|   http_code = -1; | ||||
|  | ||||
|   auto error = false; | ||||
|   int running_handles = 0; | ||||
|   curl_multi_perform(multi_handle_, &running_handles); | ||||
|   while (not error && (running_handles > 0) && not stop_requested_) { | ||||
|     int ignored{}; | ||||
|     curl_multi_wait(multi_handle_, nullptr, 0, timeout_ms, &ignored); | ||||
|  | ||||
|     const auto ret = curl_multi_perform(multi_handle_, &running_handles); | ||||
|     error = (ret != CURLM_CALL_MULTI_PERFORM) && (ret != CURLM_OK); | ||||
|   } | ||||
|  | ||||
|   if (not stop_requested_) { | ||||
|     int remaining_messages = 0; | ||||
|     auto *multi_result = | ||||
|         curl_multi_info_read(multi_handle_, &remaining_messages); | ||||
|     if ((multi_result != nullptr) && (multi_result->msg == CURLMSG_DONE)) { | ||||
|       curl_easy_getinfo(multi_result->easy_handle, CURLINFO_RESPONSE_CODE, | ||||
|                         &http_code); | ||||
|       curl_code = multi_result->data.result; | ||||
|     } | ||||
|   } | ||||
| } | ||||
| } // namespace repertory | ||||
							
								
								
									
										45
									
								
								repertory/librepertory/src/comm/curl/requests/http_post.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										45
									
								
								repertory/librepertory/src/comm/curl/requests/http_post.cpp
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,45 @@ | ||||
| /* | ||||
|   Copyright <2018-2024> <scott.e.graves@protonmail.com> | ||||
|  | ||||
|   Permission is hereby granted, free of charge, to any person obtaining a copy | ||||
|   of this software and associated documentation files (the "Software"), to deal | ||||
|   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 "comm/curl/requests/http_post.hpp" | ||||
|  | ||||
| namespace repertory::curl::requests { | ||||
| http_post::~http_post() { | ||||
|   if (headers != nullptr) { | ||||
|     curl_slist_free_all(headers); | ||||
|   } | ||||
| } | ||||
|  | ||||
| auto http_post::set_method(CURL *curl, stop_type & /*stop_requested*/) const | ||||
|     -> bool { | ||||
|   curl_easy_setopt(curl, CURLOPT_CUSTOMREQUEST, "POST"); | ||||
|   if (json.has_value()) { | ||||
|     headers = curl_slist_append(headers, "content-type: application/json"); | ||||
|     curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headers); | ||||
|  | ||||
|     json_str = json->dump(); | ||||
|     curl_easy_setopt(curl, CURLOPT_POSTFIELDS, json_str->c_str()); | ||||
|     curl_easy_setopt(curl, CURLOPT_POSTFIELDSIZE, -1L); | ||||
|   } | ||||
|  | ||||
|   return true; | ||||
| } | ||||
| } // namespace repertory::curl::requests | ||||
| @@ -0,0 +1,69 @@ | ||||
| /* | ||||
|   Copyright <2018-2024> <scott.e.graves@protonmail.com> | ||||
|  | ||||
|   Permission is hereby granted, free of charge, to any person obtaining a copy | ||||
|   of this software and associated documentation files (the "Software"), to deal | ||||
|   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 "comm/curl/requests/http_put_file.hpp" | ||||
|  | ||||
| #include "utils/string_utils.hpp" | ||||
|  | ||||
| namespace repertory::curl::requests { | ||||
| auto http_put_file::set_method(CURL *curl, stop_type &stop_requested) const | ||||
|     -> bool { | ||||
|   curl_easy_setopt(curl, CURLOPT_CUSTOMREQUEST, "PUT"); | ||||
|   curl_easy_setopt(curl, CURLOPT_UPLOAD, 1L); | ||||
|  | ||||
|   if (source_path.empty()) { | ||||
|     curl_easy_setopt(curl, CURLOPT_INFILESIZE_LARGE, 0L); | ||||
|     return true; | ||||
|   } | ||||
|  | ||||
|   if (reader) { | ||||
|     curl_easy_setopt(curl, CURLOPT_READDATA, reader.get()); | ||||
|     curl_easy_setopt( | ||||
|         curl, CURLOPT_READFUNCTION, | ||||
|         static_cast<curl_read_callback>( | ||||
|             utils::encryption::encrypting_reader::reader_function)); | ||||
|     curl_easy_setopt(curl, CURLOPT_INFILESIZE_LARGE, reader->get_total_size()); | ||||
|     return true; | ||||
|   } | ||||
|  | ||||
|   read_info = std::make_shared<read_file_info>(read_file_info{ | ||||
|       stop_requested, | ||||
|   }); | ||||
|  | ||||
|   if (native_file::create_or_open(source_path, read_info->nf) != | ||||
|       api_error::success) { | ||||
|     return false; | ||||
|   } | ||||
|  | ||||
|   read_info->nf->set_auto_close(true); | ||||
|  | ||||
|   std::uint64_t file_size{}; | ||||
|   if (not read_info->nf->get_file_size(file_size)) { | ||||
|     return false; | ||||
|   } | ||||
|  | ||||
|   curl_easy_setopt(curl, CURLOPT_READDATA, read_info.get()); | ||||
|   curl_easy_setopt(curl, CURLOPT_READFUNCTION, read_file_data); | ||||
|   curl_easy_setopt(curl, CURLOPT_INFILESIZE_LARGE, file_size); | ||||
|  | ||||
|   return true; | ||||
| } | ||||
| } // namespace repertory::curl::requests | ||||
							
								
								
									
										162
									
								
								repertory/librepertory/src/comm/packet/client_pool.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										162
									
								
								repertory/librepertory/src/comm/packet/client_pool.cpp
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,162 @@ | ||||
| /* | ||||
|   Copyright <2018-2024> <scott.e.graves@protonmail.com> | ||||
|  | ||||
|   Permission is hereby granted, free of charge, to any person obtaining a copy | ||||
|   of this software and associated documentation files (the "Software"), to deal | ||||
|   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 "comm/packet/client_pool.hpp" | ||||
|  | ||||
| #include "events/event_system.hpp" | ||||
| #include "events/events.hpp" | ||||
| #include "utils/error_utils.hpp" | ||||
|  | ||||
| namespace repertory { | ||||
| void client_pool::pool::execute( | ||||
|     std::uint64_t thread_id, const worker_callback &worker, | ||||
|     const worker_complete_callback &worker_complete) { | ||||
|   const auto index = thread_id % pool_queues_.size(); | ||||
|   auto job = std::make_shared<work_item>(worker, worker_complete); | ||||
|   auto &pool_queue = pool_queues_[index]; | ||||
|  | ||||
|   unique_mutex_lock queue_lock(pool_queue->mutex); | ||||
|   pool_queue->queue.emplace_back(job); | ||||
|   pool_queue->notify.notify_all(); | ||||
|   queue_lock.unlock(); | ||||
| } | ||||
|  | ||||
| client_pool::pool::pool(std::uint8_t pool_size) { | ||||
|   constexpr const auto *function_name = static_cast<const char *>(__FUNCTION__); | ||||
|  | ||||
|   event_system::instance().raise<service_started>("client_pool"); | ||||
|  | ||||
|   for (std::uint8_t i = 0U; i < pool_size; i++) { | ||||
|     pool_queues_.emplace_back(std::make_unique<work_queue>()); | ||||
|   } | ||||
|  | ||||
|   for (std::size_t i = 0U; i < pool_queues_.size(); i++) { | ||||
|     pool_threads_.emplace_back([this]() { | ||||
|       const auto thread_index = thread_index_++; | ||||
|  | ||||
|       auto &pool_queue = pool_queues_[thread_index]; | ||||
|       auto &queue = pool_queue->queue; | ||||
|       auto &queue_mutex = pool_queue->mutex; | ||||
|       auto &queue_notify = pool_queue->notify; | ||||
|  | ||||
|       unique_mutex_lock queue_lock(queue_mutex); | ||||
|       queue_notify.notify_all(); | ||||
|       queue_lock.unlock(); | ||||
|       while (not shutdown_) { | ||||
|         queue_lock.lock(); | ||||
|         if (queue.empty()) { | ||||
|           queue_notify.wait(queue_lock); | ||||
|         } | ||||
|  | ||||
|         while (not queue.empty()) { | ||||
|           auto item = queue.front(); | ||||
|           queue.pop_front(); | ||||
|           queue_notify.notify_all(); | ||||
|           queue_lock.unlock(); | ||||
|  | ||||
|           try { | ||||
|             const auto result = item->work(); | ||||
|             item->work_complete(result); | ||||
|           } catch (const std::exception &e) { | ||||
|             item->work_complete(utils::from_api_error(api_error::error)); | ||||
|             utils::error::raise_error(function_name, e, | ||||
|                                       "exception occurred in work item"); | ||||
|           } | ||||
|  | ||||
|           queue_lock.lock(); | ||||
|         } | ||||
|  | ||||
|         queue_notify.notify_all(); | ||||
|         queue_lock.unlock(); | ||||
|       } | ||||
|  | ||||
|       queue_lock.lock(); | ||||
|       while (not queue.empty()) { | ||||
|         auto job = queue.front(); | ||||
|         queue.pop_front(); | ||||
|         queue_notify.notify_all(); | ||||
|         queue_lock.unlock(); | ||||
|  | ||||
|         job->work_complete(utils::from_api_error(api_error::download_stopped)); | ||||
|  | ||||
|         queue_lock.lock(); | ||||
|       } | ||||
|  | ||||
|       queue_notify.notify_all(); | ||||
|       queue_lock.unlock(); | ||||
|     }); | ||||
|   } | ||||
| } | ||||
|  | ||||
| void client_pool::pool::shutdown() { | ||||
|   shutdown_ = true; | ||||
|  | ||||
|   for (auto &pool_queue : pool_queues_) { | ||||
|     mutex_lock lock(pool_queue->mutex); | ||||
|     pool_queue->notify.notify_all(); | ||||
|   } | ||||
|  | ||||
|   for (auto &thread : pool_threads_) { | ||||
|     thread.join(); | ||||
|   } | ||||
|  | ||||
|   pool_queues_.clear(); | ||||
|   pool_threads_.clear(); | ||||
| } | ||||
|  | ||||
| void client_pool::execute(const std::string &client_id, std::uint64_t thread_id, | ||||
|                           const worker_callback &worker, | ||||
|                           const worker_complete_callback &worker_complete) { | ||||
|   unique_mutex_lock pool_lock(pool_mutex_); | ||||
|   if (shutdown_) { | ||||
|     pool_lock.unlock(); | ||||
|     throw std::runtime_error("Client pool is shutdown"); | ||||
|   } | ||||
|  | ||||
|   if (not pool_lookup_[client_id]) { | ||||
|     pool_lookup_[client_id] = std::make_shared<pool>(pool_size_); | ||||
|   } | ||||
|  | ||||
|   pool_lookup_[client_id]->execute(thread_id, worker, worker_complete); | ||||
|   pool_lock.unlock(); | ||||
| } | ||||
|  | ||||
| void client_pool::remove_client(const std::string &client_id) { | ||||
|   mutex_lock pool_lock(pool_mutex_); | ||||
|   pool_lookup_.erase(client_id); | ||||
| } | ||||
|  | ||||
| void client_pool::shutdown() { | ||||
|   if (not shutdown_) { | ||||
|     event_system::instance().raise<service_shutdown_begin>("client_pool"); | ||||
|     unique_mutex_lock pool_lock(pool_mutex_); | ||||
|     if (not shutdown_) { | ||||
|       shutdown_ = true; | ||||
|       for (auto &pool_entry : pool_lookup_) { | ||||
|         pool_entry.second->shutdown(); | ||||
|       } | ||||
|       pool_lookup_.clear(); | ||||
|     } | ||||
|     pool_lock.unlock(); | ||||
|     event_system::instance().raise<service_shutdown_end>("client_pool"); | ||||
|   } | ||||
| } | ||||
| } // namespace repertory | ||||
							
								
								
									
										575
									
								
								repertory/librepertory/src/comm/packet/packet.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										575
									
								
								repertory/librepertory/src/comm/packet/packet.cpp
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,575 @@ | ||||
| /* | ||||
|   Copyright <2018-2024> <scott.e.graves@protonmail.com> | ||||
|  | ||||
|   Permission is hereby granted, free of charge, to any person obtaining a copy | ||||
|   of this software and associated documentation files (the "Software"), to deal | ||||
|   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 "comm/packet/packet.hpp" | ||||
|  | ||||
| #include "events/event_system.hpp" | ||||
| #include "events/events.hpp" | ||||
| #include "types/remote.hpp" | ||||
| #include "types/repertory.hpp" | ||||
| #include "utils/encryption.hpp" | ||||
| #include "utils/error_utils.hpp" | ||||
| #include "utils/utils.hpp" | ||||
|  | ||||
| namespace repertory { | ||||
| void packet::clear() { | ||||
|   buffer_.clear(); | ||||
|   decode_offset_ = 0U; | ||||
| } | ||||
|  | ||||
| auto packet::decode(std::string &data) -> packet::error_type { | ||||
|   const auto *str = &buffer_[decode_offset_]; | ||||
|   const auto length = strnlen(str, buffer_.size() - decode_offset_); | ||||
|   data = std::string(str, length); | ||||
|   decode_offset_ += (length + 1); | ||||
|  | ||||
|   return utils::from_api_error(api_error::success); | ||||
| } | ||||
|  | ||||
| auto packet::decode(std::wstring &data) -> packet::error_type { | ||||
|   std::string utf8_string; | ||||
|   const auto ret = decode(utf8_string); | ||||
|   if (ret == 0) { | ||||
|     data = utils::string::from_utf8(utf8_string); | ||||
|   } | ||||
|  | ||||
|   return utils::from_api_error(api_error::success); | ||||
| } | ||||
|  | ||||
| auto packet::decode(void *&ptr) -> packet::error_type { | ||||
|   return decode(reinterpret_cast<std::uint64_t &>(ptr)); | ||||
| } | ||||
|  | ||||
| auto packet::decode(void *buffer, std::size_t size) -> packet::error_type { | ||||
|   if (size != 0U) { | ||||
|     const auto read_size = | ||||
|         utils::calculate_read_size(buffer_.size(), size, decode_offset_); | ||||
|     if (read_size == size) { | ||||
|       memcpy(buffer, &buffer_[decode_offset_], size); | ||||
|       decode_offset_ += size; | ||||
|       return utils::from_api_error(api_error::success); | ||||
|     } | ||||
|  | ||||
|     return ((decode_offset_ + size) > buffer_.size()) | ||||
|                ? utils::from_api_error(api_error::buffer_overflow) | ||||
|                : utils::from_api_error(api_error::buffer_too_small); | ||||
|   } | ||||
|   return utils::from_api_error(api_error::success); | ||||
| } | ||||
|  | ||||
| auto packet::decode(std::int8_t &val) -> packet::error_type { | ||||
|   const auto ret = decode(&val, sizeof(val)); | ||||
|   if (ret == 0) { | ||||
|     boost::endian::big_to_native_inplace(val); | ||||
|   } | ||||
|   return ret; | ||||
| } | ||||
|  | ||||
| auto packet::decode(std::uint8_t &val) -> packet::error_type { | ||||
|   const auto ret = decode(&val, sizeof(val)); | ||||
|   if (ret == 0) { | ||||
|     boost::endian::big_to_native_inplace(val); | ||||
|   } | ||||
|   return ret; | ||||
| } | ||||
|  | ||||
| auto packet::decode(std::int16_t &val) -> packet::error_type { | ||||
|   const auto ret = decode(&val, sizeof(val)); | ||||
|   if (ret == 0) { | ||||
|     boost::endian::big_to_native_inplace(val); | ||||
|   } | ||||
|   return ret; | ||||
| } | ||||
|  | ||||
| auto packet::decode(std::uint16_t &val) -> packet::error_type { | ||||
|   const auto ret = decode(&val, sizeof(val)); | ||||
|   if (ret == 0) { | ||||
|     boost::endian::big_to_native_inplace(val); | ||||
|   } | ||||
|   return ret; | ||||
| } | ||||
|  | ||||
| auto packet::decode(std::int32_t &val) -> packet::error_type { | ||||
|   const auto ret = decode(&val, sizeof(val)); | ||||
|   if (ret == 0) { | ||||
|     boost::endian::big_to_native_inplace(val); | ||||
|   } | ||||
|   return ret; | ||||
| } | ||||
|  | ||||
| auto packet::decode(std::uint32_t &val) -> packet::error_type { | ||||
|   const auto ret = decode(&val, sizeof(val)); | ||||
|   if (ret == 0) { | ||||
|     boost::endian::big_to_native_inplace(val); | ||||
|   } | ||||
|   return ret; | ||||
| } | ||||
|  | ||||
| auto packet::decode(std::int64_t &val) -> packet::error_type { | ||||
|   const auto ret = decode(&val, sizeof(val)); | ||||
|   if (ret == 0) { | ||||
|     boost::endian::big_to_native_inplace(val); | ||||
|   } | ||||
|   return ret; | ||||
| } | ||||
|  | ||||
| auto packet::decode(std::uint64_t &val) -> packet::error_type { | ||||
|   const auto ret = decode(&val, sizeof(val)); | ||||
|   if (ret == 0) { | ||||
|     boost::endian::big_to_native_inplace(val); | ||||
|   } | ||||
|   return ret; | ||||
| } | ||||
|  | ||||
| auto packet::decode(remote::setattr_x &val) -> packet::error_type { | ||||
|   const auto ret = decode(&val, sizeof(val)); | ||||
|   if (ret == 0) { | ||||
|     boost::endian::big_to_native_inplace(val.acctime); | ||||
|     boost::endian::big_to_native_inplace(val.bkuptime); | ||||
|     boost::endian::big_to_native_inplace(val.chgtime); | ||||
|     boost::endian::big_to_native_inplace(val.crtime); | ||||
|     boost::endian::big_to_native_inplace(val.flags); | ||||
|     boost::endian::big_to_native_inplace(val.gid); | ||||
|     boost::endian::big_to_native_inplace(val.mode); | ||||
|     boost::endian::big_to_native_inplace(val.modtime); | ||||
|     boost::endian::big_to_native_inplace(val.size); | ||||
|     boost::endian::big_to_native_inplace(val.uid); | ||||
|     boost::endian::big_to_native_inplace(val.valid); | ||||
|   } | ||||
|  | ||||
|   return ret; | ||||
| } | ||||
|  | ||||
| auto packet::decode(remote::stat &val) -> packet::error_type { | ||||
|   const auto ret = decode(&val, sizeof(val)); | ||||
|   if (ret == 0) { | ||||
|     boost::endian::big_to_native_inplace(val.st_mode); | ||||
|     boost::endian::big_to_native_inplace(val.st_nlink); | ||||
|     boost::endian::big_to_native_inplace(val.st_uid); | ||||
|     boost::endian::big_to_native_inplace(val.st_gid); | ||||
|     boost::endian::big_to_native_inplace(val.st_atimespec); | ||||
|     boost::endian::big_to_native_inplace(val.st_mtimespec); | ||||
|     boost::endian::big_to_native_inplace(val.st_ctimespec); | ||||
|     boost::endian::big_to_native_inplace(val.st_birthtimespec); | ||||
|     boost::endian::big_to_native_inplace(val.st_size); | ||||
|     boost::endian::big_to_native_inplace(val.st_blocks); | ||||
|     boost::endian::big_to_native_inplace(val.st_blksize); | ||||
|     boost::endian::big_to_native_inplace(val.st_flags); | ||||
|   } | ||||
|  | ||||
|   return ret; | ||||
| } | ||||
|  | ||||
| auto packet::decode(remote::statfs &val) -> packet::error_type { | ||||
|   const auto ret = decode(&val, sizeof(val)); | ||||
|   if (ret == 0) { | ||||
|     boost::endian::big_to_native_inplace(val.f_bavail); | ||||
|     boost::endian::big_to_native_inplace(val.f_bfree); | ||||
|     boost::endian::big_to_native_inplace(val.f_blocks); | ||||
|     boost::endian::big_to_native_inplace(val.f_favail); | ||||
|     boost::endian::big_to_native_inplace(val.f_ffree); | ||||
|     boost::endian::big_to_native_inplace(val.f_files); | ||||
|   } | ||||
|   return ret; | ||||
| } | ||||
|  | ||||
| auto packet::decode(remote::statfs_x &val) -> packet::error_type { | ||||
|   auto ret = decode(*dynamic_cast<remote::statfs *>(&val)); | ||||
|   if (ret == 0) { | ||||
|     ret = decode(&val.f_mntfromname[0U], sizeof(val.f_mntfromname)); | ||||
|   } | ||||
|   return ret; | ||||
| } | ||||
|  | ||||
| auto packet::decode(remote::file_info &val) -> packet::error_type { | ||||
|   const auto ret = decode(&val, sizeof(val)); | ||||
|   if (ret == 0) { | ||||
|     boost::endian::big_to_native_inplace(val.AllocationSize); | ||||
|     boost::endian::big_to_native_inplace(val.ChangeTime); | ||||
|     boost::endian::big_to_native_inplace(val.CreationTime); | ||||
|     boost::endian::big_to_native_inplace(val.EaSize); | ||||
|     boost::endian::big_to_native_inplace(val.FileAttributes); | ||||
|     boost::endian::big_to_native_inplace(val.FileSize); | ||||
|     boost::endian::big_to_native_inplace(val.HardLinks); | ||||
|     boost::endian::big_to_native_inplace(val.IndexNumber); | ||||
|     boost::endian::big_to_native_inplace(val.LastAccessTime); | ||||
|     boost::endian::big_to_native_inplace(val.LastWriteTime); | ||||
|     boost::endian::big_to_native_inplace(val.ReparseTag); | ||||
|   } | ||||
|  | ||||
|   return ret; | ||||
| } | ||||
|  | ||||
| auto packet::decode_json(packet &response, json &json_data) -> int { | ||||
|   constexpr const auto *function_name = static_cast<const char *>(__FUNCTION__); | ||||
|  | ||||
|   std::string data; | ||||
|   auto ret = response.decode(data); | ||||
|   if (ret == 0) { | ||||
|     try { | ||||
|       json_data = json::parse(data); | ||||
|     } catch (const std::exception &e) { | ||||
|       utils::error::raise_error(function_name, e, | ||||
|                                 "failed to parse json string"); | ||||
|       ret = -EIO; | ||||
|     } | ||||
|   } | ||||
|  | ||||
|   return ret; | ||||
| } | ||||
|  | ||||
| auto packet::decrypt(const std::string &token) -> packet::error_type { | ||||
|   constexpr const auto *function_name = static_cast<const char *>(__FUNCTION__); | ||||
|  | ||||
|   auto ret = utils::from_api_error(api_error::success); | ||||
|   try { | ||||
|     data_buffer result; | ||||
|     if (not utils::encryption::decrypt_data(token, &buffer_[decode_offset_], | ||||
|                                             buffer_.size() - decode_offset_, | ||||
|                                             result)) { | ||||
|       throw std::runtime_error("decryption failed"); | ||||
|     } | ||||
|     buffer_ = std::move(result); | ||||
|     decode_offset_ = 0; | ||||
|   } catch (const std::exception &e) { | ||||
|     utils::error::raise_error(function_name, e, "exception occurred"); | ||||
|     ret = utils::from_api_error(api_error::error); | ||||
|   } | ||||
|  | ||||
|   return ret; | ||||
| } | ||||
|  | ||||
| void packet::encode(const void *buffer, std::size_t size, bool should_reserve) { | ||||
|   if (size != 0U) { | ||||
|     if (should_reserve) { | ||||
|       buffer_.reserve(buffer_.size() + size); | ||||
|     } | ||||
|     const auto *char_buffer = reinterpret_cast<const char *>(buffer); | ||||
|     buffer_.insert(buffer_.end(), char_buffer, char_buffer + size); | ||||
|   } | ||||
| } | ||||
|  | ||||
| void packet::encode(const std::string &str) { | ||||
|   const auto len = strnlen(str.c_str(), str.size()); | ||||
|   buffer_.reserve(len + 1 + buffer_.size()); | ||||
|   encode(str.c_str(), len, false); | ||||
|   buffer_.emplace_back(0); | ||||
| } | ||||
|  | ||||
| void packet::encode(const wchar_t *str) { | ||||
|   encode(utils::string::to_utf8(str == nullptr ? L"" : str)); | ||||
| } | ||||
|  | ||||
| void packet::encode(const std::wstring &str) { | ||||
|   encode(utils::string::to_utf8(str)); | ||||
| } | ||||
|  | ||||
| void packet::encode(std::int8_t val) { | ||||
|   boost::endian::native_to_big_inplace(val); | ||||
|   encode(&val, sizeof(val), true); | ||||
| } | ||||
|  | ||||
| void packet::encode(std::uint8_t val) { | ||||
|   boost::endian::native_to_big_inplace(val); | ||||
|   encode(&val, sizeof(val), true); | ||||
| } | ||||
|  | ||||
| void packet::encode(std::int16_t val) { | ||||
|   boost::endian::native_to_big_inplace(val); | ||||
|   encode(&val, sizeof(val), true); | ||||
| } | ||||
|  | ||||
| void packet::encode(std::uint16_t val) { | ||||
|   boost::endian::native_to_big_inplace(val); | ||||
|   encode(&val, sizeof(val), true); | ||||
| } | ||||
|  | ||||
| void packet::encode(std::int32_t val) { | ||||
|   boost::endian::native_to_big_inplace(val); | ||||
|   encode(&val, sizeof(val), true); | ||||
| } | ||||
|  | ||||
| void packet::encode(std::uint32_t val) { | ||||
|   boost::endian::native_to_big_inplace(val); | ||||
|   encode(&val, sizeof(val), true); | ||||
| } | ||||
|  | ||||
| void packet::encode(std::int64_t val) { | ||||
|   boost::endian::native_to_big_inplace(val); | ||||
|   encode(&val, sizeof(val), true); | ||||
| } | ||||
|  | ||||
| void packet::encode(std::uint64_t val) { | ||||
|   boost::endian::native_to_big_inplace(val); | ||||
|   encode(&val, sizeof(val), true); | ||||
| } | ||||
|  | ||||
| void packet::encode(remote::setattr_x val) { | ||||
|   boost::endian::native_to_big_inplace(val.acctime); | ||||
|   boost::endian::native_to_big_inplace(val.bkuptime); | ||||
|   boost::endian::native_to_big_inplace(val.chgtime); | ||||
|   boost::endian::native_to_big_inplace(val.crtime); | ||||
|   boost::endian::native_to_big_inplace(val.flags); | ||||
|   boost::endian::native_to_big_inplace(val.gid); | ||||
|   boost::endian::native_to_big_inplace(val.mode); | ||||
|   boost::endian::native_to_big_inplace(val.modtime); | ||||
|   boost::endian::native_to_big_inplace(val.size); | ||||
|   boost::endian::native_to_big_inplace(val.uid); | ||||
|   boost::endian::native_to_big_inplace(val.valid); | ||||
|  | ||||
|   encode(&val, sizeof(val), true); | ||||
| } | ||||
|  | ||||
| void packet::encode(remote::stat val) { | ||||
|   boost::endian::native_to_big_inplace(val.st_mode); | ||||
|   boost::endian::native_to_big_inplace(val.st_nlink); | ||||
|   boost::endian::native_to_big_inplace(val.st_uid); | ||||
|   boost::endian::native_to_big_inplace(val.st_gid); | ||||
|   boost::endian::native_to_big_inplace(val.st_atimespec); | ||||
|   boost::endian::native_to_big_inplace(val.st_mtimespec); | ||||
|   boost::endian::native_to_big_inplace(val.st_ctimespec); | ||||
|   boost::endian::native_to_big_inplace(val.st_birthtimespec); | ||||
|   boost::endian::native_to_big_inplace(val.st_size); | ||||
|   boost::endian::native_to_big_inplace(val.st_blocks); | ||||
|   boost::endian::native_to_big_inplace(val.st_blksize); | ||||
|   boost::endian::native_to_big_inplace(val.st_flags); | ||||
|  | ||||
|   encode(&val, sizeof(val), true); | ||||
| } | ||||
|  | ||||
| void packet::encode(remote::statfs val, bool should_reserve) { | ||||
|   boost::endian::native_to_big_inplace(val.f_bavail); | ||||
|   boost::endian::native_to_big_inplace(val.f_bfree); | ||||
|   boost::endian::native_to_big_inplace(val.f_blocks); | ||||
|   boost::endian::native_to_big_inplace(val.f_favail); | ||||
|   boost::endian::native_to_big_inplace(val.f_ffree); | ||||
|   boost::endian::native_to_big_inplace(val.f_files); | ||||
|  | ||||
|   encode(&val, sizeof(remote::statfs), should_reserve); | ||||
| } | ||||
|  | ||||
| void packet::encode(remote::statfs_x val) { | ||||
|   buffer_.reserve(buffer_.size() + sizeof(remote::statfs) + | ||||
|                   sizeof(val.f_mntfromname)); | ||||
|   encode(*dynamic_cast<remote::statfs *>(&val), false); | ||||
|   encode(&val.f_mntfromname[0], sizeof(val.f_mntfromname), false); | ||||
| } | ||||
|  | ||||
| void packet::encode(remote::file_info val) { | ||||
|   boost::endian::native_to_big_inplace(val.FileAttributes); | ||||
|   boost::endian::native_to_big_inplace(val.ReparseTag); | ||||
|   boost::endian::native_to_big_inplace(val.AllocationSize); | ||||
|   boost::endian::native_to_big_inplace(val.FileSize); | ||||
|   boost::endian::native_to_big_inplace(val.CreationTime); | ||||
|   boost::endian::native_to_big_inplace(val.LastAccessTime); | ||||
|   boost::endian::native_to_big_inplace(val.LastWriteTime); | ||||
|   boost::endian::native_to_big_inplace(val.ChangeTime); | ||||
|   boost::endian::native_to_big_inplace(val.IndexNumber); | ||||
|   boost::endian::native_to_big_inplace(val.HardLinks); | ||||
|   boost::endian::native_to_big_inplace(val.EaSize); | ||||
|  | ||||
|   encode(&val, sizeof(val), true); | ||||
| } | ||||
|  | ||||
| void packet::encode_top(const void *buffer, std::size_t size, | ||||
|                         bool should_reserve) { | ||||
|   if (size != 0U) { | ||||
|     if (should_reserve) { | ||||
|       buffer_.reserve(buffer_.size() + size); | ||||
|     } | ||||
|     const auto *char_buffer = reinterpret_cast<const char *>(buffer); | ||||
|     buffer_.insert(buffer_.begin(), char_buffer, char_buffer + size); | ||||
|   } | ||||
| } | ||||
|  | ||||
| void packet::encode_top(const std::string &str) { | ||||
|   const auto len = strnlen(str.c_str(), str.size()); | ||||
|   buffer_.reserve(len + 1U + buffer_.size()); | ||||
|   encode_top(str.c_str(), len, false); | ||||
|   buffer_.insert(buffer_.begin() + static_cast<std::int32_t>(len), 0); | ||||
| } | ||||
|  | ||||
| void packet::encode_top(const std::wstring &str) { | ||||
|   encode_top(utils::string::to_utf8(str)); | ||||
| } | ||||
|  | ||||
| void packet::encode_top(std::int8_t val) { | ||||
|   boost::endian::native_to_big_inplace(val); | ||||
|   encode_top(&val, sizeof(val), true); | ||||
| } | ||||
|  | ||||
| void packet::encode_top(std::uint8_t val) { | ||||
|   boost::endian::native_to_big_inplace(val); | ||||
|   encode_top(&val, sizeof(val), true); | ||||
| } | ||||
|  | ||||
| void packet::encode_top(std::int16_t val) { | ||||
|   boost::endian::native_to_big_inplace(val); | ||||
|   encode_top(&val, sizeof(val), true); | ||||
| } | ||||
|  | ||||
| void packet::encode_top(std::uint16_t val) { | ||||
|   boost::endian::native_to_big_inplace(val); | ||||
|   encode_top(&val, sizeof(val), true); | ||||
| } | ||||
|  | ||||
| void packet::encode_top(std::int32_t val) { | ||||
|   boost::endian::native_to_big_inplace(val); | ||||
|   encode_top(&val, sizeof(val), true); | ||||
| } | ||||
|  | ||||
| void packet::encode_top(std::uint32_t val) { | ||||
|   boost::endian::native_to_big_inplace(val); | ||||
|   encode_top(&val, sizeof(val), true); | ||||
| } | ||||
|  | ||||
| void packet::encode_top(std::int64_t val) { | ||||
|   boost::endian::native_to_big_inplace(val); | ||||
|   encode_top(&val, sizeof(val), true); | ||||
| } | ||||
|  | ||||
| void packet::encode_top(std::uint64_t val) { | ||||
|   boost::endian::native_to_big_inplace(val); | ||||
|   encode_top(&val, sizeof(val), true); | ||||
| } | ||||
|  | ||||
| void packet::encode_top(remote::setattr_x val) { | ||||
|   boost::endian::native_to_big_inplace(val.acctime); | ||||
|   boost::endian::native_to_big_inplace(val.bkuptime); | ||||
|   boost::endian::native_to_big_inplace(val.chgtime); | ||||
|   boost::endian::native_to_big_inplace(val.crtime); | ||||
|   boost::endian::native_to_big_inplace(val.flags); | ||||
|   boost::endian::native_to_big_inplace(val.gid); | ||||
|   boost::endian::native_to_big_inplace(val.mode); | ||||
|   boost::endian::native_to_big_inplace(val.modtime); | ||||
|   boost::endian::native_to_big_inplace(val.size); | ||||
|   boost::endian::native_to_big_inplace(val.uid); | ||||
|   boost::endian::native_to_big_inplace(val.valid); | ||||
|  | ||||
|   encode_top(&val, sizeof(val), true); | ||||
| } | ||||
|  | ||||
| void packet::encode_top(remote::stat val) { | ||||
|   boost::endian::native_to_big_inplace(val.st_mode); | ||||
|   boost::endian::native_to_big_inplace(val.st_nlink); | ||||
|   boost::endian::native_to_big_inplace(val.st_uid); | ||||
|   boost::endian::native_to_big_inplace(val.st_gid); | ||||
|   boost::endian::native_to_big_inplace(val.st_atimespec); | ||||
|   boost::endian::native_to_big_inplace(val.st_mtimespec); | ||||
|   boost::endian::native_to_big_inplace(val.st_ctimespec); | ||||
|   boost::endian::native_to_big_inplace(val.st_birthtimespec); | ||||
|   boost::endian::native_to_big_inplace(val.st_size); | ||||
|   boost::endian::native_to_big_inplace(val.st_blocks); | ||||
|   boost::endian::native_to_big_inplace(val.st_blksize); | ||||
|   boost::endian::native_to_big_inplace(val.st_flags); | ||||
|  | ||||
|   encode_top(&val, sizeof(val), true); | ||||
| } | ||||
|  | ||||
| void packet::encode_top(remote::statfs val, bool should_reserve) { | ||||
|   boost::endian::native_to_big_inplace(val.f_bavail); | ||||
|   boost::endian::native_to_big_inplace(val.f_bfree); | ||||
|   boost::endian::native_to_big_inplace(val.f_blocks); | ||||
|   boost::endian::native_to_big_inplace(val.f_favail); | ||||
|   boost::endian::native_to_big_inplace(val.f_ffree); | ||||
|   boost::endian::native_to_big_inplace(val.f_files); | ||||
|  | ||||
|   encode_top(&val, sizeof(remote::statfs), should_reserve); | ||||
| } | ||||
|  | ||||
| void packet::encode_top(remote::statfs_x val) { | ||||
|   buffer_.reserve(buffer_.size() + sizeof(remote::statfs) + | ||||
|                   sizeof(val.f_mntfromname)); | ||||
|   encode_top(&val.f_mntfromname[0], sizeof(val.f_mntfromname), false); | ||||
|   encode_top(*dynamic_cast<remote::statfs *>(&val), false); | ||||
| } | ||||
|  | ||||
| void packet::encode_top(remote::file_info val) { | ||||
|   boost::endian::native_to_big_inplace(val.FileAttributes); | ||||
|   boost::endian::native_to_big_inplace(val.ReparseTag); | ||||
|   boost::endian::native_to_big_inplace(val.AllocationSize); | ||||
|   boost::endian::native_to_big_inplace(val.FileSize); | ||||
|   boost::endian::native_to_big_inplace(val.CreationTime); | ||||
|   boost::endian::native_to_big_inplace(val.LastAccessTime); | ||||
|   boost::endian::native_to_big_inplace(val.LastWriteTime); | ||||
|   boost::endian::native_to_big_inplace(val.ChangeTime); | ||||
|   boost::endian::native_to_big_inplace(val.IndexNumber); | ||||
|   boost::endian::native_to_big_inplace(val.HardLinks); | ||||
|   boost::endian::native_to_big_inplace(val.EaSize); | ||||
|  | ||||
|   encode_top(&val, sizeof(val), true); | ||||
| } | ||||
|  | ||||
| void packet::encrypt(const std::string &token) { | ||||
|   constexpr const auto *function_name = static_cast<const char *>(__FUNCTION__); | ||||
|  | ||||
|   try { | ||||
|     data_buffer result; | ||||
|     utils::encryption::encrypt_data(token, buffer_, result); | ||||
|     buffer_ = std::move(result); | ||||
|     encode_top(static_cast<std::uint32_t>(buffer_.size())); | ||||
|   } catch (const std::exception &e) { | ||||
|     utils::error::raise_error(function_name, e, "exception occurred"); | ||||
|   } | ||||
| } | ||||
|  | ||||
| void packet::transfer_into(data_buffer &buffer) { | ||||
|   buffer = std::move(buffer_); | ||||
|   buffer_ = data_buffer(); | ||||
|   decode_offset_ = 0; | ||||
| } | ||||
|  | ||||
| auto packet::operator=(const data_buffer &buffer) noexcept -> packet & { | ||||
|   if (&buffer_ != &buffer) { | ||||
|     buffer_ = buffer; | ||||
|     decode_offset_ = 0; | ||||
|   } | ||||
|  | ||||
|   return *this; | ||||
| } | ||||
|  | ||||
| auto packet::operator=(data_buffer &&buffer) noexcept -> packet & { | ||||
|   if (&buffer_ != &buffer) { | ||||
|     buffer_ = std::move(buffer); | ||||
|     decode_offset_ = 0; | ||||
|   } | ||||
|  | ||||
|   return *this; | ||||
| } | ||||
|  | ||||
| auto packet::operator=(const packet &pkt) noexcept -> packet & { | ||||
|   if (this != &pkt) { | ||||
|     buffer_ = pkt.buffer_; | ||||
|     decode_offset_ = pkt.decode_offset_; | ||||
|   } | ||||
|  | ||||
|   return *this; | ||||
| } | ||||
|  | ||||
| auto packet::operator=(packet &&pkt) noexcept -> packet & { | ||||
|   if (this != &pkt) { | ||||
|     buffer_ = std::move(pkt.buffer_); | ||||
|     decode_offset_ = pkt.decode_offset_; | ||||
|   } | ||||
|  | ||||
|   return *this; | ||||
| } | ||||
| } // namespace repertory | ||||
							
								
								
									
										253
									
								
								repertory/librepertory/src/comm/packet/packet_client.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										253
									
								
								repertory/librepertory/src/comm/packet/packet_client.cpp
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,253 @@ | ||||
| /* | ||||
|   Copyright <2018-2024> <scott.e.graves@protonmail.com> | ||||
|  | ||||
|   Permission is hereby granted, free of charge, to any person obtaining a copy | ||||
|   of this software and associated documentation files (the "Software"), to deal | ||||
|   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 "comm/packet/packet_client.hpp" | ||||
|  | ||||
| #include "events/events.hpp" | ||||
| #include "types/repertory.hpp" | ||||
| #include "utils/error_utils.hpp" | ||||
| #include "utils/timeout.hpp" | ||||
|  | ||||
| namespace repertory { | ||||
| // clang-format off | ||||
| E_SIMPLE2(packet_client_timeout, error, true, | ||||
|   std::string, event_name, en, E_STRING, | ||||
|   std::string, message, msg, E_STRING | ||||
| ); | ||||
| // clang-format on | ||||
|  | ||||
| packet_client::packet_client(std::string host_name_or_ip, | ||||
|                              std::uint8_t max_connections, std::uint16_t port, | ||||
|                              std::uint16_t receive_timeout, | ||||
|                              std::uint16_t send_timeout, | ||||
|                              std::string encryption_token) | ||||
|     : host_name_or_ip_(std::move(host_name_or_ip)), | ||||
|       max_connections_(max_connections == 0U ? 20U : max_connections), | ||||
|       port_(port), | ||||
|       receive_timeout_(receive_timeout), | ||||
|       send_timeout_(send_timeout), | ||||
|       encryption_token_(std::move(encryption_token)), | ||||
|       unique_id_(utils::create_uuid_string()) {} | ||||
|  | ||||
| packet_client::~packet_client() { | ||||
|   allow_connections_ = false; | ||||
|   close_all(); | ||||
|   io_context_.stop(); | ||||
| } | ||||
|  | ||||
| void packet_client::close(client &cli) { | ||||
|   try { | ||||
|     boost::system::error_code err; | ||||
|     cli.socket.close(err); | ||||
|   } catch (...) { | ||||
|   } | ||||
| } | ||||
|  | ||||
| void packet_client::close_all() { | ||||
|   unique_mutex_lock clients_lock(clients_mutex_); | ||||
|   for (auto &cli : clients_) { | ||||
|     close(*cli); | ||||
|   } | ||||
|  | ||||
|   clients_.clear(); | ||||
|   unique_id_ = utils::create_uuid_string(); | ||||
| } | ||||
|  | ||||
| void packet_client::connect(client &cli) { | ||||
|   constexpr const auto *function_name = static_cast<const char *>(__FUNCTION__); | ||||
|  | ||||
|   try { | ||||
|     resolve(); | ||||
|     boost::asio::connect(cli.socket, resolve_results_); | ||||
|     cli.socket.set_option(boost::asio::ip::tcp::no_delay(true)); | ||||
|     cli.socket.set_option(boost::asio::socket_base::linger(false, 0)); | ||||
|  | ||||
|     packet response; | ||||
|     const auto res = read_packet(cli, response); | ||||
|     if (res != 0) { | ||||
|       throw std::runtime_error(std::to_string(res)); | ||||
|     } | ||||
|   } catch (const std::exception &e) { | ||||
|     utils::error::raise_error(function_name, e, "connection handshake failed"); | ||||
|   } | ||||
| } | ||||
|  | ||||
| auto packet_client::get_client() -> std::shared_ptr<packet_client::client> { | ||||
|   std::shared_ptr<client> ret; | ||||
|  | ||||
|   unique_mutex_lock clients_lock(clients_mutex_); | ||||
|   if (allow_connections_) { | ||||
|     if (clients_.empty()) { | ||||
|       clients_lock.unlock(); | ||||
|       ret = std::make_shared<client>(io_context_); | ||||
|       connect(*ret); | ||||
|     } else { | ||||
|       ret = clients_[0U]; | ||||
|       utils::remove_element_from(clients_, ret); | ||||
|       clients_lock.unlock(); | ||||
|     } | ||||
|   } | ||||
|  | ||||
|   return ret; | ||||
| } | ||||
|  | ||||
| void packet_client::put_client(std::shared_ptr<client> &cli) { | ||||
|   mutex_lock clientsLock(clients_mutex_); | ||||
|   if (clients_.size() < max_connections_) { | ||||
|     clients_.emplace_back(cli); | ||||
|   } | ||||
| } | ||||
|  | ||||
| auto packet_client::read_packet(client &cli, packet &response) | ||||
|     -> packet::error_type { | ||||
|   data_buffer buffer(sizeof(std::uint32_t)); | ||||
|   const auto read_buffer = [&]() { | ||||
|     std::uint32_t offset{}; | ||||
|     while (offset < buffer.size()) { | ||||
|       const auto bytes_read = boost::asio::read( | ||||
|           cli.socket, | ||||
|           boost::asio::buffer(&buffer[offset], buffer.size() - offset)); | ||||
|       if (bytes_read <= 0) { | ||||
|         throw std::runtime_error("read failed|" + std::to_string(bytes_read)); | ||||
|       } | ||||
|       offset += static_cast<std::uint32_t>(bytes_read); | ||||
|     } | ||||
|   }; | ||||
|   read_buffer(); | ||||
|  | ||||
|   const auto size = boost::endian::big_to_native( | ||||
|       *reinterpret_cast<std::uint32_t *>(buffer.data())); | ||||
|   buffer.resize(size); | ||||
|  | ||||
|   read_buffer(); | ||||
|   response = std::move(buffer); | ||||
|  | ||||
|   auto ret = response.decrypt(encryption_token_); | ||||
|   if (ret == 0) { | ||||
|     ret = response.decode(cli.nonce); | ||||
|   } | ||||
|  | ||||
|   return ret; | ||||
| } | ||||
|  | ||||
| void packet_client::resolve() { | ||||
|   if (resolve_results_.empty()) { | ||||
|     resolve_results_ = tcp::resolver(io_context_) | ||||
|                            .resolve({host_name_or_ip_, std::to_string(port_)}); | ||||
|   } | ||||
| } | ||||
|  | ||||
| auto packet_client::send(const std::string &method, | ||||
|                          std::uint32_t &service_flags) -> packet::error_type { | ||||
|   packet request; | ||||
|   return send(method, request, service_flags); | ||||
| } | ||||
|  | ||||
| auto packet_client::send(const std::string &method, packet &request, | ||||
|                          std::uint32_t &service_flags) -> packet::error_type { | ||||
|   packet response; | ||||
|   return send(method, request, response, service_flags); | ||||
| } | ||||
|  | ||||
| auto packet_client::send(const std::string &method, packet &request, | ||||
|                          packet &response, std::uint32_t &service_flags) | ||||
|     -> packet::error_type { | ||||
|   constexpr const auto *function_name = static_cast<const char *>(__FUNCTION__); | ||||
|  | ||||
|   auto success = false; | ||||
|   packet::error_type ret = utils::from_api_error(api_error::error); | ||||
|   request.encode_top(method); | ||||
|   request.encode_top(utils::get_thread_id()); | ||||
|   request.encode_top(unique_id_); | ||||
|   request.encode_top(PACKET_SERVICE_FLAGS); | ||||
|   request.encode_top(get_repertory_version()); | ||||
|  | ||||
|   static const std::uint8_t max_attempts{5U}; | ||||
|   for (std::uint8_t i = 1U; | ||||
|        allow_connections_ && not success && (i <= max_attempts); i++) { | ||||
|     auto current_client = get_client(); | ||||
|     if (current_client) { | ||||
|       try { | ||||
|         request.encode_top(current_client->nonce); | ||||
|         request.encrypt(encryption_token_); | ||||
|  | ||||
|         timeout request_timeout( | ||||
|             [method, current_client]() { | ||||
|               event_system::instance().raise<packet_client_timeout>("request", | ||||
|                                                                     method); | ||||
|               packet_client::close(*current_client); | ||||
|             }, | ||||
|             std::chrono::seconds(send_timeout_)); | ||||
|  | ||||
|         std::uint32_t offset{}; | ||||
|         while (offset < request.get_size()) { | ||||
|           const auto bytes_written = boost::asio::write( | ||||
|               current_client->socket, | ||||
|               boost::asio::buffer(&request[offset], | ||||
|                                   request.get_size() - offset)); | ||||
|           if (bytes_written <= 0) { | ||||
|             throw std::runtime_error("write failed|" + | ||||
|                                      std::to_string(bytes_written)); | ||||
|           } | ||||
|           offset += static_cast<std::uint32_t>(bytes_written); | ||||
|         } | ||||
|         request_timeout.disable(); | ||||
|  | ||||
|         timeout response_timeout( | ||||
|             [method, current_client]() { | ||||
|               event_system::instance().raise<packet_client_timeout>("response", | ||||
|                                                                     method); | ||||
|               packet_client::close(*current_client); | ||||
|             }, | ||||
|             std::chrono::seconds(receive_timeout_)); | ||||
|  | ||||
|         ret = read_packet(*current_client, response); | ||||
|         response_timeout.disable(); | ||||
|         if (ret == 0) { | ||||
|           ret = response.decode(service_flags); | ||||
|           if (ret == 0) { | ||||
|             packet::error_type res{}; | ||||
|             ret = response.decode(res); | ||||
|             if (ret == 0) { | ||||
|               ret = res; | ||||
|               success = true; | ||||
|               put_client(current_client); | ||||
|             } | ||||
|           } | ||||
|         } | ||||
|       } catch (const std::exception &e) { | ||||
|         utils::error::raise_error(function_name, e, "send failed"); | ||||
|         close_all(); | ||||
|         if (allow_connections_ && (i < max_attempts)) { | ||||
|           std::this_thread::sleep_for(1s); | ||||
|         } | ||||
|       } | ||||
|     } | ||||
|  | ||||
|     if (not allow_connections_) { | ||||
|       ret = utils::from_api_error(api_error::error); | ||||
|       success = true; | ||||
|     } | ||||
|   } | ||||
|  | ||||
|   return CONVERT_STATUS_NOT_IMPLEMENTED(ret); | ||||
| } | ||||
| } // namespace repertory | ||||
							
								
								
									
										261
									
								
								repertory/librepertory/src/comm/packet/packet_server.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										261
									
								
								repertory/librepertory/src/comm/packet/packet_server.cpp
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,261 @@ | ||||
| /* | ||||
|   Copyright <2018-2024> <scott.e.graves@protonmail.com> | ||||
|  | ||||
|   Permission is hereby granted, free of charge, to any person obtaining a copy | ||||
|   of this software and associated documentation files (the "Software"), to deal | ||||
|   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 "comm/packet/packet_server.hpp" | ||||
|  | ||||
| #include "comm/packet/packet.hpp" | ||||
| #include "events/event_system.hpp" | ||||
| #include "events/events.hpp" | ||||
| #include "types/repertory.hpp" | ||||
| #include "utils/error_utils.hpp" | ||||
| #include "utils/string_utils.hpp" | ||||
| #include "utils/utils.hpp" | ||||
|  | ||||
| namespace repertory { | ||||
| using std::thread; | ||||
|  | ||||
| packet_server::packet_server(std::uint16_t port, std::string token, | ||||
|                              std::uint8_t pool_size, closed_callback closed, | ||||
|                              message_handler_callback message_handler) | ||||
|     : encryption_token_(std::move(token)), | ||||
|       closed_(std::move(closed)), | ||||
|       message_handler_(std::move(message_handler)) { | ||||
|   initialize(port, pool_size); | ||||
|   event_system::instance().raise<service_started>("packet_server"); | ||||
| } | ||||
|  | ||||
| packet_server::~packet_server() { | ||||
|   event_system::instance().raise<service_shutdown_begin>("packet_server"); | ||||
|   std::thread([this]() { | ||||
|     for (std::size_t i = 0U; i < service_threads_.size(); i++) { | ||||
|       io_context_.stop(); | ||||
|     } | ||||
|   }).detach(); | ||||
|  | ||||
|   server_thread_->join(); | ||||
|   server_thread_.reset(); | ||||
|   event_system::instance().raise<service_shutdown_end>("packet_server"); | ||||
| } | ||||
|  | ||||
| void packet_server::add_client(connection &conn, const std::string &client_id) { | ||||
|   conn.client_id = client_id; | ||||
|  | ||||
|   recur_mutex_lock connection_lock(connection_mutex_); | ||||
|   if (connection_lookup_.find(client_id) == connection_lookup_.end()) { | ||||
|     connection_lookup_[client_id] = 1U; | ||||
|   } else { | ||||
|     connection_lookup_.at(client_id)++; | ||||
|   } | ||||
| } | ||||
|  | ||||
| void packet_server::initialize(const uint16_t &port, uint8_t pool_size) { | ||||
|   constexpr const auto *function_name = static_cast<const char *>(__FUNCTION__); | ||||
|  | ||||
|   pool_size = std::max(uint8_t(1U), pool_size); | ||||
|   server_thread_ = std::make_unique<std::thread>([this, port, pool_size]() { | ||||
|     tcp::acceptor acceptor(io_context_); | ||||
|     try { | ||||
|       const auto endpoint = tcp::endpoint(tcp::v4(), port); | ||||
|       acceptor.open(endpoint.protocol()); | ||||
|       acceptor.set_option(socket_base::reuse_address(true)); | ||||
|       acceptor.bind(endpoint); | ||||
|       acceptor.listen(); | ||||
|     } catch (const std::exception &e) { | ||||
|       repertory::utils::error::raise_error(function_name, e, | ||||
|                                            "exception occurred"); | ||||
|     } | ||||
|     listen_for_connection(acceptor); | ||||
|  | ||||
|     for (std::uint8_t i = 0U; i < pool_size; i++) { | ||||
|       service_threads_.emplace_back([this]() { io_context_.run(); }); | ||||
|     } | ||||
|  | ||||
|     for (auto &thread : service_threads_) { | ||||
|       thread.join(); | ||||
|     } | ||||
|   }); | ||||
| } | ||||
|  | ||||
| void packet_server::listen_for_connection(tcp::acceptor &acceptor) { | ||||
|   auto conn = | ||||
|       std::make_shared<packet_server::connection>(io_context_, acceptor); | ||||
|   acceptor.async_accept(conn->socket, [this, conn](auto &&err) { | ||||
|     on_accept(conn, std::forward<decltype(err)>(err)); | ||||
|   }); | ||||
| } | ||||
|  | ||||
| void packet_server::on_accept(std::shared_ptr<connection> conn, | ||||
|                               boost::system::error_code err) { | ||||
|   constexpr const auto *function_name = static_cast<const char *>(__FUNCTION__); | ||||
|  | ||||
|   listen_for_connection(conn->acceptor); | ||||
|   if (err) { | ||||
|     utils::error::raise_error(function_name, err.message()); | ||||
|     std::this_thread::sleep_for(1s); | ||||
|   } else { | ||||
|     conn->socket.set_option(boost::asio::ip::tcp::no_delay(true)); | ||||
|     conn->socket.set_option(boost::asio::socket_base::linger(false, 0)); | ||||
|  | ||||
|     conn->generate_nonce(); | ||||
|  | ||||
|     packet response; | ||||
|     send_response(conn, 0, response); | ||||
|   } | ||||
| } | ||||
|  | ||||
| void packet_server::read_header(std::shared_ptr<connection> conn) { | ||||
|   constexpr const auto *function_name = static_cast<const char *>(__FUNCTION__); | ||||
|  | ||||
|   conn->buffer.resize(sizeof(std::uint32_t)); | ||||
|   boost::asio::async_read( | ||||
|       conn->socket, | ||||
|       boost::asio::buffer(conn->buffer.data(), conn->buffer.size()), | ||||
|       [this, conn](boost::system::error_code err, std::size_t) { | ||||
|         if (err) { | ||||
|           remove_client(*conn); | ||||
|           repertory::utils::error::raise_error(function_name, err.message()); | ||||
|         } else { | ||||
|           auto to_read = | ||||
|               *reinterpret_cast<std::uint32_t *>(conn->buffer.data()); | ||||
|           boost::endian::big_to_native_inplace(to_read); | ||||
|           read_packet(conn, to_read); | ||||
|         } | ||||
|       }); | ||||
| } | ||||
|  | ||||
| void packet_server::read_packet(std::shared_ptr<connection> conn, | ||||
|                                 std::uint32_t data_size) { | ||||
|   constexpr const auto *function_name = static_cast<const char *>(__FUNCTION__); | ||||
|  | ||||
|   try { | ||||
|     const auto read_buffer = [&]() { | ||||
|       std::uint32_t offset{}; | ||||
|       while (offset < conn->buffer.size()) { | ||||
|         const auto bytes_read = boost::asio::read( | ||||
|             conn->socket, boost::asio::buffer(&conn->buffer[offset], | ||||
|                                               conn->buffer.size() - offset)); | ||||
|         if (bytes_read <= 0) { | ||||
|           throw std::runtime_error("read failed|" + std::to_string(bytes_read)); | ||||
|         } | ||||
|         offset += static_cast<std::uint32_t>(bytes_read); | ||||
|       } | ||||
|     }; | ||||
|  | ||||
|     auto should_send_response = true; | ||||
|     auto response = std::make_shared<packet>(); | ||||
|     conn->buffer.resize(data_size); | ||||
|     read_buffer(); | ||||
|  | ||||
|     packet::error_type ret{}; | ||||
|     auto request = std::make_shared<packet>(conn->buffer); | ||||
|     if (request->decrypt(encryption_token_) == 0) { | ||||
|       std::string nonce; | ||||
|       ret = request->decode(nonce); | ||||
|       if (ret == 0) { | ||||
|         if (nonce != conn->nonce) { | ||||
|           throw std::runtime_error("invalid nonce"); | ||||
|         } | ||||
|         conn->generate_nonce(); | ||||
|  | ||||
|         std::string version; | ||||
|         ret = request->decode(version); | ||||
|         if (ret == 0) { | ||||
|           if (utils::compare_version_strings( | ||||
|                   version, REPERTORY_MIN_REMOTE_VERSION) >= 0) { | ||||
|             std::uint32_t service_flags{}; | ||||
|             DECODE_OR_IGNORE(request, service_flags); | ||||
|  | ||||
|             std::string client_id; | ||||
|             DECODE_OR_IGNORE(request, client_id); | ||||
|  | ||||
|             std::uint64_t thread_id{}; | ||||
|             DECODE_OR_IGNORE(request, thread_id); | ||||
|  | ||||
|             std::string method; | ||||
|             DECODE_OR_IGNORE(request, method); | ||||
|  | ||||
|             if (ret == 0) { | ||||
|               if (conn->client_id.empty()) { | ||||
|                 add_client(*conn, client_id); | ||||
|               } | ||||
|  | ||||
|               should_send_response = false; | ||||
|               message_handler_(service_flags, client_id, thread_id, method, | ||||
|                                request.get(), *response, | ||||
|                                [this, conn, request, | ||||
|                                 response](const packet::error_type &result) { | ||||
|                                  this->send_response(conn, result, *response); | ||||
|                                }); | ||||
|             } | ||||
|           } else { | ||||
|             ret = utils::from_api_error(api_error::incompatible_version); | ||||
|           } | ||||
|         } else { | ||||
|           ret = utils::from_api_error(api_error::invalid_version); | ||||
|         } | ||||
|       } else { | ||||
|         throw std::runtime_error("invalid nonce"); | ||||
|       } | ||||
|     } else { | ||||
|       throw std::runtime_error("decryption failed"); | ||||
|     } | ||||
|     if (should_send_response) { | ||||
|       send_response(conn, ret, *response); | ||||
|     } | ||||
|   } catch (const std::exception &e) { | ||||
|     remove_client(*conn); | ||||
|     utils::error::raise_error(function_name, e, "exception occurred"); | ||||
|   } | ||||
| } | ||||
|  | ||||
| void packet_server::remove_client(connection &conn) { | ||||
|   if (not conn.client_id.empty()) { | ||||
|     recur_mutex_lock connection_lock(connection_mutex_); | ||||
|     if (--connection_lookup_[conn.client_id] == 0U) { | ||||
|       connection_lookup_.erase(conn.client_id); | ||||
|       closed_(conn.client_id); | ||||
|     } | ||||
|   } | ||||
| } | ||||
|  | ||||
| void packet_server::send_response(std::shared_ptr<connection> conn, | ||||
|                                   const packet::error_type &result, | ||||
|                                   packet &response) { | ||||
|   constexpr const auto *function_name = static_cast<const char *>(__FUNCTION__); | ||||
|  | ||||
|   response.encode_top(result); | ||||
|   response.encode_top(PACKET_SERVICE_FLAGS); | ||||
|   response.encode_top(conn->nonce); | ||||
|   response.encrypt(encryption_token_); | ||||
|   response.transfer_into(conn->buffer); | ||||
|  | ||||
|   boost::asio::async_write( | ||||
|       conn->socket, boost::asio::buffer(conn->buffer), | ||||
|       [this, conn](boost::system::error_code err, std::size_t /*length*/) { | ||||
|         if (err) { | ||||
|           remove_client(*conn); | ||||
|           utils::error::raise_error(function_name, err.message()); | ||||
|         } else { | ||||
|           read_header(conn); | ||||
|         } | ||||
|       }); | ||||
| } | ||||
| } // namespace repertory | ||||
							
								
								
									
										35
									
								
								repertory/librepertory/src/common.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										35
									
								
								repertory/librepertory/src/common.cpp
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,35 @@ | ||||
| /* | ||||
|   Copyright <2018-2024> <scott.e.graves@protonmail.com> | ||||
|  | ||||
|   Permission is hereby granted, free of charge, to any person obtaining a copy | ||||
|   of this software and associated documentation files (the "Software"), to deal | ||||
|   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 "types/repertory.hpp" | ||||
| #include "utils/utils.hpp" | ||||
|  | ||||
| namespace repertory { | ||||
| auto get_repertory_git_revision() -> const std::string & { | ||||
|   static const std::string git_revision = ""; | ||||
|   return git_revision; | ||||
| } | ||||
|  | ||||
| auto get_repertory_version() -> const std::string & { | ||||
|   static const std::string version = "2.0.2-rc"; | ||||
|   return version; | ||||
| } | ||||
| } // namespace repertory | ||||
							
								
								
									
										35
									
								
								repertory/librepertory/src/common.cpp.in
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										35
									
								
								repertory/librepertory/src/common.cpp.in
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,35 @@ | ||||
| /* | ||||
|   Copyright <2018-2024> <scott.e.graves@protonmail.com> | ||||
|  | ||||
|   Permission is hereby granted, free of charge, to any person obtaining a copy | ||||
|   of this software and associated documentation files (the "Software"), to deal | ||||
|   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 "types/repertory.hpp" | ||||
| #include "utils/utils.hpp" | ||||
|  | ||||
| namespace repertory { | ||||
| auto get_repertory_git_revision() -> const std::string & { | ||||
|   static const std::string git_revision = "@REPERTORY_GIT_REV@"; | ||||
|   return git_revision; | ||||
| } | ||||
|  | ||||
| auto get_repertory_version() -> const std::string & { | ||||
|   static const std::string version = "@REPERTORY_VERSION@"; | ||||
|   return version; | ||||
| } | ||||
| } // namespace repertory | ||||
							
								
								
									
										98
									
								
								repertory/librepertory/src/database/db_insert.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										98
									
								
								repertory/librepertory/src/database/db_insert.cpp
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,98 @@ | ||||
| /* | ||||
|   Copyright <2018-2024> <scott.e.graves@protonmail.com> | ||||
|  | ||||
|   Permission is hereby granted, free of charge, to any person obtaining a copy | ||||
|   of this software and associated documentation files (the "Software"), to deal | ||||
|   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 "database/db_insert.hpp" | ||||
|  | ||||
| namespace repertory::db { | ||||
| auto db_insert::column_value(std::string column_name, db_types_t value) | ||||
|     -> db_insert & { | ||||
|   context_->values[column_name] = value; | ||||
|   return *this; | ||||
| } | ||||
|  | ||||
| auto db_insert::dump() const -> std::string { | ||||
|   std::stringstream query; | ||||
|   query << "INSERT "; | ||||
|   if (context_->or_replace) { | ||||
|     query << "OR REPLACE "; | ||||
|   } | ||||
|   query << "INTO \"" << context_->table_name << "\" ("; | ||||
|  | ||||
|   for (std::int32_t idx = 0; | ||||
|        idx < static_cast<std::int32_t>(context_->values.size()); idx++) { | ||||
|     if (idx > 0) { | ||||
|       query << ", "; | ||||
|     } | ||||
|     query << '"' << std::next(context_->values.begin(), idx)->first << '"'; | ||||
|   } | ||||
|  | ||||
|   query << ") VALUES ("; | ||||
|   for (std::int32_t idx = 0; | ||||
|        idx < static_cast<std::int32_t>(context_->values.size()); idx++) { | ||||
|     if (idx > 0) { | ||||
|       query << ", "; | ||||
|     } | ||||
|     query << "?" << (idx + 1); | ||||
|   } | ||||
|   query << ");"; | ||||
|  | ||||
|   return query.str(); | ||||
| } | ||||
|  | ||||
| auto db_insert::go() const -> db_result<context> { | ||||
|   constexpr const auto *function_name = static_cast<const char *>(__FUNCTION__); | ||||
|  | ||||
|   sqlite3_stmt *stmt_ptr{nullptr}; | ||||
|   auto query_str = dump(); | ||||
|   auto res = sqlite3_prepare_v2(&context_->db3, query_str.c_str(), -1, | ||||
|                                 &stmt_ptr, nullptr); | ||||
|   if (res != SQLITE_OK) { | ||||
|     utils::error::raise_error(function_name, "failed to prepare|" + | ||||
|                                                  std::to_string(res) + '|' + | ||||
|                                                  sqlite3_errstr(res)); | ||||
|     return {context_, res}; | ||||
|   } | ||||
|   context_->stmt.reset(stmt_ptr); | ||||
|  | ||||
|   for (std::int32_t idx = 0; | ||||
|        idx < static_cast<std::int32_t>(context_->values.size()); idx++) { | ||||
|     res = std::visit( | ||||
|         overloaded{ | ||||
|             [this, &idx](std::int64_t data) -> std::int32_t { | ||||
|               return sqlite3_bind_int64(context_->stmt.get(), idx + 1, data); | ||||
|             }, | ||||
|             [this, &idx](const std::string &data) -> std::int32_t { | ||||
|               return sqlite3_bind_text(context_->stmt.get(), idx + 1, | ||||
|                                        data.c_str(), -1, nullptr); | ||||
|             }, | ||||
|         }, | ||||
|         std::next(context_->values.begin(), idx)->second); | ||||
|     if (res != SQLITE_OK) { | ||||
|       utils::error::raise_error(function_name, "failed to bind|" + | ||||
|                                                    std::to_string(res) + '|' + | ||||
|                                                    sqlite3_errstr(res)); | ||||
|       return {context_, res}; | ||||
|     } | ||||
|   } | ||||
|  | ||||
|   return {context_, res}; | ||||
| } | ||||
| } // namespace repertory::db | ||||
							
								
								
									
										175
									
								
								repertory/librepertory/src/database/db_select.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										175
									
								
								repertory/librepertory/src/database/db_select.cpp
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,175 @@ | ||||
| /* | ||||
|   Copyright <2018-2024> <scott.e.graves@protonmail.com> | ||||
|  | ||||
|   Permission is hereby granted, free of charge, to any person obtaining a copy | ||||
|   of this software and associated documentation files (the "Software"), to deal | ||||
|   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 "database/db_select.hpp" | ||||
|  | ||||
| namespace repertory::db { | ||||
|  | ||||
| auto db_select::column(std::string column_name) -> db_select & { | ||||
|   if (context_->delete_query) { | ||||
|     throw std::runtime_error("columns may not be specified for delete"); | ||||
|   } | ||||
|  | ||||
|   context_->columns.push_back(column_name); | ||||
|   return *this; | ||||
| } | ||||
|  | ||||
| auto db_select::count(std::string column_name, std::string as_column_name) | ||||
|     -> db_select & { | ||||
|   context_->count_columns[column_name] = as_column_name; | ||||
|   return *this; | ||||
| } | ||||
|  | ||||
| auto db_select::delete_query() -> db_select & { | ||||
|   if (not context_->columns.empty()) { | ||||
|     throw std::runtime_error("columns must be empty for delete"); | ||||
|   } | ||||
|  | ||||
|   context_->delete_query = true; | ||||
|   return *this; | ||||
| } | ||||
|  | ||||
| auto db_select::dump() const -> std::string { | ||||
|   std::stringstream query; | ||||
|   query << (context_->delete_query ? "DELETE " : "SELECT "); | ||||
|   if (not context_->delete_query) { | ||||
|     bool has_column{false}; | ||||
|     if (context_->columns.empty()) { | ||||
|       if (context_->count_columns.empty()) { | ||||
|         query << "*"; | ||||
|         has_column = true; | ||||
|       } | ||||
|     } else { | ||||
|       has_column = not context_->columns.empty(); | ||||
|       for (std::size_t idx = 0U; idx < context_->columns.size(); idx++) { | ||||
|         if (idx > 0U) { | ||||
|           query << ", "; | ||||
|         } | ||||
|         query << context_->columns.at(idx); | ||||
|       } | ||||
|     } | ||||
|  | ||||
|     for (std::int32_t idx = 0U; | ||||
|          idx < static_cast<std::int32_t>(context_->count_columns.size()); | ||||
|          idx++) { | ||||
|       if (has_column || idx > 0) { | ||||
|         query << ", "; | ||||
|       } | ||||
|       query << "COUNT(\""; | ||||
|       auto &count_column = *std::next(context_->count_columns.begin(), idx); | ||||
|       query << count_column.first << "\") AS \"" << count_column.second << '"'; | ||||
|     } | ||||
|   } | ||||
|   query << " FROM \"" << context_->table_name << "\""; | ||||
|  | ||||
|   if (not context_->ands.empty()) { | ||||
|     query << " WHERE ("; | ||||
|     for (std::int32_t idx = 0; | ||||
|          idx < static_cast<std::int32_t>(context_->ands.size()); idx++) { | ||||
|       if (idx > 0) { | ||||
|         query << " AND "; | ||||
|       } | ||||
|  | ||||
|       auto &item = context_->ands.at(static_cast<std::size_t>(idx)); | ||||
|       query << '"' << item.column_name << '"' << item.op_type << "?" | ||||
|             << (idx + 1); | ||||
|     } | ||||
|     query << ")"; | ||||
|   } | ||||
|  | ||||
|   if (not context_->delete_query) { | ||||
|     if (context_->order_by.has_value()) { | ||||
|       query << " ORDER BY \"" << context_->order_by.value().first << "\" "; | ||||
|       query << (context_->order_by.value().second ? "ASC" : "DESC"); | ||||
|     } | ||||
|  | ||||
|     if (context_->limit.has_value()) { | ||||
|       query << " LIMIT " << context_->limit.value(); | ||||
|     } | ||||
|   } | ||||
|  | ||||
|   query << ';'; | ||||
|  | ||||
|   return query.str(); | ||||
| } | ||||
|  | ||||
| auto db_select::go() const -> db_result<context> { | ||||
|   constexpr const auto *function_name = static_cast<const char *>(__FUNCTION__); | ||||
|  | ||||
|   sqlite3_stmt *stmt_ptr{nullptr}; | ||||
|   auto query_str = dump(); | ||||
|   auto res = sqlite3_prepare_v2(&context_->db3, query_str.c_str(), -1, | ||||
|                                 &stmt_ptr, nullptr); | ||||
|   if (res != SQLITE_OK) { | ||||
|     utils::error::raise_error(function_name, | ||||
|                               "failed to prepare|" + std::to_string(res) + '|' + | ||||
|                                   sqlite3_errstr(res) + '|' + query_str); | ||||
|     return {context_, res}; | ||||
|   } | ||||
|   context_->stmt.reset(stmt_ptr); | ||||
|  | ||||
|   for (std::int32_t idx = 0; | ||||
|        idx < static_cast<std::int32_t>(context_->ands.size()); idx++) { | ||||
|     res = std::visit( | ||||
|         overloaded{ | ||||
|             [this, &idx](std::int64_t data) -> std::int32_t { | ||||
|               return sqlite3_bind_int64(context_->stmt.get(), idx + 1, data); | ||||
|             }, | ||||
|             [this, &idx](const std::string &data) -> std::int32_t { | ||||
|               return sqlite3_bind_text(context_->stmt.get(), idx + 1, | ||||
|                                        data.c_str(), -1, nullptr); | ||||
|             }, | ||||
|         }, | ||||
|         context_->ands.at(static_cast<std::size_t>(idx)).value); | ||||
|     if (res != SQLITE_OK) { | ||||
|       utils::error::raise_error(function_name, | ||||
|                                 "failed to bind|" + std::to_string(res) + '|' + | ||||
|                                     sqlite3_errstr(res) + '|' + query_str); | ||||
|       return {context_, res}; | ||||
|     } | ||||
|   } | ||||
|  | ||||
|   return {context_, res}; | ||||
| } | ||||
|  | ||||
| auto db_select::limit(std::int32_t value) -> db_select & { | ||||
|   if (context_->delete_query) { | ||||
|     throw std::runtime_error("limit may not be specified for delete"); | ||||
|   } | ||||
|  | ||||
|   context_->limit = value; | ||||
|   return *this; | ||||
| } | ||||
|  | ||||
| auto db_select::order_by(std::string column_name, bool ascending) | ||||
|     -> db_select & { | ||||
|   if (context_->delete_query) { | ||||
|     throw std::runtime_error("order_by may not be specified for delete"); | ||||
|   } | ||||
|  | ||||
|   context_->order_by = {column_name, ascending}; | ||||
|   return *this; | ||||
| } | ||||
|  | ||||
| auto db_select::where(std::string column_name) const -> db_where { | ||||
|   return db_where{context_, column_name}; | ||||
| } | ||||
| } // namespace repertory::db | ||||
Some files were not shown because too many files have changed in this diff Show More
		Reference in New Issue
	
	Block a user