new_build_system (#18)
All checks were successful
BlockStorage/repertory/pipeline/head This commit looks good
All checks were successful
BlockStorage/repertory/pipeline/head This commit looks good
Reviewed-on: #18
This commit is contained in:
@@ -45,9 +45,6 @@ public:
|
||||
[[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;
|
||||
|
||||
|
||||
@@ -26,8 +26,7 @@
|
||||
#include "comm/i_http_comm.hpp"
|
||||
#include "events/event_system.hpp"
|
||||
#include "events/events.hpp"
|
||||
#include "utils/encrypt.hpp"
|
||||
#include "utils/utils.hpp"
|
||||
#include "utils/encryption.hpp"
|
||||
|
||||
namespace repertory {
|
||||
class curl_comm final : public i_http_comm {
|
||||
@@ -42,8 +41,8 @@ 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;
|
||||
data_buffer data{};
|
||||
stop_type &stop_requested;
|
||||
};
|
||||
|
||||
static const write_callback write_data;
|
||||
@@ -56,6 +55,11 @@ private:
|
||||
private:
|
||||
bool use_s3_path_style_{false};
|
||||
|
||||
public:
|
||||
[[nodiscard]] static auto create_curl() -> CURL *;
|
||||
|
||||
[[nodiscard]] static auto reset_curl(CURL *curl_handle) -> CURL *;
|
||||
|
||||
public:
|
||||
[[nodiscard]] static auto
|
||||
construct_url(CURL *curl, const std::string &relative_path,
|
||||
@@ -92,32 +96,31 @@ public:
|
||||
const auto key =
|
||||
utils::encryption::generate_key<utils::encryption::hash_256_t>(
|
||||
request.decryption_token.value());
|
||||
const auto result = utils::encryption::read_encrypted_range(
|
||||
request.range.value(), key,
|
||||
[&](data_buffer &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 utils::encryption::read_encrypted_range(
|
||||
request.range.value(), key,
|
||||
[&](data_buffer &ct, std::uint64_t start_offset,
|
||||
std::uint64_t end_offset) -> bool {
|
||||
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 (not make_request(cfg, encrypted_request, response_code,
|
||||
stop_requested)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (response_code != 200) {
|
||||
return api_error::comm_error;
|
||||
}
|
||||
if (response_code != 200) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return api_error::success;
|
||||
},
|
||||
request.total_size.value(), data);
|
||||
if (result != api_error::success) {
|
||||
return true;
|
||||
},
|
||||
request.total_size.value(), data)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -140,7 +143,7 @@ public:
|
||||
|
||||
response_code = 0;
|
||||
|
||||
auto *curl = utils::create_curl();
|
||||
auto *curl = create_curl();
|
||||
if (not request.set_method(curl, stop_requested)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -23,7 +23,7 @@
|
||||
#define INCLUDE_COMM_CURL_CURL_REQUESTS_HTTP_REQUEST_BASE_HPP_
|
||||
|
||||
#include "types/repertory.hpp"
|
||||
#include "utils/native_file.hpp"
|
||||
#include "utils/file.hpp"
|
||||
|
||||
namespace repertory::curl::requests {
|
||||
using read_callback = size_t (*)(char *, size_t, size_t, void *);
|
||||
@@ -33,7 +33,7 @@ using response_callback =
|
||||
|
||||
struct read_file_info final {
|
||||
stop_type &stop_requested;
|
||||
native_file::native_file_ptr nf{};
|
||||
std::unique_ptr<utils::file::i_file> file{};
|
||||
std::uint64_t offset{};
|
||||
};
|
||||
|
||||
@@ -41,9 +41,9 @@ 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(
|
||||
reinterpret_cast<unsigned char *>(buffer), size * nitems,
|
||||
read_info->offset, bytes_read);
|
||||
auto ret =
|
||||
read_info->file->read(reinterpret_cast<unsigned char *>(buffer),
|
||||
size * nitems, read_info->offset, &bytes_read);
|
||||
if (ret) {
|
||||
read_info->offset += bytes_read;
|
||||
}
|
||||
@@ -66,7 +66,7 @@ struct http_request_base {
|
||||
std::optional<std::string> decryption_token{};
|
||||
http_headers headers{};
|
||||
std::string path{};
|
||||
query_parameters query{};
|
||||
http_query_parameters query{};
|
||||
std::optional<http_range> range{};
|
||||
std::optional<response_callback> response_handler;
|
||||
std::optional<http_headers> response_headers;
|
||||
|
||||
@@ -61,17 +61,7 @@ inline constexpr const std::uint64_t REPERTORY_CONFIG_VERSION = 0ULL;
|
||||
inline constexpr const std::string_view REPERTORY_DATA_NAME = "repertory2";
|
||||
inline constexpr const std::string_view REPERTORY_MIN_REMOTE_VERSION = "2.0.0";
|
||||
|
||||
#if defined(_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
|
||||
|
||||
inline constexpr const auto NANOS_PER_SECOND = 1000000000L;
|
||||
|
||||
#define WINFSP_ALLOCATION_UNIT UINT64(4096U)
|
||||
|
||||
|
||||
@@ -64,15 +64,15 @@ private:
|
||||
struct fuse_operations fuse_ops_ {};
|
||||
|
||||
private:
|
||||
[[nodiscard]] auto execute_callback(
|
||||
std::string_view 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(std::string_view function_name, const char *from,
|
||||
const char *to,
|
||||
const std::function<api_error(std::string, std::string)> &cb,
|
||||
bool disable_logging = false) -> int;
|
||||
|
||||
[[nodiscard]] auto
|
||||
execute_callback(std::string_view function_name, const char *path,
|
||||
const std::function<api_error(const std::string &)> &cb,
|
||||
const std::function<api_error(std::string)> &cb,
|
||||
bool disable_logging = false) -> int;
|
||||
|
||||
static void execute_void_callback(std::string_view function_name,
|
||||
@@ -83,7 +83,7 @@ private:
|
||||
const std::function<void *()> &cb) -> void *;
|
||||
|
||||
void raise_fuse_event(std::string_view function_name,
|
||||
const std::string &api_path, int ret,
|
||||
std::string_view api_path, int ret,
|
||||
bool disable_logging);
|
||||
|
||||
private:
|
||||
|
||||
@@ -1269,7 +1269,7 @@ public:
|
||||
data_buffer buffer(write_size);
|
||||
if ((ret = request->decode(buffer.data(), buffer.size())) == 0) {
|
||||
buffer = macaron::Base64::Decode(
|
||||
std::string{buffer.begin(), buffer.end()});
|
||||
std::string(buffer.begin(), buffer.end()));
|
||||
write_size = buffer.size();
|
||||
|
||||
remote::file_offset write_offset{};
|
||||
|
||||
@@ -42,9 +42,9 @@ private:
|
||||
private:
|
||||
#if defined(_WIN32)
|
||||
#define to_handle(x) (x)
|
||||
#else
|
||||
#else // !defined(_WIN32)
|
||||
static auto to_handle(PVOID file_desc) -> native_handle;
|
||||
#endif
|
||||
#endif // defined(_WIN32)
|
||||
|
||||
public:
|
||||
auto json_create_directory_snapshot(const std::string &path, json &json_data)
|
||||
|
||||
@@ -30,7 +30,7 @@
|
||||
#include "file_manager/i_upload_manager.hpp"
|
||||
#include "platform/platform.hpp"
|
||||
#include "types/repertory.hpp"
|
||||
#include "utils/native_file.hpp"
|
||||
#include "utils/file.hpp"
|
||||
|
||||
namespace repertory {
|
||||
class app_config;
|
||||
@@ -131,7 +131,7 @@ public:
|
||||
std::atomic<std::chrono::system_clock::time_point> last_access_{
|
||||
std::chrono::system_clock::now()};
|
||||
bool modified_{false};
|
||||
native_file_ptr nf_;
|
||||
std::unique_ptr<utils::file::i_file> nf_;
|
||||
mutable std::mutex io_thread_mtx_;
|
||||
std::condition_variable io_thread_notify_;
|
||||
std::deque<std::shared_ptr<io_item>> io_thread_queue_;
|
||||
|
||||
@@ -29,6 +29,9 @@
|
||||
|
||||
namespace repertory {
|
||||
class encrypt_provider final : public i_provider {
|
||||
public:
|
||||
static const constexpr auto type{provider_type::encrypt};
|
||||
|
||||
public:
|
||||
explicit encrypt_provider(app_config &config);
|
||||
|
||||
@@ -70,10 +73,9 @@ private:
|
||||
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;
|
||||
auto process_directory_entry(const utils::file::i_fs_item &dir_entry,
|
||||
const encrypt_config &cfg,
|
||||
std::string &api_path) const -> bool;
|
||||
|
||||
void remove_deleted_files();
|
||||
|
||||
@@ -81,74 +83,68 @@ 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 {
|
||||
[[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
|
||||
get_api_path_from_source(const std::string & /*source_path*/,
|
||||
std::string & /*api_path*/) const
|
||||
-> api_error override;
|
||||
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_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_file(const std::string &api_path,
|
||||
api_file &file) const -> api_error override;
|
||||
|
||||
[[nodiscard]] auto
|
||||
get_filesystem_item_from_source_path(const std::string &source_path,
|
||||
filesystem_item &fsi) const
|
||||
-> api_error override;
|
||||
get_file_list(api_file_list &list) const -> api_error override;
|
||||
|
||||
[[nodiscard]] auto get_pinned_files() const
|
||||
-> std::vector<std::string> override;
|
||||
[[nodiscard]] auto
|
||||
get_file_size(const std::string &api_path,
|
||||
std::uint64_t &file_size) 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_filesystem_item(const std::string &api_path, bool directory,
|
||||
filesystem_item &fsi) 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_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;
|
||||
return type;
|
||||
}
|
||||
|
||||
[[nodiscard]] auto get_used_drive_space() const -> std::uint64_t override;
|
||||
@@ -158,54 +154,52 @@ public:
|
||||
[[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(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_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
|
||||
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 {
|
||||
[[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 {
|
||||
[[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 {
|
||||
[[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 {
|
||||
[[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 {
|
||||
[[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 {
|
||||
[[nodiscard]] auto
|
||||
set_item_meta(const std::string & /*api_path*/,
|
||||
const api_meta_map & /*meta*/) -> api_error override {
|
||||
return api_error::success;
|
||||
}
|
||||
|
||||
@@ -214,10 +208,10 @@ public:
|
||||
|
||||
void stop() override;
|
||||
|
||||
[[nodiscard]] auto upload_file(const std::string & /*api_path*/,
|
||||
const std::string & /*source_path*/,
|
||||
stop_type & /*stop_requested*/)
|
||||
-> api_error 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;
|
||||
}
|
||||
};
|
||||
|
||||
@@ -32,6 +32,9 @@ class i_http_comm;
|
||||
struct head_object_result;
|
||||
|
||||
class s3_provider final : public base_provider {
|
||||
public:
|
||||
static const constexpr auto type{provider_type::s3};
|
||||
|
||||
public:
|
||||
s3_provider(app_config &config, i_http_comm &comm);
|
||||
|
||||
@@ -92,6 +95,9 @@ protected:
|
||||
stop_type &stop_requested) -> api_error override;
|
||||
|
||||
public:
|
||||
[[nodiscard]] static auto
|
||||
convert_api_date(std::string_view date) -> std::uint64_t;
|
||||
|
||||
[[nodiscard]] auto get_directory_item_count(const std::string &api_path) const
|
||||
-> std::uint64_t override;
|
||||
|
||||
@@ -104,7 +110,7 @@ public:
|
||||
[[nodiscard]] auto get_total_drive_space() const -> std::uint64_t override;
|
||||
|
||||
[[nodiscard]] auto get_provider_type() const -> provider_type override {
|
||||
return provider_type::s3;
|
||||
return type;
|
||||
}
|
||||
|
||||
[[nodiscard]] auto is_direct_only() const -> bool override { return false; }
|
||||
|
||||
@@ -31,6 +31,9 @@ class i_file_manager;
|
||||
class i_http_comm;
|
||||
|
||||
class sia_provider : public base_provider {
|
||||
public:
|
||||
static const constexpr auto type{provider_type::sia};
|
||||
|
||||
public:
|
||||
sia_provider(app_config &config, i_http_comm &comm);
|
||||
|
||||
@@ -50,40 +53,39 @@ private:
|
||||
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
|
||||
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
|
||||
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_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
|
||||
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;
|
||||
[[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(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_list(api_file_list &list) const -> api_error override;
|
||||
|
||||
[[nodiscard]] auto get_provider_type() const -> provider_type override {
|
||||
return provider_type::sia;
|
||||
return type;
|
||||
}
|
||||
|
||||
[[nodiscard]] auto get_total_drive_space() const -> std::uint64_t override;
|
||||
@@ -93,8 +95,8 @@ public:
|
||||
[[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(const std::string &api_path,
|
||||
bool &exists) const -> api_error override;
|
||||
|
||||
[[nodiscard]] auto is_online() const -> bool override;
|
||||
|
||||
@@ -102,15 +104,14 @@ public:
|
||||
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
|
||||
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
|
||||
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;
|
||||
|
||||
@@ -22,14 +22,14 @@
|
||||
#ifndef INCLUDE_TYPES_REMOTE_HPP_
|
||||
#define INCLUDE_TYPES_REMOTE_HPP_
|
||||
|
||||
#define PACKET_SERVICE_FUSE 1U
|
||||
#define PACKET_SERVICE_WINFSP 2U
|
||||
inline constexpr const auto PACKET_SERVICE_FUSE{1U};
|
||||
inline constexpr const auto PACKET_SERVICE_WINFSP{2U};
|
||||
|
||||
#if defined(_WIN32)
|
||||
#define PACKET_SERVICE_FLAGS PACKET_SERVICE_WINFSP
|
||||
#else
|
||||
#define PACKET_SERVICE_FLAGS PACKET_SERVICE_FUSE
|
||||
#endif
|
||||
inline constexpr const auto PACKET_SERVICE_FLAGS{PACKET_SERVICE_WINFSP};
|
||||
#else // !defined(_WIN32)
|
||||
inline constexpr const auto PACKET_SERVICE_FLAGS{PACKET_SERVICE_FUSE};
|
||||
#endif // defined(_WIN32)
|
||||
|
||||
namespace repertory::remote {
|
||||
using block_count = std::uint64_t;
|
||||
@@ -65,16 +65,19 @@ enum class open_flags : std::uint32_t {
|
||||
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));
|
||||
#if defined(__GNUG__)
|
||||
__attribute__((unused))
|
||||
#endif // defined(__GNUG__)
|
||||
inline auto
|
||||
operator|(const open_flags &flag_1, const open_flags &flag_2) -> open_flags {
|
||||
using flag_t = std::underlying_type_t<open_flags>;
|
||||
return static_cast<open_flags>(static_cast<flag_t>(flag_1) |
|
||||
static_cast<flag_t>(flag_2));
|
||||
}
|
||||
|
||||
#if defined(__GNUG__)
|
||||
__attribute__((unused))
|
||||
#endif
|
||||
#endif // defined(__GNUG__)
|
||||
inline auto
|
||||
operator|=(open_flags &flag_1, const open_flags &flag_2) -> open_flags & {
|
||||
flag_1 = flag_1 | flag_2;
|
||||
@@ -83,69 +86,69 @@ operator|=(open_flags &flag_1, const open_flags &flag_2) -> open_flags & {
|
||||
|
||||
#if defined(__GNUG__)
|
||||
__attribute__((unused))
|
||||
#endif
|
||||
#endif // defined(__GNUG__)
|
||||
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));
|
||||
using flag_t = std::underlying_type_t<open_flags>;
|
||||
return static_cast<open_flags>(static_cast<flag_t>(flag_1) &
|
||||
static_cast<flag_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 file_info final {
|
||||
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 setattr_x final {
|
||||
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 stat final {
|
||||
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;
|
||||
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];
|
||||
struct statfs_x final : public statfs {
|
||||
std::array<char, 1024U> f_mntfromname{};
|
||||
};
|
||||
#pragma pack()
|
||||
|
||||
@@ -154,7 +157,7 @@ struct statfs_x : public statfs {
|
||||
|
||||
[[nodiscard]] auto
|
||||
create_os_open_flags(const open_flags &flags) -> std::uint32_t;
|
||||
#endif
|
||||
#endif // !defined(_WIN32)
|
||||
} // namespace repertory::remote
|
||||
|
||||
#endif // INCLUDE_TYPES_REMOTE_HPP_
|
||||
|
||||
@@ -23,26 +23,26 @@
|
||||
#define INCLUDE_TYPES_REPERTORY_HPP_
|
||||
|
||||
namespace repertory {
|
||||
constexpr const auto max_time = 0xFFFFFFFFFFFFFFFFULL;
|
||||
inline constexpr const auto max_time{std::numeric_limits<std::uint64_t>::max()};
|
||||
|
||||
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";
|
||||
inline constexpr const std::string META_ACCESSED{"accessed"};
|
||||
inline constexpr const std::string META_ATTRIBUTES{"attributes"};
|
||||
inline constexpr const std::string META_BACKUP{"backup"};
|
||||
inline constexpr const std::string META_CHANGED{"changed"};
|
||||
inline constexpr const std::string META_CREATION{"creation"};
|
||||
inline constexpr const std::string META_DIRECTORY{"directory"};
|
||||
inline constexpr const std::string META_GID{"gid"};
|
||||
inline constexpr const std::string META_KEY{"key"};
|
||||
inline constexpr const std::string META_MODE{"mode"};
|
||||
inline constexpr const std::string META_MODIFIED{"modified"};
|
||||
inline constexpr const std::string META_OSXFLAGS{"flags"};
|
||||
inline constexpr const std::string META_PINNED{"pinned"};
|
||||
inline constexpr const std::string META_SIZE{"size"};
|
||||
inline constexpr const std::string META_SOURCE{"source"};
|
||||
inline constexpr const std::string META_UID{"uid"};
|
||||
inline constexpr const std::string META_WRITTEN{"written"};
|
||||
|
||||
const std::vector<std::string> META_USED_NAMES = {
|
||||
inline constexpr const std::array<std::string, 16U> 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,
|
||||
@@ -51,8 +51,6 @@ const std::vector<std::string> META_USED_NAMES = {
|
||||
|
||||
using api_meta_map = std::map<std::string, std::string>;
|
||||
|
||||
using stop_type = std::atomic<bool>;
|
||||
|
||||
enum class api_error {
|
||||
success = 0,
|
||||
access_denied,
|
||||
@@ -152,28 +150,28 @@ enum class provider_type : std::size_t {
|
||||
};
|
||||
|
||||
#if defined(_WIN32)
|
||||
struct open_file_data {
|
||||
struct open_file_data final {
|
||||
void *directory_buffer{};
|
||||
};
|
||||
#else
|
||||
using open_file_data = int;
|
||||
#endif
|
||||
|
||||
struct api_file {
|
||||
std::string api_path;
|
||||
std::string api_parent;
|
||||
struct api_file final {
|
||||
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::string key{};
|
||||
std::uint64_t modified_date{};
|
||||
std::string source_path;
|
||||
};
|
||||
|
||||
struct directory_item {
|
||||
std::string api_path;
|
||||
std::string api_parent;
|
||||
struct directory_item final {
|
||||
std::string api_path{};
|
||||
std::string api_parent{};
|
||||
bool directory{false};
|
||||
std::uint64_t size{};
|
||||
api_meta_map meta{};
|
||||
@@ -190,26 +188,30 @@ struct directory_item {
|
||||
}
|
||||
|
||||
[[nodiscard]] auto to_json() const -> json {
|
||||
return {{"path", api_path},
|
||||
{"parent", api_parent},
|
||||
{"size", size},
|
||||
{"directory", directory},
|
||||
{"meta", meta}};
|
||||
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 encrypt_config final {
|
||||
std::string encryption_token{};
|
||||
std::string path{};
|
||||
};
|
||||
|
||||
struct host_config {
|
||||
std::string agent_string;
|
||||
std::string api_password;
|
||||
std::string api_user;
|
||||
struct filesystem_item final {
|
||||
std::string api_path{};
|
||||
std::string api_parent{};
|
||||
bool directory{false};
|
||||
std::uint64_t size{};
|
||||
std::string source_path{};
|
||||
};
|
||||
|
||||
struct host_config final {
|
||||
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{};
|
||||
@@ -265,25 +267,15 @@ from_json(const json &j, host_config &hc) {
|
||||
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;
|
||||
struct s3_config final {
|
||||
std::string access_key{};
|
||||
std::string bucket{};
|
||||
std::uint16_t cache_timeout_secs{60U};
|
||||
std::string encryption_token;
|
||||
std::string encryption_token{};
|
||||
std::string region{"any"};
|
||||
std::string secret_key;
|
||||
std::string secret_key{};
|
||||
std::uint32_t timeout_ms{60000U};
|
||||
std::string url;
|
||||
std::string url{};
|
||||
bool use_path_style{false};
|
||||
bool use_region_in_url{false};
|
||||
};
|
||||
@@ -292,11 +284,7 @@ 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 query_parameters = std::map<std::string, std::string>;
|
||||
} // namespace repertory
|
||||
|
||||
#endif // INCLUDE_TYPES_REPERTORY_HPP_
|
||||
|
||||
@@ -79,8 +79,8 @@ struct head_object_result {
|
||||
#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;
|
||||
last_modified = static_cast<std::uint64_t>(mktime(&tm1)) *
|
||||
utils::time::NANOS_PER_SECOND;
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
@@ -1,49 +0,0 @@
|
||||
/*
|
||||
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_
|
||||
@@ -1,46 +0,0 @@
|
||||
/*
|
||||
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_ENCRYPT_HPP_
|
||||
#define INCLUDE_UTILS_ENCRYPT_HPP_
|
||||
|
||||
#include "types/repertory.hpp"
|
||||
#include "utils/encryption.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(std::string_view encryption_token,
|
||||
std::string &file_path) -> api_error;
|
||||
|
||||
[[nodiscard]] auto decrypt_file_name(std::string_view encryption_token,
|
||||
std::string &file_name) -> api_error;
|
||||
|
||||
[[nodiscard]] auto
|
||||
read_encrypted_range(const http_range &range,
|
||||
const utils::encryption::hash_256_t &key,
|
||||
reader_func reader, std::uint64_t total_size,
|
||||
data_buffer &data) -> api_error;
|
||||
} // namespace repertory::utils::encryption
|
||||
|
||||
#endif // INCLUDE_UTILS_ENCRYPT_HPP_
|
||||
@@ -1,140 +0,0 @@
|
||||
/*
|
||||
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/encryption.hpp"
|
||||
#include "utils/native_file.hpp"
|
||||
|
||||
namespace repertory::utils::encryption {
|
||||
class encrypting_reader final {
|
||||
public:
|
||||
encrypting_reader(std::string_view file_name, std::string_view source_path,
|
||||
stop_type &stop_requested, std::string_view token,
|
||||
std::optional<std::string_view> relative_parent_path,
|
||||
std::size_t error_return = 0U);
|
||||
|
||||
encrypting_reader(std::string_view encrypted_file_path,
|
||||
std::string_view source_path, stop_type &stop_requested,
|
||||
std::string_view token, std::size_t error_return = 0U);
|
||||
|
||||
encrypting_reader(
|
||||
std::string_view encrypted_file_path, std::string_view source_path,
|
||||
stop_type &stop_requested, std::string_view 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:
|
||||
utils::encryption::hash_256_t key_;
|
||||
stop_type &stop_requested_;
|
||||
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(std::string_view 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]] 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_
|
||||
@@ -22,64 +22,17 @@
|
||||
#ifndef INCLUDE_UTILS_FILE_UTILS_HPP_
|
||||
#define INCLUDE_UTILS_FILE_UTILS_HPP_
|
||||
|
||||
#include "types/repertory.hpp"
|
||||
#include "utils/file.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,
|
||||
get_directory_files(std::string_view 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_modified_time(const std::string &path,
|
||||
std::uint64_t &modified) -> 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 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;
|
||||
} // namespace repertory::utils::file
|
||||
|
||||
#endif // INCLUDE_UTILS_FILE_UTILS_HPP_
|
||||
|
||||
@@ -1,117 +0,0 @@
|
||||
/*
|
||||
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(std::string_view source_path,
|
||||
bool read_only,
|
||||
native_file_ptr &ptr) -> api_error;
|
||||
|
||||
[[nodiscard]] static auto create_or_open(std::string_view source_path,
|
||||
native_file_ptr &ptr) -> api_error;
|
||||
|
||||
[[nodiscard]] static auto open(std::string_view source_path,
|
||||
native_file_ptr &ptr) -> api_error;
|
||||
|
||||
[[nodiscard]] static auto open(std::string_view 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};
|
||||
#if defined(_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;
|
||||
|
||||
#if defined(_WIN32)
|
||||
[[nodiscard]] auto read_bytes(unsigned char *buffer, std::size_t read_size,
|
||||
std::uint64_t read_offset,
|
||||
std::size_t &bytes_read) -> bool;
|
||||
#else
|
||||
[[nodiscard]] auto read_bytes(unsigned 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;
|
||||
|
||||
#if defined(_WIN32)
|
||||
[[nodiscard]] auto write_bytes(const unsigned char *buffer,
|
||||
std::size_t write_size,
|
||||
std::uint64_t write_offset,
|
||||
std::size_t &bytes_written) -> bool;
|
||||
#else
|
||||
[[nodiscard]] auto write_bytes(const unsigned 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_
|
||||
@@ -43,15 +43,9 @@ inline const std::array<std::string, 4U> attribute_namespaces = {
|
||||
|
||||
[[nodiscard]] auto unix_error_to_windows(int err) -> std::uint32_t;
|
||||
|
||||
[[nodiscard]] auto
|
||||
unix_time_to_windows_time(const remote::file_time &file_time) -> UINT64;
|
||||
|
||||
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;
|
||||
} // namespace repertory::utils
|
||||
|
||||
#endif // !_WIN32
|
||||
|
||||
@@ -29,27 +29,10 @@ void calculate_allocation_size(bool directory, std::uint64_t file_size,
|
||||
UINT64 allocation_size,
|
||||
std::string &allocation_meta_size);
|
||||
|
||||
[[nodiscard]] auto convert_api_date(const std::string &date) -> std::uint64_t;
|
||||
|
||||
[[nodiscard]] auto create_curl() -> CURL *;
|
||||
|
||||
[[nodiscard]] auto
|
||||
create_volume_label(const provider_type &prov) -> std::string;
|
||||
|
||||
[[nodiscard]] auto get_attributes_from_meta(const api_meta_map &meta) -> DWORD;
|
||||
|
||||
[[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 = "");
|
||||
|
||||
} // namespace repertory::utils
|
||||
|
||||
#endif // INCLUDE_UTILS_UTILS_HPP_
|
||||
|
||||
@@ -100,18 +100,17 @@ app_config::app_config(const provider_type &prov,
|
||||
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_)) {
|
||||
if (not utils::file::directory(data_directory_).create_directory()) {
|
||||
throw startup_exception("unable to create: " + data_directory_);
|
||||
}
|
||||
|
||||
if (not utils::file::create_full_directory_path(cache_directory_)) {
|
||||
if (not utils::file::directory(cache_directory_).create_directory()) {
|
||||
throw startup_exception("unable to create: " + cache_directory_);
|
||||
}
|
||||
|
||||
if (not utils::file::create_full_directory_path(log_directory_)) {
|
||||
if (not utils::file::directory(log_directory_).create_directory()) {
|
||||
throw startup_exception("unable to create: " + log_directory_);
|
||||
}
|
||||
|
||||
@@ -318,39 +317,12 @@ auto app_config::get_json() const -> json {
|
||||
}
|
||||
|
||||
auto app_config::get_max_cache_size_bytes() const -> std::uint64_t {
|
||||
const auto max_space =
|
||||
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 {
|
||||
#if defined(_WIN32)
|
||||
auto api_file = utils::path::combine(utils::get_local_app_data_directory(),
|
||||
{
|
||||
get_provider_display_name(prov),
|
||||
"apipassword",
|
||||
});
|
||||
#else
|
||||
#if defined(__APPLE__)
|
||||
auto api_file = utils::path::combine("~", {
|
||||
"/",
|
||||
"Library",
|
||||
"Application Support",
|
||||
get_provider_display_name(prov),
|
||||
"apipassword",
|
||||
});
|
||||
#else
|
||||
auto api_file = utils::path::combine("~/.", {
|
||||
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 free_space = utils::file::get_free_drive_space(get_cache_directory());
|
||||
return free_space.has_value() ? std::min(free_space.value(), max_space)
|
||||
: max_space;
|
||||
}
|
||||
|
||||
auto app_config::get_provider_display_name(const provider_type &prov)
|
||||
@@ -542,12 +514,11 @@ auto app_config::load() -> bool {
|
||||
static_cast<const char *>(__FUNCTION__),
|
||||
};
|
||||
|
||||
auto ret = false;
|
||||
auto ret{false};
|
||||
|
||||
const auto config_file_path = get_config_file_path();
|
||||
std::cout << config_file_path << std::endl;
|
||||
recur_mutex_lock lock(read_write_mutex_);
|
||||
if (utils::file::is_file(config_file_path)) {
|
||||
if (utils::file::file(config_file_path).exists()) {
|
||||
try {
|
||||
std::ifstream config_file(config_file_path.data());
|
||||
if (config_file.is_open()) {
|
||||
@@ -606,13 +577,6 @@ auto app_config::load() -> bool {
|
||||
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_;
|
||||
@@ -713,9 +677,9 @@ void app_config::save() {
|
||||
|
||||
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_)) {
|
||||
if (config_changed_ || not utils::file::file(file_path).exists()) {
|
||||
if (not utils::file::directory(data_directory_).exists()) {
|
||||
if (not utils::file::directory{data_directory_}.create_directory()) {
|
||||
utils::error::raise_error(
|
||||
function_name, "failed to create directory|sp|" + data_directory_ +
|
||||
"|err|" +
|
||||
|
||||
@@ -92,6 +92,16 @@ auto curl_comm::construct_url(CURL *curl, const std::string &relative_path,
|
||||
relative_path, url);
|
||||
}
|
||||
|
||||
auto curl_comm::create_curl() -> CURL * { return reset_curl(curl_easy_init()); }
|
||||
|
||||
auto curl_comm::reset_curl(CURL *curl_handle) -> CURL * {
|
||||
curl_easy_reset(curl_handle);
|
||||
#if defined(__APPLE__)
|
||||
curl_easy_setopt(curl_handle, CURLOPT_NOSIGNAL, 1);
|
||||
#endif // defined(__APPLE__)
|
||||
return curl_handle;
|
||||
}
|
||||
|
||||
auto curl_comm::create_host_config(const s3_config &cfg,
|
||||
bool use_s3_path_style) -> host_config {
|
||||
host_config host_cfg{};
|
||||
|
||||
@@ -24,8 +24,8 @@
|
||||
#include "utils/string.hpp"
|
||||
|
||||
namespace repertory::curl::requests {
|
||||
auto http_put_file::set_method(CURL *curl, stop_type &stop_requested) const
|
||||
-> bool {
|
||||
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);
|
||||
|
||||
@@ -46,19 +46,14 @@ auto http_put_file::set_method(CURL *curl, stop_type &stop_requested) const
|
||||
|
||||
read_info = std::make_shared<read_file_info>(read_file_info{
|
||||
stop_requested,
|
||||
utils::file::file::open_or_create_file(source_path),
|
||||
});
|
||||
|
||||
if (native_file::create_or_open(source_path, read_info->nf) !=
|
||||
api_error::success) {
|
||||
if (not *read_info->file) {
|
||||
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;
|
||||
}
|
||||
auto file_size = read_info->file->size();
|
||||
|
||||
curl_easy_setopt(curl, CURLOPT_READDATA, read_info.get());
|
||||
curl_easy_setopt(curl, CURLOPT_READFUNCTION, read_file_data);
|
||||
|
||||
@@ -38,7 +38,7 @@ void packet::clear() {
|
||||
auto packet::decode(std::string &data) -> packet::error_type {
|
||||
const auto *str = reinterpret_cast<const char *>(&buffer_[decode_offset_]);
|
||||
const auto length = strnlen(str, buffer_.size() - decode_offset_);
|
||||
data = std::string{str, length};
|
||||
data = std::string(str, length);
|
||||
decode_offset_ += (length + 1);
|
||||
|
||||
return utils::from_api_error(api_error::success);
|
||||
@@ -194,7 +194,7 @@ auto packet::decode(remote::statfs &val) -> packet::error_type {
|
||||
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));
|
||||
ret = decode(val.f_mntfromname.data(), val.f_mntfromname.size());
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
@@ -372,9 +372,9 @@ void packet::encode(remote::statfs val, bool should_reserve) {
|
||||
|
||||
void packet::encode(remote::statfs_x val) {
|
||||
buffer_.reserve(buffer_.size() + sizeof(remote::statfs) +
|
||||
sizeof(val.f_mntfromname));
|
||||
val.f_mntfromname.size());
|
||||
encode(*dynamic_cast<remote::statfs *>(&val), false);
|
||||
encode(&val.f_mntfromname[0], sizeof(val.f_mntfromname), false);
|
||||
encode(val.f_mntfromname.data(), val.f_mntfromname.size(), false);
|
||||
}
|
||||
|
||||
void packet::encode(remote::file_info val) {
|
||||
@@ -501,8 +501,8 @@ void packet::encode_top(remote::statfs val, bool 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);
|
||||
val.f_mntfromname.size());
|
||||
encode_top(val.f_mntfromname.data(), val.f_mntfromname.size(), false);
|
||||
encode_top(*dynamic_cast<remote::statfs *>(&val), false);
|
||||
}
|
||||
|
||||
|
||||
@@ -85,7 +85,7 @@ void directory_cache::service_function() {
|
||||
auto lookup = directory_lookup_;
|
||||
directory_lock.unlock();
|
||||
|
||||
for (const auto &kv : lookup) {
|
||||
for (auto &&kv : lookup) {
|
||||
if (std::chrono::duration_cast<std::chrono::seconds>(
|
||||
std::chrono::system_clock::now() - kv.second.last_update) >= 120s) {
|
||||
directory_lock.lock();
|
||||
|
||||
@@ -38,37 +38,31 @@ auto eviction::check_minimum_requirements(const std::string &file_path)
|
||||
static_cast<const char *>(__FUNCTION__),
|
||||
};
|
||||
|
||||
std::uint64_t file_size{};
|
||||
if (not utils::file::get_file_size(file_path, file_size)) {
|
||||
auto opt_size = utils::file::file{file_path}.size();
|
||||
if (not opt_size.has_value()) {
|
||||
utils::error::raise_error(function_name, utils::get_last_error_code(),
|
||||
file_path, "failed to get file size");
|
||||
return false;
|
||||
}
|
||||
|
||||
auto ret = false;
|
||||
if (file_size != 0U) {
|
||||
std::uint64_t reference_time{};
|
||||
ret = config_.get_eviction_uses_accessed_time()
|
||||
? utils::file::get_accessed_time(file_path, reference_time)
|
||||
: utils::file::get_modified_time(file_path, reference_time);
|
||||
if (ret) {
|
||||
#if defined(_WIN32)
|
||||
const auto now = std::chrono::system_clock::now();
|
||||
const auto delay =
|
||||
std::chrono::minutes(config_.get_eviction_delay_mins());
|
||||
ret = ((std::chrono::system_clock::from_time_t(
|
||||
static_cast<time_t>(reference_time)) +
|
||||
delay) <= now);
|
||||
#else
|
||||
const auto now = utils::time::get_time_now();
|
||||
const auto delay =
|
||||
(config_.get_eviction_delay_mins() * 60L) * NANOS_PER_SECOND;
|
||||
ret = ((reference_time + static_cast<std::uint64_t>(delay)) <= now);
|
||||
#endif
|
||||
}
|
||||
auto file_size{opt_size.value()};
|
||||
if (file_size == 0U) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return ret;
|
||||
auto reference_time = utils::file::file{file_path}.get_time(
|
||||
config_.get_eviction_uses_accessed_time()
|
||||
? utils::file::time_type::accessed
|
||||
: utils::file::time_type::modified);
|
||||
|
||||
if (not reference_time.has_value()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
auto delay = (config_.get_eviction_delay_mins() * 60UL) *
|
||||
utils::time::NANOS_PER_SECOND;
|
||||
return ((reference_time.value() + static_cast<std::uint64_t>(delay)) <=
|
||||
utils::time::get_time_now());
|
||||
}
|
||||
|
||||
auto eviction::get_filtered_cached_files() -> std::deque<std::string> {
|
||||
@@ -91,7 +85,7 @@ void eviction::service_function() {
|
||||
|
||||
// Handle maximum cache size eviction
|
||||
auto used_bytes =
|
||||
utils::file::calculate_used_space(config_.get_cache_directory(), false);
|
||||
utils::file::directory{config_.get_cache_directory()}.size();
|
||||
if (config_.get_enable_max_cache_size()) {
|
||||
should_evict = (used_bytes > config_.get_max_cache_size_bytes());
|
||||
}
|
||||
@@ -110,9 +104,9 @@ void eviction::service_function() {
|
||||
if (provider_.get_filesystem_item_and_file(api_path, file, fsi) ==
|
||||
api_error::success) {
|
||||
// Only evict files that match expected size
|
||||
std::uint64_t file_size{};
|
||||
if (utils::file::get_file_size(cached_files_list.front(),
|
||||
file_size)) {
|
||||
auto opt_size = utils::file::file{cached_files_list.front()}.size();
|
||||
if (opt_size.has_value()) {
|
||||
auto file_size{opt_size.value()};
|
||||
if (file_size == fsi.size) {
|
||||
// Try to evict file
|
||||
if (fm_.evict_file(fsi.api_path) &&
|
||||
|
||||
@@ -106,8 +106,8 @@ auto fuse_base::access_(const char *path, int mask) -> int {
|
||||
};
|
||||
|
||||
return instance().instance().execute_callback(
|
||||
function_name, path, [&](const std::string &api_path) -> api_error {
|
||||
return instance().access_impl(api_path, mask);
|
||||
function_name, path, [&](std::string api_path) -> api_error {
|
||||
return instance().access_impl(std::move(api_path), mask);
|
||||
});
|
||||
}
|
||||
|
||||
@@ -118,8 +118,8 @@ auto fuse_base::chflags_(const char *path, uint32_t flags) -> int {
|
||||
};
|
||||
|
||||
return instance().instance().execute_callback(
|
||||
function_name, path, [&](const std::string &api_path) -> api_error {
|
||||
return instance().chflags_impl(api_path, flags);
|
||||
function_name, path, [&](std::string api_path) -> api_error {
|
||||
return instance().chflags_impl(std::move(api_path), flags);
|
||||
});
|
||||
}
|
||||
#endif // __APPLE__
|
||||
@@ -132,8 +132,8 @@ auto fuse_base::chmod_(const char *path, mode_t mode,
|
||||
};
|
||||
|
||||
return instance().execute_callback(
|
||||
function_name, path, [&](const std::string &api_path) -> api_error {
|
||||
return instance().chmod_impl(api_path, mode, fi);
|
||||
function_name, path, [&](std::string api_path) -> api_error {
|
||||
return instance().chmod_impl(std::move(api_path), mode, fi);
|
||||
});
|
||||
}
|
||||
#else
|
||||
@@ -143,8 +143,8 @@ auto fuse_base::chmod_(const char *path, mode_t mode) -> int {
|
||||
};
|
||||
|
||||
return instance().execute_callback(
|
||||
function_name, path, [&](const std::string &api_path) -> api_error {
|
||||
return instance().chmod_impl(api_path, mode);
|
||||
function_name, path, [&](std::string api_path) -> api_error {
|
||||
return instance().chmod_impl(std::move(api_path), mode);
|
||||
});
|
||||
}
|
||||
#endif
|
||||
@@ -157,8 +157,8 @@ auto fuse_base::chown_(const char *path, uid_t uid, gid_t gid,
|
||||
};
|
||||
|
||||
return instance().execute_callback(
|
||||
function_name, path, [&](const std::string &api_path) -> api_error {
|
||||
return instance().chown_impl(api_path, uid, gid, fi);
|
||||
function_name, path, [&](std::string api_path) -> api_error {
|
||||
return instance().chown_impl(std::move(api_path), uid, gid, fi);
|
||||
});
|
||||
}
|
||||
#else
|
||||
@@ -168,8 +168,8 @@ auto fuse_base::chown_(const char *path, uid_t uid, gid_t gid) -> int {
|
||||
};
|
||||
|
||||
return instance().execute_callback(
|
||||
function_name, path, [&](const std::string &api_path) -> api_error {
|
||||
return instance().chown_impl(api_path, uid, gid);
|
||||
function_name, path, [&](std::string api_path) -> api_error {
|
||||
return instance().chown_impl(std::move(api_path), uid, gid);
|
||||
});
|
||||
}
|
||||
#endif
|
||||
@@ -181,8 +181,8 @@ auto fuse_base::create_(const char *path, mode_t mode,
|
||||
};
|
||||
|
||||
return instance().execute_callback(
|
||||
function_name, path, [&](const std::string &api_path) -> api_error {
|
||||
return instance().create_impl(api_path, mode, fi);
|
||||
function_name, path, [&](std::string api_path) -> api_error {
|
||||
return instance().create_impl(std::move(api_path), mode, fi);
|
||||
});
|
||||
}
|
||||
|
||||
@@ -223,12 +223,12 @@ void fuse_base::display_version_information(std::vector<const char *> args) {
|
||||
|
||||
auto fuse_base::execute_callback(
|
||||
std::string_view function_name, const char *from, const char *to,
|
||||
const std::function<api_error(const std::string &from_api_file,
|
||||
const std::string &to_api_path)> &cb,
|
||||
const std::function<api_error(std::string from_api_file,
|
||||
std::string to_api_path)> &cb,
|
||||
bool disable_logging) -> int {
|
||||
const auto from_api_file = utils::path::create_api_path(from ? from : "");
|
||||
const auto to_api_file = utils::path::create_api_path(to ? to : "");
|
||||
const auto res = utils::from_api_error(cb(from_api_file, to_api_file));
|
||||
auto from_api_file = utils::path::create_api_path(from ? from : "");
|
||||
auto to_api_file = utils::path::create_api_path(to ? to : "");
|
||||
auto res = utils::from_api_error(cb(from_api_file, to_api_file));
|
||||
raise_fuse_event(function_name,
|
||||
"from|" + from_api_file + "|to|" + to_api_file, res,
|
||||
disable_logging);
|
||||
@@ -237,7 +237,7 @@ auto fuse_base::execute_callback(
|
||||
|
||||
auto fuse_base::execute_callback(
|
||||
std::string_view function_name, const char *path,
|
||||
const std::function<api_error(const std::string &api_path)> &cb,
|
||||
const std::function<api_error(std::string api_path)> &cb,
|
||||
bool disable_logging) -> int {
|
||||
const auto api_path = utils::path::create_api_path(path ? path : "");
|
||||
const auto res = utils::from_api_error(cb(api_path));
|
||||
@@ -269,8 +269,9 @@ auto fuse_base::fallocate_(const char *path, int mode, off_t offset,
|
||||
};
|
||||
|
||||
return instance().execute_callback(
|
||||
function_name, path, [&](const std::string &api_path) -> api_error {
|
||||
return instance().fallocate_impl(api_path, mode, offset, length, fi);
|
||||
function_name, path, [&](std::string api_path) -> api_error {
|
||||
return instance().fallocate_impl(std::move(api_path), mode, offset,
|
||||
length, fi);
|
||||
});
|
||||
}
|
||||
|
||||
@@ -282,8 +283,8 @@ auto fuse_base::fgetattr_(const char *path, struct stat *st,
|
||||
};
|
||||
|
||||
return instance().execute_callback(
|
||||
function_name, path, [&](const std::string &api_path) -> api_error {
|
||||
return instance().fgetattr_impl(api_path, st, fi);
|
||||
function_name, path, [&](std::string api_path) -> api_error {
|
||||
return instance().fgetattr_impl(std::move(api_path), st, fi);
|
||||
});
|
||||
}
|
||||
#endif
|
||||
@@ -296,8 +297,8 @@ auto fuse_base::fsetattr_x_(const char *path, struct setattr_x *attr,
|
||||
};
|
||||
|
||||
return instance().execute_callback(
|
||||
function_name, path, [&](const std::string &api_path) -> api_error {
|
||||
return instance().fsetattr_x_impl(api_path, attr, fi);
|
||||
function_name, path, [&](std::string api_path) -> api_error {
|
||||
return instance().fsetattr_x_impl(std::move(api_path), attr, fi);
|
||||
});
|
||||
}
|
||||
#endif // __APPLE__
|
||||
@@ -309,8 +310,8 @@ auto fuse_base::fsync_(const char *path, int datasync,
|
||||
};
|
||||
|
||||
return instance().execute_callback(
|
||||
function_name, path, [&](const std::string &api_path) -> api_error {
|
||||
return instance().fsync_impl(api_path, datasync, fi);
|
||||
function_name, path, [&](std::string api_path) -> api_error {
|
||||
return instance().fsync_impl(std::move(api_path), datasync, fi);
|
||||
});
|
||||
}
|
||||
|
||||
@@ -322,8 +323,8 @@ auto fuse_base::ftruncate_(const char *path, off_t size,
|
||||
};
|
||||
|
||||
return instance().execute_callback(
|
||||
function_name, path, [&](const std::string &api_path) -> api_error {
|
||||
return instance().ftruncate_impl(api_path, size, fi);
|
||||
function_name, path, [&](std::string api_path) -> api_error {
|
||||
return instance().ftruncate_impl(std::move(api_path), size, fi);
|
||||
});
|
||||
}
|
||||
#endif
|
||||
@@ -336,8 +337,8 @@ auto fuse_base::getattr_(const char *path, struct stat *st,
|
||||
};
|
||||
|
||||
return instance().execute_callback(
|
||||
function_name, path, [&](const std::string &api_path) -> api_error {
|
||||
return instance().getattr_impl(api_path, st, fi);
|
||||
function_name, path, [&](std::string api_path) -> api_error {
|
||||
return instance().getattr_impl(std::move(api_path), st, fi);
|
||||
});
|
||||
}
|
||||
#else
|
||||
@@ -347,8 +348,8 @@ auto fuse_base::getattr_(const char *path, struct stat *st) -> int {
|
||||
};
|
||||
|
||||
return instance().execute_callback(
|
||||
function_name, path, [&](const std::string &api_path) -> api_error {
|
||||
return instance().getattr_impl(api_path, st);
|
||||
function_name, path, [&](std::string api_path) -> api_error {
|
||||
return instance().getattr_impl(std::move(api_path), st);
|
||||
});
|
||||
}
|
||||
#endif
|
||||
@@ -361,8 +362,8 @@ auto fuse_base::getxtimes_(const char *path, struct timespec *bkuptime,
|
||||
};
|
||||
|
||||
return instance().execute_callback(
|
||||
function_name, path, [&](const std::string &api_path) -> api_error {
|
||||
return instance().getxtimes_impl(api_path, bkuptime, crtime);
|
||||
function_name, path, [&](std::string api_path) -> api_error {
|
||||
return instance().getxtimes_impl(std::move(api_path), bkuptime, crtime);
|
||||
});
|
||||
}
|
||||
#endif // __APPLE__
|
||||
@@ -392,31 +393,34 @@ auto fuse_base::init_(struct fuse_conn_info *conn) -> void * {
|
||||
#if FUSE_USE_VERSION >= 30
|
||||
auto fuse_base::init_impl([[maybe_unused]] struct fuse_conn_info *conn,
|
||||
struct fuse_config *cfg) -> void * {
|
||||
#else
|
||||
#else // FUSE_USE_VERSION < 30
|
||||
auto fuse_base::init_impl(struct fuse_conn_info *conn) -> void * {
|
||||
#endif
|
||||
#endif // FUSE_USE_VERSION >= 30
|
||||
static constexpr const std::string_view function_name{
|
||||
static_cast<const char *>(__FUNCTION__),
|
||||
};
|
||||
|
||||
utils::file::change_to_process_directory();
|
||||
if (not console_enabled_) {
|
||||
if (not repertory::project_initialize()) {
|
||||
utils::error::raise_error(function_name,
|
||||
"failed to initialize repertory");
|
||||
event_system::instance().raise<unmount_requested>();
|
||||
}
|
||||
}
|
||||
|
||||
#if defined(__APPLE__)
|
||||
conn->want |= FUSE_CAP_VOL_RENAME;
|
||||
conn->want |= FUSE_CAP_XTIMES;
|
||||
#endif // __APPLE__
|
||||
#endif // defined(__APPLE__)
|
||||
|
||||
#if FUSE_USE_VERSION >= 30
|
||||
cfg->nullpath_ok = 0;
|
||||
cfg->hard_remove = 1;
|
||||
#endif
|
||||
#endif // FUSE_USE_VERSION >= 30
|
||||
|
||||
if (not utils::file::change_to_process_directory()) {
|
||||
utils::error::raise_error(function_name,
|
||||
"failed to change to process directory");
|
||||
event_system::instance().raise<unmount_requested>();
|
||||
return this;
|
||||
}
|
||||
|
||||
if (not console_enabled_ && not repertory::project_initialize()) {
|
||||
utils::error::raise_error(function_name, "failed to initialize repertory");
|
||||
event_system::instance().raise<unmount_requested>();
|
||||
}
|
||||
|
||||
return this;
|
||||
}
|
||||
@@ -427,8 +431,8 @@ auto fuse_base::mkdir_(const char *path, mode_t mode) -> int {
|
||||
};
|
||||
|
||||
return instance().execute_callback(
|
||||
function_name, path, [&](const std::string &api_path) -> api_error {
|
||||
return instance().mkdir_impl(api_path, mode);
|
||||
function_name, path, [&](std::string api_path) -> api_error {
|
||||
return instance().mkdir_impl(std::move(api_path), mode);
|
||||
});
|
||||
}
|
||||
|
||||
@@ -436,7 +440,7 @@ auto fuse_base::mount(std::vector<std::string> args) -> int {
|
||||
auto ret = parse_args(args);
|
||||
if (ret == 0) {
|
||||
std::vector<const char *> fuse_argv(args.size());
|
||||
for (std::size_t i = 0u; i < args.size(); i++) {
|
||||
for (std::size_t i = 0u; i < args.size(); ++i) {
|
||||
fuse_argv[i] = args[i].c_str();
|
||||
}
|
||||
|
||||
@@ -486,8 +490,8 @@ auto fuse_base::open_(const char *path, struct fuse_file_info *fi) -> int {
|
||||
};
|
||||
|
||||
return instance().execute_callback(
|
||||
function_name, path, [&](const std::string &api_path) -> api_error {
|
||||
return instance().open_impl(api_path, fi);
|
||||
function_name, path, [&](std::string api_path) -> api_error {
|
||||
return instance().open_impl(std::move(api_path), fi);
|
||||
});
|
||||
}
|
||||
|
||||
@@ -497,8 +501,8 @@ auto fuse_base::opendir_(const char *path, struct fuse_file_info *fi) -> int {
|
||||
};
|
||||
|
||||
return instance().execute_callback(
|
||||
function_name, path, [&](const std::string &api_path) -> api_error {
|
||||
return instance().opendir_impl(api_path, fi);
|
||||
function_name, path, [&](std::string api_path) -> api_error {
|
||||
return instance().opendir_impl(std::move(api_path), fi);
|
||||
});
|
||||
}
|
||||
|
||||
@@ -511,9 +515,9 @@ auto fuse_base::read_(const char *path, char *buffer, size_t read_size,
|
||||
std::size_t bytes_read{};
|
||||
const auto res = instance().execute_callback(
|
||||
function_name, path,
|
||||
[&](const std::string &api_path) -> api_error {
|
||||
return instance().read_impl(api_path, buffer, read_size, read_offset,
|
||||
fi, bytes_read);
|
||||
[&](std::string api_path) -> api_error {
|
||||
return instance().read_impl(std::move(api_path), buffer, read_size,
|
||||
read_offset, fi, bytes_read);
|
||||
},
|
||||
true);
|
||||
return (res == 0) ? static_cast<int>(bytes_read) : res;
|
||||
@@ -529,9 +533,9 @@ auto fuse_base::readdir_(const char *path, void *buf,
|
||||
};
|
||||
|
||||
return instance().execute_callback(
|
||||
function_name, path, [&](const std::string &api_path) -> api_error {
|
||||
return instance().readdir_impl(api_path, buf, fuse_fill_dir, offset, fi,
|
||||
flags);
|
||||
function_name, path, [&](std::string api_path) -> api_error {
|
||||
return instance().readdir_impl(std::move(api_path), buf, fuse_fill_dir,
|
||||
offset, fi, flags);
|
||||
});
|
||||
}
|
||||
#else
|
||||
@@ -543,9 +547,9 @@ auto fuse_base::readdir_(const char *path, void *buf,
|
||||
};
|
||||
|
||||
return instance().execute_callback(
|
||||
function_name, path, [&](const std::string &api_path) -> api_error {
|
||||
return instance().readdir_impl(api_path, buf, fuse_fill_dir, offset,
|
||||
fi);
|
||||
function_name, path, [&](std::string api_path) -> api_error {
|
||||
return instance().readdir_impl(std::move(api_path), buf, fuse_fill_dir,
|
||||
offset, fi);
|
||||
});
|
||||
}
|
||||
#endif
|
||||
@@ -556,8 +560,8 @@ auto fuse_base::release_(const char *path, struct fuse_file_info *fi) -> int {
|
||||
};
|
||||
|
||||
return instance().execute_callback(
|
||||
function_name, path, [&](const std::string &api_path) -> api_error {
|
||||
return instance().release_impl(api_path, fi);
|
||||
function_name, path, [&](std::string api_path) -> api_error {
|
||||
return instance().release_impl(std::move(api_path), fi);
|
||||
});
|
||||
}
|
||||
|
||||
@@ -568,8 +572,8 @@ auto fuse_base::releasedir_(const char *path,
|
||||
};
|
||||
|
||||
return instance().execute_callback(
|
||||
function_name, path, [&](const std::string &api_path) -> api_error {
|
||||
return instance().releasedir_impl(api_path, fi);
|
||||
function_name, path, [&](std::string api_path) -> api_error {
|
||||
return instance().releasedir_impl(std::move(api_path), fi);
|
||||
});
|
||||
}
|
||||
|
||||
@@ -582,9 +586,9 @@ auto fuse_base::rename_(const char *from, const char *to,
|
||||
|
||||
return instance().execute_callback(
|
||||
function_name, from, to,
|
||||
[&](const std::string &from_api_file,
|
||||
const std::string &to_api_path) -> api_error {
|
||||
return instance().rename_impl(from_api_file, to_api_path, flags);
|
||||
[&](std::string from_api_file, std::string to_api_path) -> api_error {
|
||||
return instance().rename_impl(std::move(from_api_file),
|
||||
std::move(to_api_path), flags);
|
||||
});
|
||||
}
|
||||
#else
|
||||
@@ -595,9 +599,9 @@ auto fuse_base::rename_(const char *from, const char *to) -> int {
|
||||
|
||||
return instance().execute_callback(
|
||||
function_name, from, to,
|
||||
[&](const std::string &from_api_file,
|
||||
const std::string &to_api_path) -> api_error {
|
||||
return instance().rename_impl(from_api_file, to_api_path);
|
||||
[&](std::string from_api_file, std::string to_api_path) -> api_error {
|
||||
return instance().rename_impl(std::move(from_api_file),
|
||||
std::move(to_api_path));
|
||||
});
|
||||
}
|
||||
#endif
|
||||
@@ -608,8 +612,8 @@ auto fuse_base::rmdir_(const char *path) -> int {
|
||||
};
|
||||
|
||||
return instance().execute_callback(
|
||||
function_name, path, [&](const std::string &api_path) -> api_error {
|
||||
return instance().rmdir_impl(api_path);
|
||||
function_name, path, [&](std::string api_path) -> api_error {
|
||||
return instance().rmdir_impl(std::move(api_path));
|
||||
});
|
||||
}
|
||||
|
||||
@@ -623,9 +627,9 @@ auto fuse_base::getxattr_(const char *path, const char *name, char *value,
|
||||
|
||||
int attribute_size = 0;
|
||||
const auto res = instance().execute_callback(
|
||||
function_name, path, [&](const std::string &api_path) -> api_error {
|
||||
return instance().getxattr_impl(api_path, name, value, size, position,
|
||||
attribute_size);
|
||||
function_name, path, [&](std::string api_path) -> api_error {
|
||||
return instance().getxattr_impl(std::move(api_path), name, value, size,
|
||||
position, attribute_size);
|
||||
});
|
||||
|
||||
return res == 0 ? attribute_size : res;
|
||||
@@ -639,8 +643,8 @@ auto fuse_base::getxattr_(const char *path, const char *name, char *value,
|
||||
|
||||
int attribute_size = 0;
|
||||
const auto res = instance().execute_callback(
|
||||
function_name, path, [&](const std::string &api_path) -> api_error {
|
||||
return instance().getxattr_impl(api_path, name, value, size,
|
||||
function_name, path, [&](std::string api_path) -> api_error {
|
||||
return instance().getxattr_impl(std::move(api_path), name, value, size,
|
||||
attribute_size);
|
||||
});
|
||||
|
||||
@@ -657,9 +661,9 @@ auto fuse_base::listxattr_(const char *path, char *buffer, size_t size) -> int {
|
||||
bool return_size = false;
|
||||
|
||||
const auto res = instance().execute_callback(
|
||||
function_name, path, [&](const std::string &api_path) -> api_error {
|
||||
return instance().listxattr_impl(api_path, buffer, size, required_size,
|
||||
return_size);
|
||||
function_name, path, [&](std::string api_path) -> api_error {
|
||||
return instance().listxattr_impl(std::move(api_path), buffer, size,
|
||||
required_size, return_size);
|
||||
});
|
||||
|
||||
return return_size ? required_size : res;
|
||||
@@ -676,14 +680,14 @@ void fuse_base::notify_fuse_args_parsed(const std::vector<std::string> &args) {
|
||||
|
||||
auto fuse_base::parse_args(std::vector<std::string> &args) -> int {
|
||||
auto force_no_console = false;
|
||||
for (std::size_t i = 1u; !force_no_console && (i < args.size()); i++) {
|
||||
for (std::size_t i = 1u; !force_no_console && (i < args.size()); ++i) {
|
||||
if (args[i] == "-nc") {
|
||||
force_no_console = true;
|
||||
}
|
||||
}
|
||||
utils::collection::remove_element(args, "-nc");
|
||||
|
||||
for (std::size_t i = 1u; i < args.size(); i++) {
|
||||
for (std::size_t i = 1u; i < args.size(); ++i) {
|
||||
if (args[i] == "-f") {
|
||||
console_enabled_ = not force_no_console;
|
||||
} else if (args[i].find("-o") == 0) {
|
||||
@@ -697,7 +701,7 @@ auto fuse_base::parse_args(std::vector<std::string> &args) -> int {
|
||||
}
|
||||
|
||||
const auto option_parts = utils::string::split(options, ',', true);
|
||||
for (const auto &option : option_parts) {
|
||||
for (auto &&option : option_parts) {
|
||||
if (option.find("gid") == 0) {
|
||||
const auto parts = utils::string::split(option, '=', true);
|
||||
if (parts.size() == 2u) {
|
||||
@@ -752,7 +756,7 @@ auto fuse_base::parse_args(std::vector<std::string> &args) -> int {
|
||||
}
|
||||
|
||||
void fuse_base::raise_fuse_event(std::string_view function_name,
|
||||
const std::string &api_path, int ret,
|
||||
std::string_view api_path, int ret,
|
||||
bool disable_logging) {
|
||||
if ((ret >= 0) && disable_logging) {
|
||||
return;
|
||||
@@ -766,7 +770,7 @@ void fuse_base::raise_fuse_event(std::string_view function_name,
|
||||
(config_.get_event_level() >= event_level::trace)) {
|
||||
std::string func{function_name};
|
||||
event_system::instance().raise<fuse_event>(
|
||||
utils::string::right_trim(func, '_'), api_path, ret);
|
||||
utils::string::right_trim(func, '_'), std::string{api_path}, ret);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -776,8 +780,8 @@ auto fuse_base::removexattr_(const char *path, const char *name) -> int {
|
||||
};
|
||||
|
||||
return instance().execute_callback(
|
||||
function_name, path, [&](const std::string &api_path) -> api_error {
|
||||
return instance().removexattr_impl(api_path, name);
|
||||
function_name, path, [&](std::string api_path) -> api_error {
|
||||
return instance().removexattr_impl(std::move(api_path), name);
|
||||
});
|
||||
}
|
||||
|
||||
@@ -789,9 +793,9 @@ auto fuse_base::setxattr_(const char *path, const char *name, const char *value,
|
||||
};
|
||||
|
||||
const auto res = instance().execute_callback(
|
||||
function_name, path, [&](const std::string &api_path) -> api_error {
|
||||
return instance().setxattr_impl(api_path, name, value, size, flags,
|
||||
position);
|
||||
function_name, path, [&](std::string api_path) -> api_error {
|
||||
return instance().setxattr_impl(std::move(api_path), name, value, size,
|
||||
flags, position);
|
||||
});
|
||||
if (res != 0) {
|
||||
errno = std::abs(res);
|
||||
@@ -807,8 +811,9 @@ auto fuse_base::setxattr_(const char *path, const char *name, const char *value,
|
||||
};
|
||||
|
||||
const auto res = instance().execute_callback(
|
||||
function_name, path, [&](const std::string &api_path) -> api_error {
|
||||
return instance().setxattr_impl(api_path, name, value, size, flags);
|
||||
function_name, path, [&](std::string api_path) -> api_error {
|
||||
return instance().setxattr_impl(std::move(api_path), name, value, size,
|
||||
flags);
|
||||
});
|
||||
if (res != 0) {
|
||||
errno = std::abs(res);
|
||||
@@ -832,8 +837,8 @@ auto fuse_base::setattr_x_(const char *path, struct setattr_x *attr) -> int {
|
||||
};
|
||||
|
||||
return instance().execute_callback(
|
||||
function_name, path, [&](const std::string &api_path) -> api_error {
|
||||
return instance().setattr_x_impl(api_path, attr);
|
||||
function_name, path, [&](std::string api_path) -> api_error {
|
||||
return instance().setattr_x_impl(std::move(api_path), attr);
|
||||
});
|
||||
}
|
||||
|
||||
@@ -844,8 +849,8 @@ auto fuse_base::setbkuptime_(const char *path,
|
||||
};
|
||||
|
||||
return instance().execute_callback(
|
||||
function_name, path, [&](const std::string &api_path) -> api_error {
|
||||
return instance().setbkuptime_impl(api_path, bkuptime);
|
||||
function_name, path, [&](std::string api_path) -> api_error {
|
||||
return instance().setbkuptime_impl(std::move(api_path), bkuptime);
|
||||
});
|
||||
}
|
||||
|
||||
@@ -856,8 +861,8 @@ auto fuse_base::setchgtime_(const char *path,
|
||||
};
|
||||
|
||||
return instance().execute_callback(
|
||||
function_name, path, [&](const std::string &api_path) -> api_error {
|
||||
return instance().setchgtime_impl(api_path, chgtime);
|
||||
function_name, path, [&](std::string api_path) -> api_error {
|
||||
return instance().setchgtime_impl(std::move(api_path), chgtime);
|
||||
});
|
||||
}
|
||||
|
||||
@@ -868,8 +873,8 @@ auto fuse_base::setcrtime_(const char *path,
|
||||
};
|
||||
|
||||
return instance().execute_callback(
|
||||
function_name, path, [&](const std::string &api_path) -> api_error {
|
||||
return instance().setcrtime_impl(api_path, crtime);
|
||||
function_name, path, [&](std::string api_path) -> api_error {
|
||||
return instance().setcrtime_impl(std::move(api_path), crtime);
|
||||
});
|
||||
}
|
||||
|
||||
@@ -879,8 +884,8 @@ auto fuse_base::setvolname_(const char *volname) -> int {
|
||||
};
|
||||
|
||||
return instance().execute_callback(
|
||||
function_name, volname, [&](const std::string &api_path) -> api_error {
|
||||
return instance().setvolname_impl(volname);
|
||||
function_name, volname, [&](std::string api_path) -> api_error {
|
||||
return instance().setvolname_impl(std::move(volname));
|
||||
});
|
||||
}
|
||||
|
||||
@@ -890,8 +895,8 @@ auto fuse_base::statfs_x_(const char *path, struct statfs *stbuf) -> int {
|
||||
};
|
||||
|
||||
return instance().execute_callback(
|
||||
function_name, path, [&](const std::string &api_path) -> api_error {
|
||||
return instance().statfs_x_impl(api_path, stbuf);
|
||||
function_name, path, [&](std::string api_path) -> api_error {
|
||||
return instance().statfs_x_impl(std::move(api_path), stbuf);
|
||||
});
|
||||
}
|
||||
#else // __APPLE__
|
||||
@@ -901,8 +906,8 @@ auto fuse_base::statfs_(const char *path, struct statvfs *stbuf) -> int {
|
||||
};
|
||||
|
||||
return instance().execute_callback(
|
||||
function_name, path, [&](const std::string &api_path) -> api_error {
|
||||
return instance().statfs_impl(api_path, stbuf);
|
||||
function_name, path, [&](std::string api_path) -> api_error {
|
||||
return instance().statfs_impl(std::move(api_path), stbuf);
|
||||
});
|
||||
}
|
||||
#endif // __APPLE__
|
||||
@@ -915,8 +920,8 @@ auto fuse_base::truncate_(const char *path, off_t size,
|
||||
};
|
||||
|
||||
return instance().execute_callback(
|
||||
function_name, path, [&](const std::string &api_path) -> api_error {
|
||||
return instance().truncate_impl(api_path, size, fi);
|
||||
function_name, path, [&](std::string api_path) -> api_error {
|
||||
return instance().truncate_impl(std::move(api_path), size, fi);
|
||||
});
|
||||
}
|
||||
#else
|
||||
@@ -926,8 +931,8 @@ auto fuse_base::truncate_(const char *path, off_t size) -> int {
|
||||
};
|
||||
|
||||
return instance().execute_callback(
|
||||
function_name, path, [&](const std::string &api_path) -> api_error {
|
||||
return instance().truncate_impl(api_path, size);
|
||||
function_name, path, [&](std::string api_path) -> api_error {
|
||||
return instance().truncate_impl(std::move(api_path), size);
|
||||
});
|
||||
}
|
||||
#endif
|
||||
@@ -938,8 +943,8 @@ auto fuse_base::unlink_(const char *path) -> int {
|
||||
};
|
||||
|
||||
return instance().execute_callback(
|
||||
function_name, path, [&](const std::string &api_path) -> api_error {
|
||||
return instance().unlink_impl(api_path);
|
||||
function_name, path, [&](std::string api_path) -> api_error {
|
||||
return instance().unlink_impl(std::move(api_path));
|
||||
});
|
||||
}
|
||||
|
||||
@@ -965,8 +970,8 @@ auto fuse_base::utimens_(const char *path, const struct timespec tv[2],
|
||||
};
|
||||
|
||||
return instance().execute_callback(
|
||||
function_name, path, [&](const std::string &api_path) -> api_error {
|
||||
return instance().utimens_impl(api_path, tv, fi);
|
||||
function_name, path, [&](std::string api_path) -> api_error {
|
||||
return instance().utimens_impl(std::move(api_path), tv, fi);
|
||||
});
|
||||
}
|
||||
#else
|
||||
@@ -976,8 +981,8 @@ auto fuse_base::utimens_(const char *path, const struct timespec tv[2]) -> int {
|
||||
};
|
||||
|
||||
return instance().execute_callback(
|
||||
function_name, path, [&](const std::string &api_path) -> api_error {
|
||||
return instance().utimens_impl(api_path, tv);
|
||||
function_name, path, [&](std::string api_path) -> api_error {
|
||||
return instance().utimens_impl(std::move(api_path), tv);
|
||||
});
|
||||
}
|
||||
#endif
|
||||
@@ -992,9 +997,9 @@ auto fuse_base::write_(const char *path, const char *buffer, size_t write_size,
|
||||
|
||||
const auto res = instance().execute_callback(
|
||||
function_name, path,
|
||||
[&](const std::string &api_path) -> api_error {
|
||||
return instance().write_impl(api_path, buffer, write_size, write_offset,
|
||||
fi, bytes_written);
|
||||
[&](std::string api_path) -> api_error {
|
||||
return instance().write_impl(std::move(api_path), buffer, write_size,
|
||||
write_offset, fi, bytes_written);
|
||||
},
|
||||
true);
|
||||
return (res == 0) ? static_cast<int>(bytes_written) : res;
|
||||
|
||||
@@ -163,7 +163,7 @@ auto fuse_drive::create_impl(std::string api_path, mode_t mode,
|
||||
{
|
||||
std::shared_ptr<i_open_file> open_file;
|
||||
if (is_create_op) {
|
||||
const auto now = utils::time::get_file_time_now();
|
||||
const auto now = utils::time::get_time_now();
|
||||
#if defined(__APPLE__)
|
||||
const auto osx_flags = static_cast<std::uint32_t>(file_info->flags);
|
||||
#else // !defined(__APPLE__)
|
||||
@@ -614,7 +614,7 @@ auto fuse_drive::mkdir_impl(std::string api_path, mode_t mode) -> api_error {
|
||||
return res;
|
||||
}
|
||||
|
||||
const auto now = utils::time::get_file_time_now();
|
||||
const auto now = utils::time::get_time_now();
|
||||
auto meta = create_meta_attributes(now, FILE_ATTRIBUTE_DIRECTORY, now, now,
|
||||
true, get_effective_gid(), "", mode, now,
|
||||
0U, 0U, 0U, "", get_effective_uid(), now);
|
||||
@@ -915,7 +915,7 @@ auto fuse_drive::listxattr_impl(std::string api_path, char *buffer, size_t size,
|
||||
|
||||
api_meta_map meta;
|
||||
if ((res = provider_.get_item_meta(api_path, meta)) == api_error::success) {
|
||||
for (const auto &meta_item : meta) {
|
||||
for (auto &&meta_item : meta) {
|
||||
if (utils::collection::excludes(META_USED_NAMES, meta_item.first)) {
|
||||
auto attribute_name = meta_item.first;
|
||||
#if defined(__APPLE__)
|
||||
@@ -1155,8 +1155,8 @@ auto fuse_drive::setbkuptime_impl(
|
||||
std::string api_path, const struct timespec *bkuptime) -> api_error {
|
||||
return check_and_perform(
|
||||
api_path, X_OK, [&](api_meta_map &meta) -> api_error {
|
||||
const auto nanos =
|
||||
bkuptime->tv_nsec + (bkuptime->tv_nsec * NANOS_PER_SECOND);
|
||||
const auto nanos = bkuptime->tv_nsec +
|
||||
(bkuptime->tv_nsec * utils::time::NANOS_PER_SECOND);
|
||||
return provider_.set_item_meta(api_path, META_BACKUP,
|
||||
std::to_string(nanos));
|
||||
});
|
||||
@@ -1166,8 +1166,8 @@ auto fuse_drive::setchgtime_impl(std::string api_path,
|
||||
const struct timespec *chgtime) -> api_error {
|
||||
return check_and_perform(
|
||||
api_path, X_OK, [&](api_meta_map &meta) -> api_error {
|
||||
const auto nanos =
|
||||
chgtime->tv_nsec + (chgtime->tv_nsec * NANOS_PER_SECOND);
|
||||
const auto nanos = chgtime->tv_nsec +
|
||||
(chgtime->tv_nsec * utils::time::NANOS_PER_SECOND);
|
||||
return provider_.set_item_meta(api_path, META_CHANGED,
|
||||
std::to_string(nanos));
|
||||
});
|
||||
@@ -1178,7 +1178,7 @@ auto fuse_drive::setcrtime_impl(std::string api_path,
|
||||
return check_and_perform(
|
||||
api_path, X_OK, [&](api_meta_map &meta) -> api_error {
|
||||
const auto nanos =
|
||||
crtime->tv_nsec + (crtime->tv_nsec * NANOS_PER_SECOND);
|
||||
crtime->tv_nsec + (crtime->tv_nsec * utils::time::NANOS_PER_SECOND);
|
||||
return provider_.set_item_meta(api_path, META_CREATION,
|
||||
std::to_string(nanos));
|
||||
});
|
||||
@@ -1310,19 +1310,24 @@ auto fuse_drive::utimens_impl(std::string api_path,
|
||||
}
|
||||
|
||||
meta.clear();
|
||||
if ((tv == nullptr) || (tv[0U].tv_nsec == UTIME_NOW)) {
|
||||
meta[META_ACCESSED] = std::to_string(utils::time::get_file_time_now());
|
||||
} else if (tv[0U].tv_nsec != UTIME_OMIT) {
|
||||
const auto val = tv[0U].tv_nsec + (tv[0U].tv_sec * NANOS_PER_SECOND);
|
||||
meta[META_ACCESSED] = std::to_string(val);
|
||||
}
|
||||
|
||||
if ((tv == nullptr) || (tv[1U].tv_nsec == UTIME_NOW)) {
|
||||
meta[META_MODIFIED] = std::to_string(utils::time::get_file_time_now());
|
||||
} else if (tv[1U].tv_nsec != UTIME_OMIT) {
|
||||
const auto val = tv[1U].tv_nsec + (tv[1U].tv_sec * NANOS_PER_SECOND);
|
||||
meta[META_MODIFIED] = std::to_string(val);
|
||||
}
|
||||
const auto process_timespec = [&meta, &tv](const auto &src,
|
||||
std::string attr) {
|
||||
if ((tv == nullptr) || (src.tv_nsec == UTIME_NOW)) {
|
||||
meta[attr] = std::to_string(utils::time::get_time_now());
|
||||
return;
|
||||
}
|
||||
|
||||
if (src.tv_nsec != UTIME_OMIT) {
|
||||
meta[attr] = std::to_string(
|
||||
src.tv_nsec +
|
||||
(src.tv_sec * static_cast<std::decay_t<decltype(src.tv_sec)>>(
|
||||
utils::time::NANOS_PER_SECOND)));
|
||||
}
|
||||
};
|
||||
|
||||
process_timespec(tv[0U], META_ACCESSED);
|
||||
process_timespec(tv[1U], META_MODIFIED);
|
||||
|
||||
if (not meta.empty()) {
|
||||
return provider_.set_item_meta(api_path, meta);
|
||||
@@ -1369,8 +1374,7 @@ void fuse_drive::update_accessed_time(const std::string &api_path) {
|
||||
|
||||
if (atime_enabled_) {
|
||||
auto res = provider_.set_item_meta(
|
||||
api_path, META_ACCESSED,
|
||||
std::to_string(utils::time::get_file_time_now()));
|
||||
api_path, META_ACCESSED, std::to_string(utils::time::get_time_now()));
|
||||
if (res != api_error::success) {
|
||||
utils::error::raise_api_path_error(function_name, api_path, res,
|
||||
"failed to set accessed time");
|
||||
|
||||
@@ -26,6 +26,7 @@
|
||||
#include "platform/platform.hpp"
|
||||
#include "providers/i_provider.hpp"
|
||||
#include "utils/common.hpp"
|
||||
#include "utils/time.hpp"
|
||||
|
||||
namespace repertory {
|
||||
auto fuse_drive_base::access_impl(std::string api_path, int mask) -> api_error {
|
||||
@@ -165,9 +166,9 @@ auto fuse_drive_base::check_parent_access(const std::string &api_path,
|
||||
// Ignore root
|
||||
if (api_path != "/") {
|
||||
if ((mask & X_OK) == X_OK) {
|
||||
for (auto parent = utils::path::get_parent_directory(api_path);
|
||||
for (auto parent = utils::path::get_parent_path(api_path);
|
||||
(ret == api_error::success) && not parent.empty();
|
||||
parent = utils::path::get_parent_directory(parent)) {
|
||||
parent = utils::path::get_parent_path(parent)) {
|
||||
if (((ret = check_access(parent, X_OK)) == api_error::success) &&
|
||||
(parent == "/")) {
|
||||
break;
|
||||
@@ -178,7 +179,7 @@ auto fuse_drive_base::check_parent_access(const std::string &api_path,
|
||||
if (ret == api_error::success) {
|
||||
mask &= (~X_OK);
|
||||
if (mask != 0) {
|
||||
ret = check_access(utils::path::get_parent_directory(api_path), mask);
|
||||
ret = check_access(utils::path::get_parent_path(api_path), mask);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -233,9 +234,9 @@ auto fuse_drive_base::get_mode_from_meta(const api_meta_map &meta) -> mode_t {
|
||||
void fuse_drive_base::get_timespec_from_meta(const api_meta_map &meta,
|
||||
const std::string &name,
|
||||
struct timespec &ts) {
|
||||
const auto meta_time = utils::string::to_int64(meta.at(name));
|
||||
ts.tv_nsec = meta_time % NANOS_PER_SECOND;
|
||||
ts.tv_sec = meta_time / NANOS_PER_SECOND;
|
||||
auto meta_time = utils::string::to_uint64(meta.at(name));
|
||||
ts.tv_nsec = meta_time % utils::time::NANOS_PER_SECOND;
|
||||
ts.tv_sec = meta_time / utils::time::NANOS_PER_SECOND;
|
||||
}
|
||||
|
||||
auto fuse_drive_base::get_uid_from_meta(const api_meta_map &meta) -> uid_t {
|
||||
@@ -299,7 +300,7 @@ void fuse_drive_base::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) {
|
||||
memset(st, 0, sizeof(struct stat));
|
||||
std::memset(st, 0, sizeof(struct stat));
|
||||
st->st_nlink = static_cast<nlink_t>(
|
||||
directory ? 2 + (size_or_count == 0U
|
||||
? provider.get_directory_item_count(api_path)
|
||||
@@ -341,9 +342,9 @@ void fuse_drive_base::populate_stat(const std::string &api_path,
|
||||
void fuse_drive_base::set_timespec_from_meta(const api_meta_map &meta,
|
||||
const std::string &name,
|
||||
struct timespec &ts) {
|
||||
const auto meta_time = utils::string::to_int64(meta.at(name));
|
||||
ts.tv_nsec = meta_time % NANOS_PER_SECOND;
|
||||
ts.tv_sec = meta_time / NANOS_PER_SECOND;
|
||||
auto meta_time = utils::string::to_uint64(meta.at(name));
|
||||
ts.tv_nsec = meta_time % utils::time::NANOS_PER_SECOND;
|
||||
ts.tv_sec = meta_time / utils::time::NANOS_PER_SECOND;
|
||||
}
|
||||
} // namespace repertory
|
||||
|
||||
|
||||
@@ -36,6 +36,7 @@
|
||||
#include "utils/error_utils.hpp"
|
||||
#include "utils/file_utils.hpp"
|
||||
#include "utils/path.hpp"
|
||||
#include "utils/time.hpp"
|
||||
#include "utils/utils.hpp"
|
||||
|
||||
namespace repertory::remote_fuse {
|
||||
@@ -142,16 +143,17 @@ api_error remote_fuse_drive::fsetattr_x_impl(std::string api_path,
|
||||
attributes.uid = attr->uid;
|
||||
attributes.gid = attr->gid;
|
||||
attributes.size = attr->size;
|
||||
attributes.acctime =
|
||||
((attr->acctime.tv_sec * NANOS_PER_SECOND) + attr->acctime.tv_nsec);
|
||||
attributes.modtime =
|
||||
((attr->modtime.tv_sec * NANOS_PER_SECOND) + attr->modtime.tv_nsec);
|
||||
attributes.crtime =
|
||||
((attr->crtime.tv_sec * NANOS_PER_SECOND) + attr->crtime.tv_nsec);
|
||||
attributes.chgtime =
|
||||
((attr->chgtime.tv_sec * NANOS_PER_SECOND) + attr->chgtime.tv_nsec);
|
||||
attributes.acctime = ((attr->acctime.tv_sec * utils::time::NANOS_PER_SECOND) +
|
||||
attr->acctime.tv_nsec);
|
||||
attributes.modtime = ((attr->modtime.tv_sec * utils::time::NANOS_PER_SECOND) +
|
||||
attr->modtime.tv_nsec);
|
||||
attributes.crtime = ((attr->crtime.tv_sec * utils::time::NANOS_PER_SECOND) +
|
||||
attr->crtime.tv_nsec);
|
||||
attributes.chgtime = ((attr->chgtime.tv_sec * utils::time::NANOS_PER_SECOND) +
|
||||
attr->chgtime.tv_nsec);
|
||||
attributes.bkuptime =
|
||||
((attr->bkuptime.tv_sec * NANOS_PER_SECOND) + attr->bkuptime.tv_nsec);
|
||||
((attr->bkuptime.tv_sec * utils::time::NANOS_PER_SECOND) +
|
||||
attr->bkuptime.tv_nsec);
|
||||
attributes.flags = attr->flags;
|
||||
return utils::to_api_error(remote_instance_->fuse_fsetattr_x(
|
||||
api_path.c_str(), attributes, f_info->fh));
|
||||
@@ -208,10 +210,11 @@ api_error remote_fuse_drive::getxtimes_impl(std::string api_path,
|
||||
api_path.c_str(), repertory_bkuptime, repertory_crtime);
|
||||
if (res == 0) {
|
||||
bkuptime->tv_nsec =
|
||||
static_cast<long>(repertory_bkuptime % NANOS_PER_SECOND);
|
||||
bkuptime->tv_sec = repertory_bkuptime / NANOS_PER_SECOND;
|
||||
crtime->tv_nsec = static_cast<long>(repertory_crtime % NANOS_PER_SECOND);
|
||||
crtime->tv_sec = repertory_crtime / NANOS_PER_SECOND;
|
||||
static_cast<long>(repertory_bkuptime % utils::time::NANOS_PER_SECOND);
|
||||
bkuptime->tv_sec = repertory_bkuptime / utils::time::NANOS_PER_SECOND;
|
||||
crtime->tv_nsec =
|
||||
static_cast<long>(repertory_crtime % utils::time::NANOS_PER_SECOND);
|
||||
crtime->tv_sec = repertory_crtime / utils::time::NANOS_PER_SECOND;
|
||||
}
|
||||
|
||||
return utils::to_api_error(res);
|
||||
@@ -296,42 +299,51 @@ auto remote_fuse_drive::opendir_impl(
|
||||
|
||||
void remote_fuse_drive::populate_stat(const remote::stat &r_stat,
|
||||
bool directory, struct stat &unix_st) {
|
||||
memset(&unix_st, 0, sizeof(struct stat));
|
||||
std::memset(&unix_st, 0, sizeof(struct stat));
|
||||
|
||||
#if defined(__APPLE__)
|
||||
unix_st.st_blksize = 0;
|
||||
|
||||
unix_st.st_atimespec.tv_nsec = r_stat.st_atimespec % NANOS_PER_SECOND;
|
||||
unix_st.st_atimespec.tv_sec = r_stat.st_atimespec / NANOS_PER_SECOND;
|
||||
unix_st.st_atimespec.tv_nsec =
|
||||
r_stat.st_atimespec % utils::time::NANOS_PER_SECOND;
|
||||
unix_st.st_atimespec.tv_sec =
|
||||
r_stat.st_atimespec / utils::time::NANOS_PER_SECOND;
|
||||
|
||||
unix_st.st_birthtimespec.tv_nsec = r_stat.st_birthtimespec % NANOS_PER_SECOND;
|
||||
unix_st.st_birthtimespec.tv_sec = r_stat.st_birthtimespec / NANOS_PER_SECOND;
|
||||
unix_st.st_birthtimespec.tv_nsec =
|
||||
r_stat.st_birthtimespec % utils::time::NANOS_PER_SECOND;
|
||||
unix_st.st_birthtimespec.tv_sec =
|
||||
r_stat.st_birthtimespec / utils::time::NANOS_PER_SECOND;
|
||||
|
||||
unix_st.st_ctimespec.tv_nsec = r_stat.st_ctimespec % NANOS_PER_SECOND;
|
||||
unix_st.st_ctimespec.tv_sec = r_stat.st_ctimespec / NANOS_PER_SECOND;
|
||||
unix_st.st_ctimespec.tv_nsec =
|
||||
r_stat.st_ctimespec % utils::time::NANOS_PER_SECOND;
|
||||
unix_st.st_ctimespec.tv_sec =
|
||||
r_stat.st_ctimespec / utils::time::NANOS_PER_SECOND;
|
||||
|
||||
unix_st.st_mtimespec.tv_nsec = r_stat.st_mtimespec % NANOS_PER_SECOND;
|
||||
unix_st.st_mtimespec.tv_sec = r_stat.st_mtimespec / NANOS_PER_SECOND;
|
||||
unix_st.st_mtimespec.tv_nsec =
|
||||
r_stat.st_mtimespec % utils::time::NANOS_PER_SECOND;
|
||||
unix_st.st_mtimespec.tv_sec =
|
||||
r_stat.st_mtimespec / utils::time::NANOS_PER_SECOND;
|
||||
|
||||
unix_st.st_flags = r_stat.st_flags;
|
||||
#else
|
||||
#else // !defined(__APPLE__)
|
||||
unix_st.st_blksize = 4096;
|
||||
|
||||
unix_st.st_atim.tv_nsec =
|
||||
static_cast<suseconds_t>(r_stat.st_atimespec % NANOS_PER_SECOND);
|
||||
unix_st.st_atim.tv_sec =
|
||||
static_cast<suseconds_t>(r_stat.st_atimespec / NANOS_PER_SECOND);
|
||||
unix_st.st_atim.tv_nsec = static_cast<suseconds_t>(
|
||||
r_stat.st_atimespec % utils::time::NANOS_PER_SECOND);
|
||||
unix_st.st_atim.tv_sec = static_cast<suseconds_t>(
|
||||
r_stat.st_atimespec / utils::time::NANOS_PER_SECOND);
|
||||
|
||||
unix_st.st_ctim.tv_nsec =
|
||||
static_cast<suseconds_t>(r_stat.st_ctimespec % NANOS_PER_SECOND);
|
||||
unix_st.st_ctim.tv_sec =
|
||||
static_cast<suseconds_t>(r_stat.st_ctimespec / NANOS_PER_SECOND);
|
||||
unix_st.st_ctim.tv_nsec = static_cast<suseconds_t>(
|
||||
r_stat.st_ctimespec % utils::time::NANOS_PER_SECOND);
|
||||
unix_st.st_ctim.tv_sec = static_cast<suseconds_t>(
|
||||
r_stat.st_ctimespec / utils::time::NANOS_PER_SECOND);
|
||||
|
||||
unix_st.st_mtim.tv_nsec = static_cast<suseconds_t>(
|
||||
r_stat.st_mtimespec % utils::time::NANOS_PER_SECOND);
|
||||
unix_st.st_mtim.tv_sec = static_cast<suseconds_t>(
|
||||
r_stat.st_mtimespec / utils::time::NANOS_PER_SECOND);
|
||||
#endif // defined(__APPLE__)
|
||||
|
||||
unix_st.st_mtim.tv_nsec =
|
||||
static_cast<suseconds_t>(r_stat.st_mtimespec % NANOS_PER_SECOND);
|
||||
unix_st.st_mtim.tv_sec =
|
||||
static_cast<suseconds_t>(r_stat.st_mtimespec / NANOS_PER_SECOND);
|
||||
#endif
|
||||
if (not directory) {
|
||||
const auto block_size_stat = static_cast<std::uint64_t>(512U);
|
||||
const auto block_size = static_cast<std::uint64_t>(4096U);
|
||||
@@ -440,16 +452,17 @@ api_error remote_fuse_drive::setattr_x_impl(std::string api_path,
|
||||
attributes.uid = attr->uid;
|
||||
attributes.gid = attr->gid;
|
||||
attributes.size = attr->size;
|
||||
attributes.acctime =
|
||||
((attr->acctime.tv_sec * NANOS_PER_SECOND) + attr->acctime.tv_nsec);
|
||||
attributes.modtime =
|
||||
((attr->modtime.tv_sec * NANOS_PER_SECOND) + attr->modtime.tv_nsec);
|
||||
attributes.crtime =
|
||||
((attr->crtime.tv_sec * NANOS_PER_SECOND) + attr->crtime.tv_nsec);
|
||||
attributes.chgtime =
|
||||
((attr->chgtime.tv_sec * NANOS_PER_SECOND) + attr->chgtime.tv_nsec);
|
||||
attributes.acctime = ((attr->acctime.tv_sec * utils::time::NANOS_PER_SECOND) +
|
||||
attr->acctime.tv_nsec);
|
||||
attributes.modtime = ((attr->modtime.tv_sec * utils::time::NANOS_PER_SECOND) +
|
||||
attr->modtime.tv_nsec);
|
||||
attributes.crtime = ((attr->crtime.tv_sec * utils::time::NANOS_PER_SECOND) +
|
||||
attr->crtime.tv_nsec);
|
||||
attributes.chgtime = ((attr->chgtime.tv_sec * utils::time::NANOS_PER_SECOND) +
|
||||
attr->chgtime.tv_nsec);
|
||||
attributes.bkuptime =
|
||||
((attr->bkuptime.tv_sec * NANOS_PER_SECOND) + attr->bkuptime.tv_nsec);
|
||||
((attr->bkuptime.tv_sec * utils::time::NANOS_PER_SECOND) +
|
||||
attr->bkuptime.tv_nsec);
|
||||
attributes.flags = attr->flags;
|
||||
return utils::to_api_error(
|
||||
remote_instance_->fuse_setattr_x(api_path.c_str(), attributes));
|
||||
@@ -458,7 +471,7 @@ api_error remote_fuse_drive::setattr_x_impl(std::string api_path,
|
||||
api_error remote_fuse_drive::setbkuptime_impl(std::string api_path,
|
||||
const struct timespec *bkuptime) {
|
||||
remote::file_time repertory_bkuptime =
|
||||
((bkuptime->tv_sec * NANOS_PER_SECOND) + bkuptime->tv_nsec);
|
||||
((bkuptime->tv_sec * utils::time::NANOS_PER_SECOND) + bkuptime->tv_nsec);
|
||||
return utils::to_api_error(
|
||||
remote_instance_->fuse_setbkuptime(api_path.c_str(), repertory_bkuptime));
|
||||
}
|
||||
@@ -466,7 +479,7 @@ api_error remote_fuse_drive::setbkuptime_impl(std::string api_path,
|
||||
api_error remote_fuse_drive::setchgtime_impl(std::string api_path,
|
||||
const struct timespec *chgtime) {
|
||||
remote::file_time repertory_chgtime =
|
||||
((chgtime->tv_sec * NANOS_PER_SECOND) + chgtime->tv_nsec);
|
||||
((chgtime->tv_sec * utils::time::NANOS_PER_SECOND) + chgtime->tv_nsec);
|
||||
return utils::to_api_error(
|
||||
remote_instance_->fuse_setchgtime(api_path.c_str(), repertory_chgtime));
|
||||
}
|
||||
@@ -474,7 +487,7 @@ api_error remote_fuse_drive::setchgtime_impl(std::string api_path,
|
||||
api_error remote_fuse_drive::setcrtime_impl(std::string api_path,
|
||||
const struct timespec *crtime) {
|
||||
remote::file_time repertory_crtime =
|
||||
((crtime->tv_sec * NANOS_PER_SECOND) + crtime->tv_nsec);
|
||||
((crtime->tv_sec * utils::time::NANOS_PER_SECOND) + crtime->tv_nsec);
|
||||
return utils::to_api_error(
|
||||
remote_instance_->fuse_setcrtime(api_path.c_str(), repertory_crtime));
|
||||
}
|
||||
@@ -555,10 +568,14 @@ auto remote_fuse_drive::utimens_impl(std::string api_path,
|
||||
#endif
|
||||
remote::file_time rtv[2U] = {0};
|
||||
if (tv != nullptr) {
|
||||
rtv[0U] = static_cast<remote::file_time>(
|
||||
tv[0U].tv_nsec + (tv[0U].tv_sec * NANOS_PER_SECOND));
|
||||
rtv[1U] = static_cast<remote::file_time>(
|
||||
tv[1U].tv_nsec + (tv[1U].tv_sec * NANOS_PER_SECOND));
|
||||
const auto update_timespec = [](auto &dst, const auto &src) {
|
||||
dst = static_cast<remote::file_time>(
|
||||
src.tv_nsec +
|
||||
(src.tv_sec * static_cast<std::decay_t<decltype(src.tv_sec)>>(
|
||||
utils::time::NANOS_PER_SECOND)));
|
||||
};
|
||||
update_timespec(rtv[0U], tv[0U]);
|
||||
update_timespec(rtv[1U], tv[1U]);
|
||||
}
|
||||
|
||||
return utils::to_api_error(remote_instance_->fuse_utimens(
|
||||
|
||||
@@ -93,9 +93,10 @@ auto remote_server::populate_file_info(const std::string &api_path,
|
||||
auto error = drive_.get_item_meta(api_path, META_ATTRIBUTES, meta_attributes);
|
||||
if (error == api_error::success) {
|
||||
if (meta_attributes.empty()) {
|
||||
meta_attributes = utils::file::is_directory(construct_path(api_path))
|
||||
? std::to_string(FILE_ATTRIBUTE_DIRECTORY)
|
||||
: std::to_string(FILE_ATTRIBUTE_NORMAL);
|
||||
meta_attributes =
|
||||
utils::file::directory(construct_path(api_path)).exists()
|
||||
? std::to_string(FILE_ATTRIBUTE_DIRECTORY)
|
||||
: std::to_string(FILE_ATTRIBUTE_NORMAL);
|
||||
drive_.set_item_meta(api_path, META_ATTRIBUTES, meta_attributes);
|
||||
}
|
||||
const auto attributes = utils::string::to_uint32(meta_attributes);
|
||||
@@ -124,18 +125,18 @@ void remote_server::populate_file_info(const std::string &api_path,
|
||||
file_info.AllocationSize =
|
||||
utils::divide_with_ceiling(file_size, WINFSP_ALLOCATION_UNIT) *
|
||||
WINFSP_ALLOCATION_UNIT;
|
||||
file_info.ChangeTime = utils::unix_time_to_windows_time(
|
||||
file_info.ChangeTime = utils::time::unix_time_to_windows_time(
|
||||
utils::string::to_uint64(empty_as_zero(meta[META_MODIFIED])));
|
||||
file_info.CreationTime = utils::unix_time_to_windows_time(
|
||||
file_info.CreationTime = utils::time::unix_time_to_windows_time(
|
||||
utils::string::to_uint64(empty_as_zero(meta[META_CREATION])));
|
||||
file_info.EaSize = 0;
|
||||
file_info.FileAttributes = attributes;
|
||||
file_info.FileSize = file_size;
|
||||
file_info.HardLinks = 0;
|
||||
file_info.IndexNumber = 0;
|
||||
file_info.LastAccessTime = utils::unix_time_to_windows_time(
|
||||
file_info.LastAccessTime = utils::time::unix_time_to_windows_time(
|
||||
utils::string::to_uint64(empty_as_zero(meta[META_ACCESSED])));
|
||||
file_info.LastWriteTime = utils::unix_time_to_windows_time(
|
||||
file_info.LastWriteTime = utils::time::unix_time_to_windows_time(
|
||||
utils::string::to_uint64(empty_as_zero(meta[META_WRITTEN])));
|
||||
if (meta[META_WRITTEN].empty() || (meta[META_WRITTEN] == "0") ||
|
||||
(meta[META_WRITTEN] == "116444736000000000")) {
|
||||
@@ -147,30 +148,45 @@ void remote_server::populate_file_info(const std::string &api_path,
|
||||
|
||||
void remote_server::populate_stat(const struct stat64 &unix_st,
|
||||
remote::stat &r_stat) {
|
||||
memset(&r_stat, 0, sizeof(r_stat));
|
||||
r_stat = {};
|
||||
|
||||
#if defined(__APPLE__)
|
||||
r_stat.st_flags = unix_st.st_flags;
|
||||
|
||||
r_stat.st_atimespec = unix_st.st_atimespec.tv_nsec +
|
||||
(unix_st.st_atimespec.tv_sec * NANOS_PER_SECOND);
|
||||
r_stat.st_atimespec =
|
||||
unix_st.st_atimespec.tv_nsec +
|
||||
(unix_st.st_atimespec.tv_sec * utils::time::NANOS_PER_SECOND);
|
||||
r_stat.st_birthtimespec =
|
||||
unix_st.st_birthtimespec.tv_nsec +
|
||||
(unix_st.st_birthtimespec.tv_sec * NANOS_PER_SECOND);
|
||||
r_stat.st_ctimespec = unix_st.st_ctimespec.tv_nsec +
|
||||
(unix_st.st_ctimespec.tv_sec * NANOS_PER_SECOND);
|
||||
r_stat.st_mtimespec = unix_st.st_mtimespec.tv_nsec +
|
||||
(unix_st.st_mtimespec.tv_sec * NANOS_PER_SECOND);
|
||||
(unix_st.st_birthtimespec.tv_sec * utils::time::NANOS_PER_SECOND);
|
||||
r_stat.st_ctimespec =
|
||||
unix_st.st_ctimespec.tv_nsec +
|
||||
(unix_st.st_ctimespec.tv_sec * utils::time::NANOS_PER_SECOND);
|
||||
r_stat.st_mtimespec =
|
||||
unix_st.st_mtimespec.tv_nsec +
|
||||
(unix_st.st_mtimespec.tv_sec * utils::time::NANOS_PER_SECOND);
|
||||
#else // !defined(__APPLE__)
|
||||
r_stat.st_flags = 0;
|
||||
|
||||
r_stat.st_atimespec = static_cast<remote::file_time>(
|
||||
unix_st.st_atim.tv_nsec + (unix_st.st_atim.tv_sec * NANOS_PER_SECOND));
|
||||
r_stat.st_birthtimespec = static_cast<remote::file_time>(
|
||||
unix_st.st_ctim.tv_nsec + (unix_st.st_ctim.tv_sec * NANOS_PER_SECOND));
|
||||
r_stat.st_ctimespec = static_cast<remote::file_time>(
|
||||
unix_st.st_ctim.tv_nsec + (unix_st.st_ctim.tv_sec * NANOS_PER_SECOND));
|
||||
r_stat.st_mtimespec = static_cast<remote::file_time>(
|
||||
unix_st.st_mtim.tv_nsec + (unix_st.st_mtim.tv_sec * NANOS_PER_SECOND));
|
||||
r_stat.st_atimespec =
|
||||
static_cast<remote::file_time>(unix_st.st_atim.tv_nsec) +
|
||||
(static_cast<remote::file_time>(unix_st.st_atim.tv_sec) *
|
||||
utils::time::NANOS_PER_SECOND);
|
||||
|
||||
r_stat.st_birthtimespec =
|
||||
static_cast<remote::file_time>(unix_st.st_ctim.tv_nsec) +
|
||||
(static_cast<remote::file_time>(unix_st.st_ctim.tv_sec) *
|
||||
utils::time::NANOS_PER_SECOND);
|
||||
|
||||
r_stat.st_ctimespec =
|
||||
static_cast<remote::file_time>(unix_st.st_ctim.tv_nsec) +
|
||||
(static_cast<remote::file_time>(unix_st.st_ctim.tv_sec) *
|
||||
utils::time::NANOS_PER_SECOND);
|
||||
|
||||
r_stat.st_mtimespec =
|
||||
static_cast<remote::file_time>(unix_st.st_mtim.tv_nsec) +
|
||||
(static_cast<remote::file_time>(unix_st.st_mtim.tv_sec) *
|
||||
utils::time::NANOS_PER_SECOND);
|
||||
#endif // defined(__APPLE__)
|
||||
r_stat.st_blksize = static_cast<remote::block_size>(unix_st.st_blksize);
|
||||
r_stat.st_blocks = static_cast<remote::block_count>(unix_st.st_blocks);
|
||||
@@ -319,12 +335,13 @@ auto remote_server::fuse_fgetattr(
|
||||
static_cast<const char *>(__FUNCTION__),
|
||||
};
|
||||
|
||||
r_stat = {};
|
||||
|
||||
const auto file_path = construct_path(path);
|
||||
memset(&r_stat, 0, sizeof(remote::stat));
|
||||
|
||||
auto res = has_open_info(static_cast<native_handle>(handle), EBADF);
|
||||
if (res == 0) {
|
||||
directory = utils::file::is_directory(file_path);
|
||||
directory = utils::file::directory(file_path).exists();
|
||||
struct stat64 unix_st {};
|
||||
res = fstat64(static_cast<native_handle>(handle), &unix_st);
|
||||
if (res == 0) {
|
||||
@@ -405,16 +422,18 @@ auto remote_server::fuse_fsetattr_x(
|
||||
if (SETATTR_WANTS_MODTIME(&attr)) {
|
||||
struct timeval val[2];
|
||||
if (SETATTR_WANTS_ACCTIME(&attr)) {
|
||||
val[0U].tv_sec = static_cast<time_t>(attr.acctime / NANOS_PER_SECOND);
|
||||
val[0U].tv_usec =
|
||||
static_cast<time_t>((attr.acctime % NANOS_PER_SECOND) / 1000);
|
||||
val[0U].tv_sec =
|
||||
static_cast<time_t>(attr.acctime / utils::time::NANOS_PER_SECOND);
|
||||
val[0U].tv_usec = static_cast<time_t>(
|
||||
(attr.acctime % utils::time::NANOS_PER_SECOND) / 1000);
|
||||
} else {
|
||||
gettimeofday(&val[0U], nullptr);
|
||||
}
|
||||
|
||||
val[1U].tv_sec = static_cast<time_t>(attr.modtime / NANOS_PER_SECOND);
|
||||
val[1U].tv_usec =
|
||||
static_cast<time_t>((attr.modtime % NANOS_PER_SECOND) / 1000);
|
||||
val[1U].tv_sec =
|
||||
static_cast<time_t>(attr.modtime / utils::time::NANOS_PER_SECOND);
|
||||
val[1U].tv_usec = static_cast<time_t>(
|
||||
(attr.modtime % utils::time::NANOS_PER_SECOND) / 1000);
|
||||
|
||||
res = utimes(file_path.c_str(), &val[0U]);
|
||||
}
|
||||
@@ -486,9 +505,10 @@ auto remote_server::fuse_getattr(const char *path, remote::stat &r_stat,
|
||||
const auto api_path = utils::path::create_api_path(path);
|
||||
const auto file_path = construct_path(api_path);
|
||||
const auto parent_api_path = utils::path::get_parent_api_path(api_path);
|
||||
memset(&r_stat, 0, sizeof(remote::stat));
|
||||
|
||||
directory = utils::file::is_directory(file_path);
|
||||
r_stat = {};
|
||||
|
||||
directory = utils::file::directory(file_path).exists();
|
||||
|
||||
struct stat64 unix_st {};
|
||||
auto res = stat64(file_path.c_str(), &unix_st);
|
||||
@@ -651,7 +671,7 @@ auto remote_server::fuse_opendir(const char *path, remote::file_handle &handle)
|
||||
auto res = -1;
|
||||
errno = ENOENT;
|
||||
|
||||
if (utils::file::is_directory(file_path)) {
|
||||
if (utils::file::directory(file_path).exists()) {
|
||||
auto iter = std::make_shared<directory_iterator>(
|
||||
drive_.get_directory_items(utils::path::create_api_path(path)));
|
||||
|
||||
@@ -949,10 +969,10 @@ auto remote_server::fuse_statfs_x(const char *path, std::uint64_t bsize,
|
||||
r_stat.f_blocks ? (r_stat.f_blocks - used_blocks) : 0;
|
||||
r_stat.f_ffree = r_stat.f_favail =
|
||||
r_stat.f_files - drive_.get_total_item_count();
|
||||
std::memset(&r_stat.f_mntfromname[0U], 0, sizeof(r_stat.f_mntfromname));
|
||||
strncpy(&r_stat.f_mntfromname[0U],
|
||||
std::memset(r_stat.f_mntfromname.data(), 0, r_stat.f_mntfromname.size());
|
||||
strncpy(r_stat.f_mntfromname.data(),
|
||||
(utils::create_volume_label(config_.get_provider_type())).c_str(),
|
||||
sizeof(r_stat.f_mntfromname) - 1U);
|
||||
r_stat.f_mntfromname.size() - 1U);
|
||||
|
||||
RAISE_REMOTE_FUSE_SERVER_EVENT(function_name, file_path, 0);
|
||||
return 0;
|
||||
@@ -993,21 +1013,19 @@ auto remote_server::fuse_utimens(const char *path, const remote::file_time *tv,
|
||||
const auto file_path = construct_path(path);
|
||||
|
||||
struct timespec tv2[2] = {{0, 0}};
|
||||
if ((op0 == UTIME_NOW) || (op0 == UTIME_OMIT)) {
|
||||
tv2[0U].tv_nsec = static_cast<time_t>(op0);
|
||||
tv2[0U].tv_sec = 0;
|
||||
} else {
|
||||
tv2[0U].tv_nsec = static_cast<time_t>(tv[0U] % NANOS_PER_SECOND);
|
||||
tv2[0U].tv_sec = static_cast<time_t>(tv[0U] / NANOS_PER_SECOND);
|
||||
}
|
||||
const auto process_timespec = [](auto op, const auto &src, auto &dst) {
|
||||
if ((op == UTIME_NOW) || (op == UTIME_OMIT)) {
|
||||
dst.tv_nsec = static_cast<time_t>(op);
|
||||
dst.tv_sec = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
if ((op1 == UTIME_NOW) || (op1 == UTIME_OMIT)) {
|
||||
tv2[1U].tv_nsec = static_cast<time_t>(op1);
|
||||
tv2[1U].tv_sec = 0;
|
||||
} else {
|
||||
tv2[1U].tv_nsec = static_cast<time_t>(tv[1U] % NANOS_PER_SECOND);
|
||||
tv2[1U].tv_sec = static_cast<time_t>(tv[1U] / NANOS_PER_SECOND);
|
||||
}
|
||||
dst.tv_nsec = static_cast<time_t>(src % utils::time::NANOS_PER_SECOND);
|
||||
dst.tv_sec = static_cast<time_t>(src / utils::time::NANOS_PER_SECOND);
|
||||
};
|
||||
|
||||
process_timespec(op0, tv[0U], tv2[0U]);
|
||||
process_timespec(op1, tv[1U], tv2[1U]);
|
||||
|
||||
const auto res =
|
||||
utimensat(0, file_path.c_str(), &tv2[0U], AT_SYMLINK_NOFOLLOW);
|
||||
@@ -1065,7 +1083,7 @@ auto remote_server::winfsp_can_delete(PVOID file_desc,
|
||||
STATUS_INVALID_HANDLE));
|
||||
if (ret == STATUS_SUCCESS) {
|
||||
ret = static_cast<packet::error_type>(
|
||||
utils::file::is_directory(file_path)
|
||||
utils::file::directory(file_path).exists()
|
||||
? drive_.get_directory_item_count(
|
||||
utils::path::create_api_path(relative_path))
|
||||
? STATUS_DIRECTORY_NOT_EMPTY
|
||||
@@ -1090,7 +1108,7 @@ auto remote_server::winfsp_cleanup(PVOID /*file_desc*/, PWSTR file_name,
|
||||
const auto file_path = construct_path(relative_path);
|
||||
was_closed = 0;
|
||||
|
||||
const auto directory = utils::file::is_directory(file_path);
|
||||
const auto directory = utils::file::directory(file_path).exists();
|
||||
if (flags & FileSystemBase::FspCleanupDelete) {
|
||||
remove_all(file_path);
|
||||
was_closed = 1;
|
||||
@@ -1170,7 +1188,7 @@ auto remote_server::winfsp_create(PWSTR file_name, UINT32 create_options,
|
||||
|
||||
const auto relative_path = utils::string::to_utf8(file_name);
|
||||
const auto file_path = construct_path(relative_path);
|
||||
exists = utils::file::is_file(file_path);
|
||||
exists = utils::file::file(file_path).exists();
|
||||
|
||||
if ((create_options & FILE_DIRECTORY_FILE) != 0U) {
|
||||
attributes |= FILE_ATTRIBUTE_DIRECTORY;
|
||||
@@ -1268,8 +1286,8 @@ auto remote_server::winfsp_get_security_by_name(
|
||||
|
||||
auto ret = static_cast<packet::error_type>(STATUS_SUCCESS);
|
||||
const auto file_path = construct_path(file_name);
|
||||
if (utils::file::is_file(file_path) ||
|
||||
(utils::file::is_directory(file_path))) {
|
||||
if (utils::file::file(file_path).exists() ||
|
||||
(utils::file::directory(file_path).exists())) {
|
||||
if (attributes) {
|
||||
remote::file_info file_info{};
|
||||
if ((ret = populate_file_info(construct_api_path(file_path),
|
||||
@@ -1318,7 +1336,7 @@ auto remote_server::winfsp_open(
|
||||
|
||||
const auto relative_path = utils::string::to_utf8(file_name);
|
||||
const auto file_path = construct_path(relative_path);
|
||||
const auto directory = utils::file::is_directory(file_path);
|
||||
const auto directory = utils::file::directory(file_path).exists();
|
||||
if (directory) {
|
||||
create_options |= FILE_DIRECTORY_FILE;
|
||||
}
|
||||
@@ -1489,11 +1507,11 @@ auto remote_server::winfsp_rename(
|
||||
|
||||
auto res = -1;
|
||||
errno = ENOENT;
|
||||
if (utils::file::is_file(file_path)) {
|
||||
if (utils::file::file(file_path).exists()) {
|
||||
res = drive_.rename_file(construct_api_path(file_path),
|
||||
construct_api_path(new_file_path),
|
||||
replace_if_exists != 0U);
|
||||
} else if (utils::file::is_directory(file_path)) {
|
||||
} else if (utils::file::directory(file_path).exists()) {
|
||||
res = drive_.rename_directory(construct_api_path(file_path),
|
||||
construct_api_path(new_file_path));
|
||||
}
|
||||
@@ -1523,7 +1541,7 @@ auto remote_server::winfsp_set_basic_info(
|
||||
if (attributes == INVALID_FILE_ATTRIBUTES) {
|
||||
attributes = 0;
|
||||
} else if (attributes == 0) {
|
||||
attributes = utils::file::is_directory(file_path)
|
||||
attributes = utils::file::directory(file_path).exists()
|
||||
? FILE_ATTRIBUTE_DIRECTORY
|
||||
: FILE_ATTRIBUTE_NORMAL;
|
||||
}
|
||||
@@ -1542,25 +1560,28 @@ auto remote_server::winfsp_set_basic_info(
|
||||
if ((creation_time != 0U) && (creation_time != max_time)) {
|
||||
drive_.set_item_meta(
|
||||
api_path, META_CREATION,
|
||||
std::to_string(utils::windows_time_to_unix_time(creation_time)));
|
||||
std::to_string(
|
||||
utils::time::windows_time_to_unix_time(creation_time)));
|
||||
}
|
||||
|
||||
if ((last_access_time != 0U) && (last_access_time != max_time)) {
|
||||
drive_.set_item_meta(
|
||||
api_path, META_ACCESSED,
|
||||
std::to_string(utils::windows_time_to_unix_time(last_access_time)));
|
||||
std::to_string(
|
||||
utils::time::windows_time_to_unix_time(last_access_time)));
|
||||
}
|
||||
|
||||
if ((last_write_time != 0U) && (last_write_time != max_time)) {
|
||||
drive_.set_item_meta(
|
||||
api_path, META_WRITTEN,
|
||||
std::to_string(utils::windows_time_to_unix_time(last_write_time)));
|
||||
std::to_string(
|
||||
utils::time::windows_time_to_unix_time(last_write_time)));
|
||||
}
|
||||
|
||||
if ((change_time != 0U) && (change_time != max_time)) {
|
||||
drive_.set_item_meta(
|
||||
api_path, META_MODIFIED,
|
||||
std::to_string(utils::windows_time_to_unix_time(change_time)));
|
||||
std::to_string(utils::time::windows_time_to_unix_time(change_time)));
|
||||
}
|
||||
|
||||
ret = populate_file_info(api_path, *file_info);
|
||||
@@ -1679,7 +1700,7 @@ auto remote_server::json_create_directory_snapshot(
|
||||
auto res = -1;
|
||||
errno = ENOENT;
|
||||
|
||||
if (utils::file::is_directory(file_path)) {
|
||||
if (utils::file::directory(file_path).exists()) {
|
||||
auto iter = std::make_shared<directory_iterator>(
|
||||
drive_.get_directory_items(api_path));
|
||||
auto handle = get_next_handle();
|
||||
@@ -1745,12 +1766,22 @@ auto remote_server::json_release_directory_snapshot(
|
||||
|
||||
auto remote_server::update_to_windows_format(json &item) -> json & {
|
||||
const auto api_path = item["path"].get<std::string>();
|
||||
item["meta"][META_MODIFIED] = std::to_string(utils::unix_time_to_windows_time(
|
||||
utils::string::to_uint64(empty_as_zero(item["meta"][META_MODIFIED]))));
|
||||
item["meta"][META_CREATION] = std::to_string(utils::unix_time_to_windows_time(
|
||||
utils::string::to_uint64(empty_as_zero(item["meta"][META_CREATION]))));
|
||||
item["meta"][META_ACCESSED] = std::to_string(utils::unix_time_to_windows_time(
|
||||
utils::string::to_uint64(empty_as_zero(item["meta"][META_ACCESSED]))));
|
||||
item["meta"][META_ACCESSED] = std::to_string(
|
||||
utils::string::to_uint64(empty_as_zero(item["meta"][META_ACCESSED])));
|
||||
item["meta"][META_CREATION] = std::to_string(
|
||||
utils::string::to_uint64(empty_as_zero(item["meta"][META_CREATION])));
|
||||
item["meta"][META_MODIFIED] = std::to_string(
|
||||
utils::string::to_uint64(empty_as_zero(item["meta"][META_MODIFIED])));
|
||||
|
||||
if (item["meta"][META_WRITTEN].empty() ||
|
||||
(item["meta"][META_WRITTEN].get<std::string>() == "0") ||
|
||||
(item["meta"][META_WRITTEN].get<std::string>() ==
|
||||
std::to_string(utils::time::WIN32_TIME_CONVERSION))) {
|
||||
drive_.set_item_meta(api_path, META_WRITTEN,
|
||||
item["meta"][META_MODIFIED].get<std::string>());
|
||||
item["meta"][META_WRITTEN] = item["meta"][META_MODIFIED];
|
||||
}
|
||||
|
||||
if (item["meta"][META_ATTRIBUTES].empty()) {
|
||||
item["meta"][META_ATTRIBUTES] =
|
||||
item["directory"].get<bool>() ? std::to_string(FILE_ATTRIBUTE_DIRECTORY)
|
||||
@@ -1759,19 +1790,6 @@ auto remote_server::update_to_windows_format(json &item) -> json & {
|
||||
item["meta"][META_ATTRIBUTES].get<std::string>());
|
||||
}
|
||||
|
||||
if (item["meta"][META_WRITTEN].empty() ||
|
||||
(item["meta"][META_WRITTEN].get<std::string>() == "0") ||
|
||||
(item["meta"][META_WRITTEN].get<std::string>() == "116444736000000000")) {
|
||||
drive_.set_item_meta(api_path, META_WRITTEN,
|
||||
item["meta"][META_MODIFIED].get<std::string>());
|
||||
item["meta"][META_WRITTEN] = std::to_string(
|
||||
utils::unix_time_to_windows_time(utils::string::to_uint64(
|
||||
empty_as_zero(item["meta"][META_MODIFIED]))));
|
||||
} else {
|
||||
item["meta"][META_WRITTEN] = std::to_string(
|
||||
utils::unix_time_to_windows_time(utils::string::to_uint64(
|
||||
empty_as_zero(item["meta"][META_WRITTEN]))));
|
||||
}
|
||||
return item;
|
||||
}
|
||||
} // namespace repertory::remote_fuse
|
||||
|
||||
@@ -39,14 +39,14 @@ void remote_open_file_table::add_directory(const std::string &client_id,
|
||||
void remote_open_file_table::close_all(const std::string &client_id) {
|
||||
std::vector<remote::file_handle> compat_handles;
|
||||
unique_recur_mutex_lock compat_lock(compat_mutex_);
|
||||
for (auto &kv : compat_lookup_) {
|
||||
for (auto &&kv : compat_lookup_) {
|
||||
if (kv.second.client_id == client_id) {
|
||||
compat_handles.emplace_back(kv.first);
|
||||
}
|
||||
}
|
||||
compat_lock.unlock();
|
||||
|
||||
for (auto &handle : compat_handles) {
|
||||
for (auto &&handle : compat_handles) {
|
||||
#if defined(_WIN32)
|
||||
_close(static_cast<int>(handle));
|
||||
#else
|
||||
@@ -57,14 +57,14 @@ void remote_open_file_table::close_all(const std::string &client_id) {
|
||||
|
||||
std::vector<native_handle> handles;
|
||||
unique_recur_mutex_lock file_lock(file_mutex_);
|
||||
for (auto &kv : file_lookup_) {
|
||||
for (auto &&kv : file_lookup_) {
|
||||
if (kv.second.client_id == client_id) {
|
||||
handles.emplace_back(kv.first);
|
||||
}
|
||||
}
|
||||
file_lock.unlock();
|
||||
|
||||
for (auto &handle : handles) {
|
||||
for (auto &&handle : handles) {
|
||||
#if defined(_WIN32)
|
||||
::CloseHandle(handle);
|
||||
#else
|
||||
@@ -75,7 +75,7 @@ void remote_open_file_table::close_all(const std::string &client_id) {
|
||||
|
||||
std::vector<std::uint64_t> dirs;
|
||||
unique_recur_mutex_lock directory_lock(directory_mutex_);
|
||||
for (auto &kv : directory_lookup_) {
|
||||
for (auto &&kv : directory_lookup_) {
|
||||
if (kv.first == client_id) {
|
||||
dirs.insert(dirs.end(), kv.second.begin(), kv.second.end());
|
||||
}
|
||||
@@ -183,11 +183,11 @@ void remote_open_file_table::remove_all(const std::string &file_path) {
|
||||
});
|
||||
file_lock.unlock();
|
||||
|
||||
for (auto &handle : open_list) {
|
||||
for (auto &&handle : open_list) {
|
||||
remove_open_info(handle);
|
||||
}
|
||||
|
||||
for (auto &handle : compat_open_list) {
|
||||
for (auto &&handle : compat_open_list) {
|
||||
remove_compat_open_info(handle);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -65,7 +65,10 @@ auto remote_client::winfsp_can_delete(PVOID file_desc,
|
||||
request.encode(file_name);
|
||||
|
||||
std::uint32_t service_flags{};
|
||||
const auto ret = packet_client_.send(function_name, request, service_flags);
|
||||
auto ret{
|
||||
packet_client_.send(function_name, request, service_flags),
|
||||
};
|
||||
|
||||
RAISE_REMOTE_WINFSP_CLIENT_EVENT(
|
||||
function_name,
|
||||
utils::path::create_api_path(utils::string::to_utf8(file_name)), ret);
|
||||
@@ -83,8 +86,9 @@ auto remote_client::json_create_directory_snapshot(
|
||||
|
||||
packet response;
|
||||
std::uint32_t service_flags{};
|
||||
auto ret =
|
||||
packet_client_.send(function_name, request, response, service_flags);
|
||||
auto ret{
|
||||
packet_client_.send(function_name, request, response, service_flags),
|
||||
};
|
||||
if (ret == 0) {
|
||||
ret = packet::decode_json(response, json_data);
|
||||
}
|
||||
@@ -107,8 +111,9 @@ auto remote_client::json_read_directory_snapshot(
|
||||
|
||||
packet response;
|
||||
std::uint32_t service_flags{};
|
||||
auto ret =
|
||||
packet_client_.send(function_name, request, response, service_flags);
|
||||
auto ret{
|
||||
packet_client_.send(function_name, request, response, service_flags),
|
||||
};
|
||||
if (ret == 0) {
|
||||
ret = packet::decode_json(response, json_data);
|
||||
}
|
||||
@@ -129,7 +134,9 @@ auto remote_client::json_release_directory_snapshot(
|
||||
request.encode(handle);
|
||||
|
||||
std::uint32_t service_flags{};
|
||||
const auto ret = packet_client_.send(function_name, request, service_flags);
|
||||
auto ret{
|
||||
packet_client_.send(function_name, request, service_flags),
|
||||
};
|
||||
|
||||
RAISE_REMOTE_WINFSP_CLIENT_EVENT(function_name, path, ret);
|
||||
return ret;
|
||||
@@ -142,8 +149,14 @@ auto remote_client::winfsp_cleanup(PVOID file_desc, PWSTR file_name,
|
||||
static_cast<const char *>(__FUNCTION__),
|
||||
};
|
||||
|
||||
auto handle = to_handle(file_desc);
|
||||
const auto file_path = get_open_file_path(handle);
|
||||
auto handle{
|
||||
to_handle(file_desc),
|
||||
};
|
||||
|
||||
auto file_path{
|
||||
get_open_file_path(handle),
|
||||
};
|
||||
|
||||
was_closed = 0;
|
||||
|
||||
packet request;
|
||||
@@ -153,8 +166,9 @@ auto remote_client::winfsp_cleanup(PVOID file_desc, PWSTR file_name,
|
||||
|
||||
packet response;
|
||||
std::uint32_t service_flags{};
|
||||
auto ret =
|
||||
packet_client_.send(function_name, request, response, service_flags);
|
||||
auto ret{
|
||||
packet_client_.send(function_name, request, response, service_flags),
|
||||
};
|
||||
DECODE_OR_IGNORE(&response, was_closed);
|
||||
if (was_closed != 0U) {
|
||||
remove_all(file_path);
|
||||
@@ -168,15 +182,21 @@ auto remote_client::winfsp_close(PVOID file_desc) -> packet::error_type {
|
||||
static_cast<const char *>(__FUNCTION__),
|
||||
};
|
||||
|
||||
auto handle = to_handle(file_desc);
|
||||
auto handle{
|
||||
to_handle(file_desc),
|
||||
};
|
||||
if (has_open_info(handle, STATUS_INVALID_HANDLE) == STATUS_SUCCESS) {
|
||||
const auto file_path = get_open_file_path(handle);
|
||||
auto file_path{
|
||||
get_open_file_path(handle),
|
||||
};
|
||||
|
||||
packet request;
|
||||
request.encode(file_desc);
|
||||
|
||||
std::uint32_t service_flags{};
|
||||
const auto ret = packet_client_.send(function_name, request, service_flags);
|
||||
auto ret{
|
||||
packet_client_.send(function_name, request, service_flags),
|
||||
};
|
||||
if ((ret == STATUS_SUCCESS) ||
|
||||
(ret == static_cast<packet::error_type>(STATUS_INVALID_HANDLE))) {
|
||||
remove_open_info(handle);
|
||||
@@ -206,8 +226,9 @@ auto remote_client::winfsp_create(PWSTR file_name, UINT32 create_options,
|
||||
|
||||
packet response;
|
||||
std::uint32_t service_flags{};
|
||||
auto ret =
|
||||
packet_client_.send(function_name, request, response, service_flags);
|
||||
auto ret{
|
||||
packet_client_.send(function_name, request, response, service_flags),
|
||||
};
|
||||
if (ret == STATUS_SUCCESS) {
|
||||
HANDLE handle{};
|
||||
DECODE_OR_IGNORE(&response, handle);
|
||||
@@ -243,8 +264,9 @@ auto remote_client::winfsp_flush(PVOID file_desc, remote::file_info *file_info)
|
||||
|
||||
packet response;
|
||||
std::uint32_t service_flags{};
|
||||
auto ret =
|
||||
packet_client_.send(function_name, request, response, service_flags);
|
||||
auto ret{
|
||||
packet_client_.send(function_name, request, response, service_flags),
|
||||
};
|
||||
DECODE_OR_IGNORE(&response, *file_info);
|
||||
|
||||
RAISE_REMOTE_WINFSP_CLIENT_EVENT(
|
||||
@@ -274,8 +296,9 @@ auto remote_client::winfsp_get_file_info(
|
||||
|
||||
packet response;
|
||||
std::uint32_t service_flags{};
|
||||
auto ret =
|
||||
packet_client_.send(function_name, request, response, service_flags);
|
||||
auto ret{
|
||||
packet_client_.send(function_name, request, response, service_flags),
|
||||
};
|
||||
DECODE_OR_IGNORE(&response, *file_info);
|
||||
|
||||
RAISE_REMOTE_WINFSP_CLIENT_EVENT(
|
||||
@@ -298,8 +321,9 @@ auto remote_client::winfsp_get_security_by_name(
|
||||
|
||||
packet response;
|
||||
std::uint32_t service_flags{};
|
||||
auto ret =
|
||||
packet_client_.send(function_name, request, response, service_flags);
|
||||
auto ret{
|
||||
packet_client_.send(function_name, request, response, service_flags),
|
||||
};
|
||||
|
||||
string_descriptor.clear();
|
||||
DECODE_OR_IGNORE(&response, string_descriptor);
|
||||
@@ -326,8 +350,9 @@ auto remote_client::winfsp_get_volume_info(
|
||||
packet request;
|
||||
packet response;
|
||||
std::uint32_t service_flags{};
|
||||
auto ret =
|
||||
packet_client_.send(function_name, request, response, service_flags);
|
||||
auto ret{
|
||||
packet_client_.send(function_name, request, response, service_flags),
|
||||
};
|
||||
DECODE_OR_IGNORE(&response, total_size);
|
||||
DECODE_OR_IGNORE(&response, free_size);
|
||||
DECODE_OR_IGNORE(&response, volume_label);
|
||||
@@ -346,8 +371,13 @@ auto remote_client::winfsp_mounted(const std::wstring &location)
|
||||
request.encode(location);
|
||||
|
||||
std::uint32_t service_flags{};
|
||||
const auto ret = packet_client_.send(function_name, request, service_flags);
|
||||
const auto mount_location = utils::string::to_utf8(location);
|
||||
auto ret{
|
||||
packet_client_.send(function_name, request, service_flags),
|
||||
};
|
||||
|
||||
auto mount_location{
|
||||
utils::string::to_utf8(location),
|
||||
};
|
||||
event_system::instance().raise<drive_mounted>(mount_location);
|
||||
|
||||
RAISE_REMOTE_WINFSP_CLIENT_EVENT(function_name, mount_location, ret);
|
||||
@@ -369,8 +399,9 @@ auto remote_client::winfsp_open(
|
||||
|
||||
packet response;
|
||||
std::uint32_t service_flags{};
|
||||
auto ret =
|
||||
packet_client_.send(function_name, request, response, service_flags);
|
||||
auto ret{
|
||||
packet_client_.send(function_name, request, response, service_flags),
|
||||
};
|
||||
if (ret == STATUS_SUCCESS) {
|
||||
HANDLE handle{};
|
||||
DECODE_OR_IGNORE(&response, handle);
|
||||
@@ -406,8 +437,9 @@ auto remote_client::winfsp_overwrite(
|
||||
|
||||
packet response;
|
||||
std::uint32_t service_flags{};
|
||||
auto ret =
|
||||
packet_client_.send(function_name, request, response, service_flags);
|
||||
auto ret{
|
||||
packet_client_.send(function_name, request, response, service_flags),
|
||||
};
|
||||
DECODE_OR_IGNORE(&response, *file_info);
|
||||
|
||||
RAISE_REMOTE_WINFSP_CLIENT_EVENT(
|
||||
@@ -429,8 +461,9 @@ auto remote_client::winfsp_read(PVOID file_desc, PVOID buffer, UINT64 offset,
|
||||
|
||||
packet response;
|
||||
std::uint32_t service_flags{};
|
||||
auto ret =
|
||||
packet_client_.send(function_name, request, response, service_flags);
|
||||
auto ret{
|
||||
packet_client_.send(function_name, request, response, service_flags),
|
||||
};
|
||||
DECODE_OR_IGNORE(&response, *bytes_transferred);
|
||||
if (ret == STATUS_SUCCESS) {
|
||||
ret = response.decode(buffer, *bytes_transferred);
|
||||
@@ -464,8 +497,9 @@ auto remote_client::winfsp_read_directory(PVOID file_desc, PWSTR pattern,
|
||||
|
||||
packet response;
|
||||
std::uint32_t service_flags{};
|
||||
auto ret =
|
||||
packet_client_.send(function_name, request, response, service_flags);
|
||||
auto ret{
|
||||
packet_client_.send(function_name, request, response, service_flags),
|
||||
};
|
||||
if (ret == STATUS_SUCCESS) {
|
||||
ret = packet::decode_json(response, item_list);
|
||||
}
|
||||
@@ -489,7 +523,10 @@ auto remote_client::winfsp_rename(
|
||||
request.encode(replace_if_exists);
|
||||
|
||||
std::uint32_t service_flags{};
|
||||
const auto ret = packet_client_.send(function_name, request, service_flags);
|
||||
auto ret{
|
||||
packet_client_.send(function_name, request, service_flags),
|
||||
};
|
||||
|
||||
RAISE_REMOTE_WINFSP_CLIENT_EVENT(
|
||||
function_name,
|
||||
utils::path::create_api_path(utils::string::to_utf8(file_name)) + "|" +
|
||||
@@ -516,8 +553,9 @@ auto remote_client::winfsp_set_basic_info(
|
||||
|
||||
packet response;
|
||||
std::uint32_t service_flags{};
|
||||
auto ret =
|
||||
packet_client_.send(function_name, request, response, service_flags);
|
||||
auto ret{
|
||||
packet_client_.send(function_name, request, response, service_flags),
|
||||
};
|
||||
DECODE_OR_IGNORE(&response, *file_info);
|
||||
|
||||
RAISE_REMOTE_WINFSP_CLIENT_EVENT(
|
||||
@@ -539,8 +577,9 @@ auto remote_client::winfsp_set_file_size(
|
||||
|
||||
packet response;
|
||||
std::uint32_t service_flags{};
|
||||
auto ret =
|
||||
packet_client_.send(function_name, request, response, service_flags);
|
||||
auto ret{
|
||||
packet_client_.send(function_name, request, response, service_flags),
|
||||
};
|
||||
DECODE_OR_IGNORE(&response, *file_info);
|
||||
|
||||
RAISE_REMOTE_WINFSP_CLIENT_EVENT(
|
||||
@@ -554,13 +593,17 @@ auto remote_client::winfsp_unmounted(const std::wstring &location)
|
||||
static_cast<const char *>(__FUNCTION__),
|
||||
};
|
||||
|
||||
const auto mount_location = utils::string::to_utf8(location);
|
||||
auto mount_location{
|
||||
utils::string::to_utf8(location),
|
||||
};
|
||||
event_system::instance().raise<drive_unmount_pending>(mount_location);
|
||||
packet request;
|
||||
request.encode(location);
|
||||
|
||||
std::uint32_t service_flags{};
|
||||
const auto ret = packet_client_.send(function_name, request, service_flags);
|
||||
auto ret{
|
||||
packet_client_.send(function_name, request, service_flags),
|
||||
};
|
||||
event_system::instance().raise<drive_unmounted>(mount_location);
|
||||
|
||||
RAISE_REMOTE_WINFSP_CLIENT_EVENT(function_name, mount_location, ret);
|
||||
@@ -587,8 +630,9 @@ auto remote_client::winfsp_write(
|
||||
|
||||
packet response;
|
||||
std::uint32_t service_flags{};
|
||||
auto ret =
|
||||
packet_client_.send(function_name, request, response, service_flags);
|
||||
auto ret{
|
||||
packet_client_.send(function_name, request, response, service_flags),
|
||||
};
|
||||
DECODE_OR_IGNORE(&response, *bytes_transferred);
|
||||
DECODE_OR_IGNORE(&response, *file_info);
|
||||
|
||||
@@ -603,5 +647,5 @@ auto remote_client::winfsp_write(
|
||||
auto remote_client::to_handle(PVOID file_desc) -> native_handle {
|
||||
return static_cast<native_handle>(reinterpret_cast<std::uint64_t>(file_desc));
|
||||
}
|
||||
#endif
|
||||
#endif // !defined(_WIN32)
|
||||
} // namespace repertory::remote_winfsp
|
||||
|
||||
@@ -38,18 +38,11 @@
|
||||
#include "types/remote.hpp"
|
||||
#include "types/repertory.hpp"
|
||||
#include "utils/common.hpp"
|
||||
#include "utils/file.hpp"
|
||||
#include "utils/file_utils.hpp"
|
||||
#include "utils/path.hpp"
|
||||
#include "utils/time.hpp"
|
||||
|
||||
#if !defined(_SH_DENYNO)
|
||||
#define _SH_DENYRW 0x10 // deny read/write mode
|
||||
#define _SH_DENYWR 0x20 // deny write mode
|
||||
#define _SH_DENYRD 0x30 // deny read mode
|
||||
#define _SH_DENYNO 0x40 // deny none mode
|
||||
#define _SH_SECURE 0x80 // secure mode
|
||||
#endif
|
||||
|
||||
namespace repertory::remote_winfsp {
|
||||
#define RAISE_REMOTE_WINFSP_SERVER_EVENT(func, file, ret) \
|
||||
if (config_.get_enable_drive_events() && \
|
||||
@@ -99,10 +92,14 @@ void remote_server::populate_stat(const char *path, bool directory,
|
||||
directory ? 2 + drive_.get_directory_item_count(
|
||||
utils::path::create_api_path(path))
|
||||
: 1);
|
||||
r_stat.st_atimespec = utils::time::time64_to_unix_time(unix_st.st_atime);
|
||||
r_stat.st_birthtimespec = utils::time::time64_to_unix_time(unix_st.st_ctime);
|
||||
r_stat.st_ctimespec = utils::time::time64_to_unix_time(unix_st.st_ctime);
|
||||
r_stat.st_mtimespec = utils::time::time64_to_unix_time(unix_st.st_mtime);
|
||||
r_stat.st_atimespec =
|
||||
utils::time::windows_time_t_to_unix_time(unix_st.st_atime);
|
||||
r_stat.st_birthtimespec =
|
||||
utils::time::windows_time_t_to_unix_time(unix_st.st_ctime);
|
||||
r_stat.st_ctimespec =
|
||||
utils::time::windows_time_t_to_unix_time(unix_st.st_ctime);
|
||||
r_stat.st_mtimespec =
|
||||
utils::time::windows_time_t_to_unix_time(unix_st.st_mtime);
|
||||
r_stat.st_size = static_cast<remote::file_size>(unix_st.st_size);
|
||||
r_stat.st_mode = unix_st.st_mode;
|
||||
}
|
||||
@@ -114,10 +111,22 @@ auto remote_server::fuse_access(const char *path, const std::int32_t &mask)
|
||||
static_cast<const char *>(__FUNCTION__),
|
||||
};
|
||||
|
||||
const auto file_path = construct_path(path);
|
||||
const auto windows_mask = utils::unix_access_mask_to_windows(mask);
|
||||
const auto res = _access(file_path.c_str(), windows_mask);
|
||||
const auto ret = ((res < 0) ? -errno : 0);
|
||||
auto file_path{
|
||||
construct_path(path),
|
||||
};
|
||||
|
||||
auto windows_mask{
|
||||
utils::unix_access_mask_to_windows(mask),
|
||||
};
|
||||
|
||||
auto res{
|
||||
_access(file_path.c_str(), windows_mask),
|
||||
};
|
||||
|
||||
auto ret{
|
||||
((res < 0) ? -errno : 0),
|
||||
};
|
||||
|
||||
RAISE_REMOTE_WINFSP_SERVER_EVENT(function_name, file_path, ret);
|
||||
return ret;
|
||||
}
|
||||
@@ -188,12 +197,15 @@ auto remote_server::fuse_fgetattr(
|
||||
static_cast<const char *>(__FUNCTION__),
|
||||
};
|
||||
|
||||
const auto file_path = construct_path(path);
|
||||
memset(&r_stat, 0, sizeof(remote::stat));
|
||||
r_stat = {};
|
||||
|
||||
auto res = has_compat_open_info(handle, EBADF);
|
||||
const auto file_path = construct_path(path);
|
||||
|
||||
auto res{
|
||||
has_compat_open_info(handle, EBADF),
|
||||
};
|
||||
if (res == 0) {
|
||||
directory = utils::file::is_directory(file_path);
|
||||
directory = utils::file::directory(file_path).exists();
|
||||
struct _stat64 unix_st {};
|
||||
res = _fstat64(static_cast<int>(handle), &unix_st);
|
||||
if (res == 0) {
|
||||
@@ -228,7 +240,9 @@ auto remote_server::fuse_fsync(
|
||||
|
||||
const auto file_path = construct_path(path);
|
||||
|
||||
auto res = has_compat_open_info(handle, EBADF);
|
||||
auto res{
|
||||
has_compat_open_info(handle, EBADF),
|
||||
};
|
||||
if (res == 0) {
|
||||
res = -1;
|
||||
errno = EBADF;
|
||||
@@ -257,7 +271,9 @@ auto remote_server::fuse_ftruncate(
|
||||
|
||||
const auto file_path = construct_path(path);
|
||||
|
||||
auto res = has_compat_open_info(handle, EBADF);
|
||||
auto res{
|
||||
has_compat_open_info(handle, EBADF),
|
||||
};
|
||||
if (res == 0) {
|
||||
res = -1;
|
||||
errno = EBADF;
|
||||
@@ -286,13 +302,16 @@ auto remote_server::fuse_getattr(const char *path, remote::stat &r_st,
|
||||
static_cast<const char *>(__FUNCTION__),
|
||||
};
|
||||
|
||||
const auto file_path = construct_path(path);
|
||||
memset(&r_st, 0, sizeof(remote::stat));
|
||||
r_st = {};
|
||||
|
||||
directory = utils::file::is_directory(file_path);
|
||||
const auto file_path = construct_path(path);
|
||||
|
||||
directory = utils::file::directory(file_path).exists();
|
||||
|
||||
struct _stat64 st1 {};
|
||||
const auto res = _stat64(file_path.c_str(), &st1);
|
||||
auto res{
|
||||
_stat64(file_path.c_str(), &st1),
|
||||
};
|
||||
if (res == 0) {
|
||||
populate_stat(path, directory, r_st, st1);
|
||||
}
|
||||
@@ -352,7 +371,9 @@ auto remote_server::fuse_mkdir(const char *path,
|
||||
};
|
||||
|
||||
const auto file_path = construct_path(path);
|
||||
const auto res = _mkdir(file_path.c_str());
|
||||
auto res{
|
||||
_mkdir(file_path.c_str()),
|
||||
};
|
||||
const auto ret = ((res < 0) ? -errno : 0);
|
||||
RAISE_REMOTE_WINFSP_SERVER_EVENT(function_name, file_path, ret);
|
||||
return ret;
|
||||
@@ -366,7 +387,7 @@ auto remote_server::fuse_opendir(const char *path, remote::file_handle &handle)
|
||||
|
||||
const auto file_path = construct_path(path);
|
||||
const auto unicode_file_path = utils::string::from_utf8(file_path);
|
||||
auto res = -1;
|
||||
auto res{-1};
|
||||
errno = ENOENT;
|
||||
|
||||
if (::PathIsDirectoryW(unicode_file_path.c_str()) != 0) {
|
||||
@@ -409,8 +430,9 @@ auto remote_server::fuse_create(const char *path, const remote::file_mode &mode,
|
||||
ret = -EACCES;
|
||||
} else {
|
||||
int file = -1;
|
||||
const auto res =
|
||||
_sopen_s(&file, file_path.c_str(), open_flags, _SH_DENYNO, perms);
|
||||
auto res{
|
||||
_sopen_s(&file, file_path.c_str(), open_flags, _SH_DENYNO, perms),
|
||||
};
|
||||
if (res == 0) {
|
||||
handle = static_cast<remote::file_handle>(file);
|
||||
ret = 0;
|
||||
@@ -432,7 +454,7 @@ auto remote_server::fuse_open(const char *path, const remote::open_flags &flags,
|
||||
};
|
||||
|
||||
const auto file_path = construct_path(path);
|
||||
auto res = -1;
|
||||
auto res{-1};
|
||||
|
||||
if ((flags & remote::open_flags::directory) ==
|
||||
remote::open_flags::directory) {
|
||||
@@ -467,34 +489,21 @@ auto remote_server::fuse_read(
|
||||
|
||||
const auto file_path = construct_path(path);
|
||||
auto &data = *reinterpret_cast<data_buffer *>(buffer);
|
||||
auto res = 0;
|
||||
auto res{0};
|
||||
if (read_size > std::numeric_limits<std::size_t>::max()) {
|
||||
res = -1;
|
||||
errno = ERANGE;
|
||||
} else if ((res = has_compat_open_info(handle, EBADF)) == 0) {
|
||||
res = -1;
|
||||
errno = EBADF;
|
||||
auto *os_handle =
|
||||
reinterpret_cast<HANDLE>(_get_osfhandle(static_cast<int>(handle)));
|
||||
if (os_handle != INVALID_HANDLE_VALUE) {
|
||||
errno = EFAULT;
|
||||
|
||||
auto file = native_file::attach(os_handle);
|
||||
std::uint64_t file_size{};
|
||||
if (file->get_file_size(file_size)) {
|
||||
data.resize(utils::calculate_read_size(
|
||||
file_size, static_cast<std::size_t>(read_size), read_offset));
|
||||
if (!data.empty()) {
|
||||
std::size_t bytes_read{};
|
||||
if (file->read_bytes(data.data(), data.size(), read_offset,
|
||||
bytes_read)) {
|
||||
res = 0;
|
||||
errno = 0;
|
||||
}
|
||||
} else {
|
||||
res = 0;
|
||||
errno = 0;
|
||||
}
|
||||
res = static_cast<std::decay_t<decltype(res)>>(_lseeki64(
|
||||
static_cast<int>(handle), static_cast<__int64>(read_offset), SEEK_SET));
|
||||
if (res != -1) {
|
||||
data.resize(read_size);
|
||||
res = read(static_cast<int>(handle), data.data(),
|
||||
static_cast<unsigned int>(data.size()));
|
||||
if (res == -1) {
|
||||
data.resize(0U);
|
||||
} else if (data.size() != static_cast<std::size_t>(res)) {
|
||||
data.resize(static_cast<std::size_t>(res));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -514,7 +523,9 @@ auto remote_server::fuse_rename(const char *from,
|
||||
|
||||
const auto from_path = utils::path::combine(mount_location_, {from});
|
||||
const auto to_path = utils::path::combine(mount_location_, {to});
|
||||
const auto res = rename(from_path.c_str(), to_path.c_str());
|
||||
auto res{
|
||||
rename(from_path.c_str(), to_path.c_str()),
|
||||
};
|
||||
|
||||
const auto ret = ((res < 0) ? -errno : 0);
|
||||
RAISE_REMOTE_WINFSP_SERVER_EVENT(function_name, from + std::string("|") + to,
|
||||
@@ -532,26 +543,21 @@ auto remote_server::fuse_write(
|
||||
|
||||
const auto file_path = construct_path(path);
|
||||
std::size_t bytes_written{};
|
||||
auto res = 0;
|
||||
auto res{0};
|
||||
if (write_size > std::numeric_limits<std::size_t>::max()) {
|
||||
res = -1;
|
||||
errno = ERANGE;
|
||||
} else {
|
||||
res = has_compat_open_info(handle, EBADF);
|
||||
if (res == 0) {
|
||||
res = -1;
|
||||
errno = EBADF;
|
||||
auto *os_handle =
|
||||
reinterpret_cast<HANDLE>(_get_osfhandle(static_cast<int>(handle)));
|
||||
if (os_handle != INVALID_HANDLE_VALUE) {
|
||||
errno = EFAULT;
|
||||
if ((write_size == 0) ||
|
||||
native_file::attach(os_handle)->write_bytes(
|
||||
reinterpret_cast<const unsigned char *>(buffer),
|
||||
static_cast<std::size_t>(write_size), write_offset,
|
||||
bytes_written)) {
|
||||
res = 0;
|
||||
errno = 0;
|
||||
res = static_cast<std::decay_t<decltype(res)>>(
|
||||
_lseeki64(static_cast<int>(handle),
|
||||
static_cast<__int64>(write_offset), SEEK_SET));
|
||||
if (res != -1) {
|
||||
res = write(static_cast<int>(handle), buffer,
|
||||
static_cast<unsigned int>(write_size));
|
||||
if (res != -1) {
|
||||
bytes_written = static_cast<std::size_t>(res);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -582,7 +588,7 @@ auto remote_server::fuse_readdir(const char *path,
|
||||
};
|
||||
|
||||
const auto file_path = construct_path(path);
|
||||
auto res = 0;
|
||||
auto res{0};
|
||||
if (offset > std::numeric_limits<std::size_t>::max()) {
|
||||
errno = ERANGE;
|
||||
res = -1;
|
||||
@@ -610,7 +616,9 @@ auto remote_server::fuse_release(
|
||||
const auto file_path = construct_path(path);
|
||||
|
||||
remove_compat_open_info(handle);
|
||||
const auto res = _close(static_cast<int>(handle));
|
||||
auto res{
|
||||
_close(static_cast<int>(handle)),
|
||||
};
|
||||
|
||||
const auto ret = ((res < 0) ? -errno : 0);
|
||||
RAISE_REMOTE_WINFSP_SERVER_EVENT(function_name, file_path, ret);
|
||||
@@ -642,7 +650,9 @@ auto remote_server::fuse_rmdir(const char *path) -> packet::error_type {
|
||||
};
|
||||
|
||||
const auto file_path = construct_path(path);
|
||||
const auto res = _rmdir(file_path.c_str());
|
||||
auto res{
|
||||
_rmdir(file_path.c_str()),
|
||||
};
|
||||
const auto ret = ((res < 0) ? -errno : 0);
|
||||
RAISE_REMOTE_WINFSP_SERVER_EVENT(function_name, file_path, ret);
|
||||
return ret;
|
||||
@@ -767,9 +777,9 @@ auto remote_server::fuse_statfs_x(const char *path, std::uint64_t bsize,
|
||||
r_stat.f_files = 4294967295;
|
||||
r_stat.f_ffree = r_stat.f_favail =
|
||||
r_stat.f_files - drive_.get_total_item_count();
|
||||
strncpy(&r_stat.f_mntfromname[0U],
|
||||
strncpy(r_stat.f_mntfromname.data(),
|
||||
(utils::create_volume_label(config_.get_provider_type())).c_str(),
|
||||
sizeof(r_stat.f_mntfromname) - 1U);
|
||||
r_stat.f_mntfromname.size() - 1U);
|
||||
|
||||
RAISE_REMOTE_WINFSP_SERVER_EVENT(function_name, file_path, 0);
|
||||
return 0;
|
||||
@@ -783,7 +793,7 @@ auto remote_server::fuse_truncate(
|
||||
|
||||
const auto file_path = construct_path(path);
|
||||
const auto unicode_file_path = utils::string::from_utf8(file_path);
|
||||
auto res = -1;
|
||||
auto res{-1};
|
||||
errno = ENOENT;
|
||||
|
||||
const auto flags_and_attributes =
|
||||
@@ -818,7 +828,9 @@ auto remote_server::fuse_unlink(const char *path) -> packet::error_type {
|
||||
};
|
||||
|
||||
const auto file_path = construct_path(path);
|
||||
const auto res = _unlink(file_path.c_str());
|
||||
auto res{
|
||||
_unlink(file_path.c_str()),
|
||||
};
|
||||
const auto ret = ((res < 0) ? -errno : 0);
|
||||
RAISE_REMOTE_WINFSP_SERVER_EVENT(function_name, file_path, ret);
|
||||
return ret;
|
||||
@@ -834,7 +846,7 @@ auto remote_server::fuse_utimens(const char *path, const remote::file_time *tv,
|
||||
const auto file_path = construct_path(path);
|
||||
const auto unicode_file_path = utils::string::from_utf8(file_path);
|
||||
|
||||
auto res = -1;
|
||||
auto res{-1};
|
||||
errno = ENOENT;
|
||||
|
||||
const auto flags_and_attributes =
|
||||
@@ -849,29 +861,27 @@ auto remote_server::fuse_utimens(const char *path, const remote::file_time *tv,
|
||||
if (os_handle != INVALID_HANDLE_VALUE) {
|
||||
FILETIME access_time{};
|
||||
FILETIME write_time{};
|
||||
FILETIME *access_time_ptr = nullptr;
|
||||
FILETIME *write_time_ptr = nullptr;
|
||||
FILETIME *access_time_ptr{nullptr};
|
||||
FILETIME *write_time_ptr{nullptr};
|
||||
|
||||
if ((tv[0U] == 0U) || (op0 == UTIME_NOW)) {
|
||||
const auto now = utils::time::get_file_time_now();
|
||||
access_time.dwHighDateTime =
|
||||
static_cast<DWORD>((now >> 32U) & 0xFFFFFFFF);
|
||||
access_time.dwLowDateTime = now & 0xFFFFFFFF;
|
||||
access_time_ptr = &access_time;
|
||||
} else if (op0 != UTIME_OMIT) {
|
||||
access_time = utils::time::unix_time_to_filetime(tv[0U]);
|
||||
access_time_ptr = &access_time;
|
||||
}
|
||||
const auto proccess_timespec = [](auto op, const auto &src, auto &dst,
|
||||
auto *&dst_ptr) {
|
||||
if ((src == 0U) || (op == UTIME_NOW)) {
|
||||
auto now =
|
||||
utils::time::unix_time_to_windows_time(utils::time::get_time_now());
|
||||
dst.dwHighDateTime = static_cast<DWORD>((now >> 32U) & 0xFFFFFFFF);
|
||||
dst.dwLowDateTime = now & 0xFFFFFFFF;
|
||||
dst_ptr = &dst;
|
||||
return;
|
||||
}
|
||||
|
||||
if ((tv[1U] == 0U) || (op1 == UTIME_NOW)) {
|
||||
const auto now = utils::time::get_file_time_now();
|
||||
write_time.dwHighDateTime = static_cast<DWORD>((now >> 32U) & 0xFFFFFFFF);
|
||||
write_time.dwLowDateTime = now & 0xFFFFFFFF;
|
||||
write_time_ptr = &write_time;
|
||||
} else if (op1 != UTIME_OMIT) {
|
||||
write_time = utils::time::unix_time_to_filetime(tv[1U]);
|
||||
write_time_ptr = &write_time;
|
||||
}
|
||||
if (op != UTIME_OMIT) {
|
||||
dst = utils::time::unix_time_to_filetime(src);
|
||||
dst_ptr = &dst;
|
||||
}
|
||||
};
|
||||
proccess_timespec(op0, tv[0U], access_time, access_time_ptr);
|
||||
proccess_timespec(op1, tv[1U], write_time, write_time_ptr);
|
||||
|
||||
errno = EFAULT;
|
||||
if (::SetFileTime(os_handle, nullptr, access_time_ptr, write_time_ptr) !=
|
||||
@@ -879,6 +889,7 @@ auto remote_server::fuse_utimens(const char *path, const remote::file_time *tv,
|
||||
res = 0;
|
||||
errno = 0;
|
||||
}
|
||||
|
||||
::CloseHandle(os_handle);
|
||||
}
|
||||
|
||||
@@ -896,10 +907,10 @@ auto remote_server::json_create_directory_snapshot(
|
||||
|
||||
const auto file_path = construct_path(path);
|
||||
|
||||
auto res = -1;
|
||||
auto res{-1};
|
||||
errno = ENOENT;
|
||||
|
||||
if (utils::file::is_directory(file_path)) {
|
||||
if (utils::file::directory(file_path).exists()) {
|
||||
auto iter = std::make_shared<directory_iterator>(
|
||||
drive_.get_directory_items(utils::path::create_api_path(path)));
|
||||
auto handle = get_next_handle();
|
||||
@@ -1037,8 +1048,11 @@ auto remote_server::winfsp_create(PWSTR file_name, UINT32 create_options,
|
||||
|
||||
const auto file_path = utils::string::from_utf8(utils::path::combine(
|
||||
mount_location_, {utils::string::to_utf8(file_name)}));
|
||||
exists = static_cast<BOOLEAN>(utils::file::is_file(utils::path::combine(
|
||||
mount_location_, {utils::string::to_utf8(file_name)})));
|
||||
exists = static_cast<BOOLEAN>(
|
||||
utils::file::file(
|
||||
utils::path::combine(mount_location_,
|
||||
{utils::string::to_utf8(file_name)}))
|
||||
.exists());
|
||||
|
||||
auto create_flags = FILE_FLAG_BACKUP_SEMANTICS;
|
||||
if ((create_options & FILE_DIRECTORY_FILE) != 0U) {
|
||||
@@ -1500,4 +1514,4 @@ auto remote_server::winfsp_get_dir_buffer(PVOID /*file_desc*/, PVOID *& /*ptr*/)
|
||||
}
|
||||
} // namespace repertory::remote_winfsp
|
||||
|
||||
#endif // _WIN32
|
||||
#endif // defined(_WIN32)
|
||||
|
||||
@@ -62,7 +62,7 @@ auto remote_winfsp_drive::winfsp_service::OnStart(ULONG, PWSTR *) -> NTSTATUS {
|
||||
(mount_location[1u] == ':');
|
||||
|
||||
auto ret = drive_letter ? STATUS_DEVICE_BUSY : STATUS_NOT_SUPPORTED;
|
||||
if ((drive_letter && not utils::file::is_directory(mount_location))) {
|
||||
if ((drive_letter && not utils::file::directory(mount_location).exists())) {
|
||||
auto unicode_mount_location = utils::string::from_utf8(mount_location);
|
||||
host_.SetFileSystemName(&unicode_mount_location[0u]);
|
||||
if (config_.get_enable_mount_manager()) {
|
||||
@@ -230,7 +230,7 @@ auto remote_winfsp_drive::Init(PVOID host) -> NTSTATUS {
|
||||
file_system_host->SetPersistentAcls(FALSE);
|
||||
file_system_host->SetPostCleanupWhenModifiedOnly(TRUE);
|
||||
file_system_host->SetPassQueryDirectoryPattern(FALSE);
|
||||
file_system_host->SetVolumeCreationTime(utils::time::get_file_time_now());
|
||||
file_system_host->SetVolumeCreationTime(utils::time::get_time_now());
|
||||
file_system_host->SetVolumeSerialNumber(0);
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
@@ -363,33 +363,33 @@ auto remote_winfsp_drive::ReadDirectory(PVOID /*file_node*/, PVOID file_desc,
|
||||
utils::path::strip_to_file_name(item_path));
|
||||
if (not marker || (marker && item_found)) {
|
||||
// if (not utils::path::is_ads_file_path(item_path)) {
|
||||
union {
|
||||
UINT8 B[FIELD_OFFSET(FSP_FSCTL_DIR_INFO, FileNameBuf) +
|
||||
((MAX_PATH + 1) * sizeof(WCHAR))];
|
||||
FSP_FSCTL_DIR_INFO D;
|
||||
} directory_info_buffer;
|
||||
union {
|
||||
UINT8 B[FIELD_OFFSET(FSP_FSCTL_DIR_INFO, FileNameBuf) +
|
||||
((MAX_PATH + 1) * sizeof(WCHAR))];
|
||||
FSP_FSCTL_DIR_INFO D;
|
||||
} directory_info_buffer;
|
||||
|
||||
auto *directory_info = &directory_info_buffer.D;
|
||||
::ZeroMemory(directory_info, sizeof(*directory_info));
|
||||
directory_info->Size = static_cast<UINT16>(
|
||||
FIELD_OFFSET(FSP_FSCTL_DIR_INFO, FileNameBuf) +
|
||||
(std::min((size_t)MAX_PATH, display_name.size()) *
|
||||
sizeof(WCHAR)));
|
||||
auto *directory_info = &directory_info_buffer.D;
|
||||
::ZeroMemory(directory_info, sizeof(*directory_info));
|
||||
directory_info->Size = static_cast<UINT16>(
|
||||
FIELD_OFFSET(FSP_FSCTL_DIR_INFO, FileNameBuf) +
|
||||
(std::min(static_cast<size_t>(MAX_PATH), display_name.size()) *
|
||||
sizeof(WCHAR)));
|
||||
|
||||
if (not item["meta"].empty() ||
|
||||
((item_path != ".") && (item_path != ".."))) {
|
||||
populate_file_info(item, directory_info->FileInfo);
|
||||
}
|
||||
if (ret == STATUS_SUCCESS) {
|
||||
::wcscpy_s(&directory_info->FileNameBuf[0], MAX_PATH,
|
||||
&display_name[0]);
|
||||
|
||||
FspFileSystemFillDirectoryBuffer(directory_buffer,
|
||||
directory_info, &ret);
|
||||
if (ret != STATUS_SUCCESS) {
|
||||
break;
|
||||
}
|
||||
if (not item["meta"].empty() ||
|
||||
((item_path != ".") && (item_path != ".."))) {
|
||||
populate_file_info(item, directory_info->FileInfo);
|
||||
}
|
||||
if (ret == STATUS_SUCCESS) {
|
||||
::wcscpy_s(&directory_info->FileNameBuf[0], MAX_PATH,
|
||||
&display_name[0]);
|
||||
|
||||
FspFileSystemFillDirectoryBuffer(directory_buffer, directory_info,
|
||||
&ret);
|
||||
if (ret != STATUS_SUCCESS) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
// }
|
||||
} else {
|
||||
item_found = display_name == std::wstring(marker);
|
||||
|
||||
@@ -81,7 +81,7 @@ auto winfsp_drive::winfsp_service::OnStart(ULONG /*Argc*/,
|
||||
(mount_location[1U] == ':');
|
||||
|
||||
auto ret = drive_letter ? STATUS_DEVICE_BUSY : STATUS_NOT_SUPPORTED;
|
||||
if ((drive_letter && not utils::file::is_directory(mount_location))) {
|
||||
if ((drive_letter && not utils::file::directory(mount_location).exists())) {
|
||||
auto unicode_mount_location = utils::string::from_utf8(mount_location);
|
||||
host_.SetFileSystemName(unicode_mount_location.data());
|
||||
if (config_.get_enable_mount_manager()) {
|
||||
@@ -215,7 +215,7 @@ VOID winfsp_drive::Cleanup(PVOID file_node, PVOID file_desc,
|
||||
|
||||
if ((flags & (FspCleanupSetLastAccessTime | FspCleanupSetLastWriteTime |
|
||||
FspCleanupSetChangeTime)) != 0U) {
|
||||
const auto now = utils::time::get_file_time_now();
|
||||
const auto now = utils::time::get_time_now();
|
||||
if ((flags & FspCleanupSetLastAccessTime) != 0U) {
|
||||
auto res = provider_.set_item_meta(api_path, META_ACCESSED,
|
||||
std::to_string(now));
|
||||
@@ -238,8 +238,10 @@ VOID winfsp_drive::Cleanup(PVOID file_node, PVOID file_desc,
|
||||
|
||||
if ((flags & FspCleanupSetChangeTime) != 0U) {
|
||||
auto res = provider_.set_item_meta(
|
||||
api_path, {{META_CHANGED, std::to_string(now)},
|
||||
{META_MODIFIED, std::to_string(now)}});
|
||||
api_path, {
|
||||
{META_CHANGED, std::to_string(now)},
|
||||
{META_MODIFIED, std::to_string(now)},
|
||||
});
|
||||
if (res != api_error::success) {
|
||||
utils::error::raise_api_path_error(
|
||||
function_name, api_path, res,
|
||||
@@ -310,7 +312,7 @@ auto winfsp_drive::Create(PWSTR file_name, UINT32 create_options,
|
||||
attributes = FILE_ATTRIBUTE_NORMAL;
|
||||
}
|
||||
|
||||
const auto now = utils::time::get_file_time_now();
|
||||
const auto now = utils::time::get_time_now();
|
||||
auto meta = create_meta_attributes(
|
||||
now, attributes, now, now, (attributes & FILE_ATTRIBUTE_DIRECTORY) != 0U,
|
||||
0U, "", 0U, now, 0U, 0U, 0U,
|
||||
@@ -477,8 +479,7 @@ auto winfsp_drive::get_security_by_name(
|
||||
if (descriptor_size != nullptr) {
|
||||
ULONG size{};
|
||||
PSECURITY_DESCRIPTOR sec_desc{};
|
||||
|
||||
if (::ConvertStringSecurityDescriptorToSecurityDescriptor(
|
||||
if (::ConvertStringSecurityDescriptorToSecurityDescriptorA(
|
||||
"O:BAG:BAD:P(A;;FA;;;SY)(A;;FA;;;BA)(A;;FA;;;WD)",
|
||||
SDDL_REVISION_1, &sec_desc, &size) != 0) {
|
||||
if (size > *descriptor_size) {
|
||||
@@ -512,6 +513,7 @@ auto winfsp_drive::GetSecurityByName(PWSTR file_name, PUINT32 attributes,
|
||||
if (sds != 0U) {
|
||||
*descriptor_size = static_cast<SIZE_T>(sds);
|
||||
}
|
||||
|
||||
RAISE_WINFSP_EVENT(function_name, api_path, ret);
|
||||
return ret;
|
||||
}
|
||||
@@ -579,7 +581,7 @@ auto winfsp_drive::Init(PVOID host) -> NTSTATUS {
|
||||
file_system_host->SetPersistentAcls(FALSE);
|
||||
file_system_host->SetPostCleanupWhenModifiedOnly(TRUE);
|
||||
file_system_host->SetPassQueryDirectoryPattern(FALSE);
|
||||
file_system_host->SetVolumeCreationTime(utils::time::get_file_time_now());
|
||||
file_system_host->SetVolumeCreationTime(utils::time::get_time_now());
|
||||
file_system_host->SetVolumeSerialNumber(0);
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
@@ -590,7 +592,7 @@ auto winfsp_drive::mount(const std::vector<std::string> &drive_args) -> int {
|
||||
const auto force_no_console = utils::collection::includes(drive_args, "-nc");
|
||||
|
||||
auto enable_console = false;
|
||||
for (const auto &arg : drive_args) {
|
||||
for (auto &&arg : drive_args) {
|
||||
if (arg == "-f") {
|
||||
if (not force_no_console) {
|
||||
enable_console = true;
|
||||
@@ -620,10 +622,14 @@ auto winfsp_drive::Mounted(PVOID host) -> NTSTATUS {
|
||||
static_cast<const char *>(__FUNCTION__),
|
||||
};
|
||||
|
||||
auto ret = STATUS_SUCCESS;
|
||||
utils::file::change_to_process_directory();
|
||||
auto ret{STATUS_SUCCESS};
|
||||
if (not utils::file::change_to_process_directory()) {
|
||||
return static_cast<NTSTATUS>(utils::get_last_error_code());
|
||||
}
|
||||
|
||||
auto *file_system_host = reinterpret_cast<FileSystemHost *>(host);
|
||||
auto *file_system_host{
|
||||
reinterpret_cast<FileSystemHost *>(host),
|
||||
};
|
||||
polling::instance().start(&config_);
|
||||
fm_ = std::make_unique<file_manager>(config_, provider_);
|
||||
server_ = std::make_unique<full_server>(config_, provider_, *fm_);
|
||||
@@ -868,7 +874,7 @@ auto winfsp_drive::Read(PVOID /*file_node*/, PVOID file_desc, PVOID buffer,
|
||||
data.clear();
|
||||
auto res = provider_.set_item_meta(
|
||||
api_path, META_ACCESSED,
|
||||
std::to_string(utils::time::get_file_time_now()));
|
||||
std::to_string(utils::time::get_time_now()));
|
||||
if (res != api_error::success) {
|
||||
utils::error::raise_api_path_error(
|
||||
function_name, api_path, res,
|
||||
@@ -929,10 +935,9 @@ auto winfsp_drive::ReadDirectory(PVOID /*file_node*/, PVOID file_desc,
|
||||
api_path, {utils::string::to_utf8(marker)})));
|
||||
while ((error = iterator.get_directory_item(
|
||||
offset++, dir_item)) == api_error::success) {
|
||||
// if (utils::path::is_ads_file_path(dir_item.api_path) ||
|
||||
// dir_item.api_path == "." || dir_item.api_path == "..") {
|
||||
// continue;
|
||||
// }
|
||||
if (dir_item.api_path == "." || dir_item.api_path == "..") {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (dir_item.meta.empty()) {
|
||||
utils::error::raise_api_path_error(
|
||||
@@ -1058,17 +1063,22 @@ auto winfsp_drive::SetBasicInfo(PVOID /*file_node*/, PVOID file_desc,
|
||||
meta[META_ATTRIBUTES] = std::to_string(attributes);
|
||||
}
|
||||
if ((creation_time != 0U) && (creation_time != max_time)) {
|
||||
meta[META_CREATION] = std::to_string(creation_time);
|
||||
meta[META_CREATION] = std::to_string(
|
||||
utils::time::windows_time_to_unix_time(creation_time));
|
||||
}
|
||||
if ((last_access_time != 0U) && (last_access_time != max_time)) {
|
||||
meta[META_ACCESSED] = std::to_string(last_access_time);
|
||||
meta[META_ACCESSED] = std::to_string(
|
||||
utils::time::windows_time_to_unix_time(last_access_time));
|
||||
}
|
||||
if ((last_write_time != 0U) && (last_write_time != max_time)) {
|
||||
meta[META_WRITTEN] = std::to_string(last_write_time);
|
||||
meta[META_WRITTEN] = std::to_string(
|
||||
utils::time::windows_time_to_unix_time(last_write_time));
|
||||
}
|
||||
if ((change_time != 0U) && (change_time != max_time)) {
|
||||
meta[META_CHANGED] = std::to_string(change_time);
|
||||
meta[META_MODIFIED] = std::to_string(change_time);
|
||||
meta[META_CHANGED] =
|
||||
std::to_string(utils::time::windows_time_to_unix_time(change_time));
|
||||
meta[META_MODIFIED] =
|
||||
std::to_string(utils::time::windows_time_to_unix_time(change_time));
|
||||
}
|
||||
|
||||
error = provider_.set_item_meta(api_path, meta);
|
||||
|
||||
@@ -116,7 +116,7 @@ file_manager::file_manager(app_config &config, i_provider &provider)
|
||||
}
|
||||
db_.reset(db3);
|
||||
|
||||
for (const auto &create_item : sql_create_tables) {
|
||||
for (auto &&create_item : sql_create_tables) {
|
||||
std::string err;
|
||||
if (not db::execute_sql(*db_, create_item.second, err)) {
|
||||
db_.reset();
|
||||
@@ -176,12 +176,12 @@ void file_manager::close_timed_out_files() {
|
||||
}
|
||||
return items;
|
||||
});
|
||||
for (const auto &closeable_file : closeable_list) {
|
||||
for (auto &&closeable_file : closeable_list) {
|
||||
open_file_lookup_.erase(closeable_file->get_api_path());
|
||||
}
|
||||
file_lock.unlock();
|
||||
|
||||
for (auto &closeable_file : closeable_list) {
|
||||
for (auto &&closeable_file : closeable_list) {
|
||||
closeable_file->close();
|
||||
event_system::instance().raise<item_timeout>(
|
||||
closeable_file->get_api_path());
|
||||
@@ -244,7 +244,7 @@ auto file_manager::evict_file(const std::string &api_path) -> bool {
|
||||
|
||||
open_file_lookup_.erase(api_path);
|
||||
|
||||
auto removed = utils::file::retry_delete_file(source_path);
|
||||
auto removed = utils::file::file(source_path).remove();
|
||||
if (removed) {
|
||||
event_system::instance().raise<filesystem_item_evicted>(api_path,
|
||||
source_path);
|
||||
@@ -329,7 +329,7 @@ auto file_manager::get_open_files() const
|
||||
std::unordered_map<std::string, std::size_t> ret;
|
||||
|
||||
recur_mutex_lock open_lock(open_file_mtx_);
|
||||
for (const auto &item : open_file_lookup_) {
|
||||
for (auto &&item : open_file_lookup_) {
|
||||
ret[item.first] = item.second->get_open_file_count();
|
||||
}
|
||||
|
||||
@@ -513,8 +513,8 @@ void file_manager::queue_upload(const std::string &api_path,
|
||||
db::db_insert{*db_.get(), upload_table}
|
||||
.or_replace()
|
||||
.column_value("api_path", api_path)
|
||||
.column_value("date_time", static_cast<std::int64_t>(
|
||||
utils::time::get_file_time_now()))
|
||||
.column_value("date_time",
|
||||
static_cast<std::int64_t>(utils::time::get_time_now()))
|
||||
.column_value("source_path", source_path)
|
||||
.go();
|
||||
if (result.ok()) {
|
||||
@@ -557,7 +557,7 @@ auto file_manager::remove_file(const std::string &api_path) -> api_error {
|
||||
return res;
|
||||
}
|
||||
|
||||
if (not utils::file::retry_delete_file(fsi.source_path)) {
|
||||
if (not utils::file::file(fsi.source_path).remove()) {
|
||||
utils::error::raise_api_path_error(
|
||||
function_name, fsi.api_path, fsi.source_path,
|
||||
utils::get_last_error_code(), "failed to delete source");
|
||||
@@ -778,14 +778,9 @@ auto file_manager::rename_file(const std::string &from_api_path,
|
||||
return res;
|
||||
}
|
||||
|
||||
std::uint64_t file_size{};
|
||||
if (not utils::file::get_file_size(fsi.source_path, file_size)) {
|
||||
return api_error::os_error;
|
||||
}
|
||||
|
||||
res = remove_file(to_api_path);
|
||||
if ((res == api_error::success) || (res == api_error::item_not_found)) {
|
||||
if (not utils::file::retry_delete_file(fsi.source_path)) {
|
||||
if (not utils::file::file(fsi.source_path).remove()) {
|
||||
utils::error::raise_api_path_error(
|
||||
function_name, fsi.api_path, fsi.source_path,
|
||||
utils::get_last_error_code(), "failed to delete source path");
|
||||
@@ -848,7 +843,7 @@ void file_manager::start() {
|
||||
}
|
||||
}
|
||||
|
||||
for (const auto &active_item : active_items) {
|
||||
for (auto &&active_item : active_items) {
|
||||
queue_upload(active_item.api_path, active_item.source_path, false);
|
||||
}
|
||||
active_items.clear();
|
||||
@@ -878,8 +873,9 @@ void file_manager::start() {
|
||||
auto res = provider_.get_filesystem_item(api_path, false, fsi);
|
||||
if (res == api_error::success) {
|
||||
if (source_path == fsi.source_path) {
|
||||
std::uint64_t file_size{};
|
||||
if (utils::file::get_file_size(fsi.source_path, file_size)) {
|
||||
auto opt_size = utils::file::file{fsi.source_path}.size();
|
||||
if (opt_size.has_value()) {
|
||||
auto file_size{opt_size.value()};
|
||||
if (file_size == fsi.size) {
|
||||
auto closeable_file = std::make_shared<open_file>(
|
||||
chunk_size,
|
||||
@@ -941,7 +937,7 @@ void file_manager::stop() {
|
||||
open_file_lookup_.clear();
|
||||
|
||||
upload_lock.lock();
|
||||
for (auto &item : upload_lookup_) {
|
||||
for (auto &&item : upload_lookup_) {
|
||||
item.second->stop();
|
||||
}
|
||||
upload_notify_.notify_all();
|
||||
@@ -1027,7 +1023,7 @@ void file_manager::upload_completed(const file_upload_completed &evt) {
|
||||
bool exists{};
|
||||
auto res = provider_.is_file(evt.get_api_path(), exists);
|
||||
if ((res == api_error::success && not exists) ||
|
||||
not utils::file::is_file(evt.get_source().get<std::string>())) {
|
||||
not utils::file::file(evt.get_source().get<std::string>()).exists()) {
|
||||
event_system::instance().raise<file_upload_not_found>(
|
||||
evt.get_api_path(), evt.get_source());
|
||||
remove_upload(evt.get_api_path(), true);
|
||||
@@ -1129,7 +1125,7 @@ void file_manager::upload_handler() {
|
||||
|
||||
void file_manager::update_used_space(std::uint64_t &used_space) const {
|
||||
recur_mutex_lock open_lock(open_file_mtx_);
|
||||
for (const auto &item : open_file_lookup_) {
|
||||
for (auto &&item : open_file_lookup_) {
|
||||
std::uint64_t file_size{};
|
||||
auto res = provider_.get_file_size(item.second->get_api_path(), file_size);
|
||||
if ((res == api_error::success) &&
|
||||
|
||||
@@ -66,8 +66,9 @@ file_manager::open_file::open_file(
|
||||
}
|
||||
|
||||
if (not fsi.directory) {
|
||||
set_api_error(native_file::create_or_open(fsi.source_path,
|
||||
provider_.is_direct_only(), nf_));
|
||||
nf_ = utils::file::file::open_or_create_file(fsi.source_path,
|
||||
provider_.is_direct_only());
|
||||
set_api_error(*nf_ ? api_error::success : api_error::os_error);
|
||||
if (get_api_error() == api_error::success) {
|
||||
if (read_state.has_value()) {
|
||||
read_state_ = read_state.value();
|
||||
@@ -77,19 +78,15 @@ file_manager::open_file::open_file(
|
||||
fsi_.size, chunk_size)),
|
||||
false);
|
||||
|
||||
std::uint64_t file_size{};
|
||||
if (nf_->get_file_size(file_size)) {
|
||||
if (provider_.is_direct_only() || file_size == fsi.size) {
|
||||
read_state_.set(0U, read_state_.size(), true);
|
||||
} else if (not nf_->truncate(fsi.size)) {
|
||||
set_api_error(api_error::os_error);
|
||||
}
|
||||
} else {
|
||||
auto file_size = nf_->size();
|
||||
if (provider_.is_direct_only() || file_size == fsi.size) {
|
||||
read_state_.set(0U, read_state_.size(), true);
|
||||
} else if (not nf_->truncate(fsi.size)) {
|
||||
set_api_error(api_error::os_error);
|
||||
}
|
||||
}
|
||||
|
||||
if (get_api_error() != api_error::success && nf_) {
|
||||
if (get_api_error() != api_error::success && *nf_) {
|
||||
nf_->close();
|
||||
}
|
||||
}
|
||||
@@ -185,8 +182,7 @@ void file_manager::open_file::download_chunk(std::size_t chunk,
|
||||
|
||||
res = do_io([&]() -> api_error {
|
||||
std::size_t bytes_written{};
|
||||
if (not nf_->write_bytes(data.data(), data.size(), data_offset,
|
||||
bytes_written)) {
|
||||
if (not nf_->write(data, data_offset, &bytes_written)) {
|
||||
return api_error::os_error;
|
||||
}
|
||||
|
||||
@@ -296,14 +292,7 @@ auto file_manager::open_file::native_operation(
|
||||
}
|
||||
|
||||
{
|
||||
std::uint64_t file_size{};
|
||||
if (not nf_->get_file_size(file_size)) {
|
||||
utils::error::raise_api_path_error(function_name, get_api_path(),
|
||||
utils::get_last_error_code(),
|
||||
"failed to get file size");
|
||||
return set_api_error(api_error::os_error);
|
||||
}
|
||||
|
||||
auto file_size = nf_->size().value_or(0U);
|
||||
if (file_size != new_file_size) {
|
||||
utils::error::raise_api_path_error(
|
||||
function_name, get_api_path(), api_error::file_size_mismatch,
|
||||
@@ -331,7 +320,7 @@ auto file_manager::open_file::native_operation(
|
||||
set_modified();
|
||||
|
||||
fsi_.size = new_file_size;
|
||||
const auto now = std::to_string(utils::time::get_file_time_now());
|
||||
const auto now = std::to_string(utils::time::get_time_now());
|
||||
res = provider_.set_item_meta(
|
||||
fsi_.api_path, {
|
||||
{META_CHANGED, now},
|
||||
@@ -372,7 +361,7 @@ auto file_manager::open_file::read(std::size_t read_size,
|
||||
|
||||
data.resize(read_size);
|
||||
std::size_t bytes_read{};
|
||||
return nf_->read_bytes(data.data(), read_size, read_offset, bytes_read)
|
||||
return nf_->read(data.data(), read_size, read_offset, &bytes_read)
|
||||
? api_error::success
|
||||
: api_error::os_error;
|
||||
});
|
||||
@@ -461,7 +450,6 @@ auto file_manager::open_file::close() -> bool {
|
||||
}
|
||||
|
||||
nf_->close();
|
||||
nf_.reset();
|
||||
|
||||
if (modified_ && (get_api_error() == api_error::success)) {
|
||||
mgr_.queue_upload(*this);
|
||||
@@ -470,13 +458,13 @@ auto file_manager::open_file::close() -> bool {
|
||||
mgr_.store_resume(*this);
|
||||
} else if (get_api_error() != api_error::success) {
|
||||
mgr_.remove_resume(get_api_path(), get_source_path());
|
||||
if (not utils::file::retry_delete_file(fsi_.source_path)) {
|
||||
if (not utils::file::file(fsi_.source_path).remove()) {
|
||||
utils::error::raise_api_path_error(
|
||||
function_name, get_api_path(), fsi_.source_path,
|
||||
utils::get_last_error_code(), "failed to delete file");
|
||||
}
|
||||
|
||||
auto parent = utils::path::remove_file_name(fsi_.source_path);
|
||||
auto parent = utils::path::get_parent_path(fsi_.source_path);
|
||||
fsi_.source_path =
|
||||
utils::path::combine(parent, {utils::create_uuid_string()});
|
||||
const auto res = provider_.set_item_meta(fsi_.api_path, META_SOURCE,
|
||||
@@ -587,8 +575,7 @@ auto file_manager::open_file::write(std::uint64_t write_offset,
|
||||
}
|
||||
|
||||
auto res = do_io([&]() -> api_error {
|
||||
if (not nf_->write_bytes(data.data(), data.size(), write_offset,
|
||||
bytes_written)) {
|
||||
if (not nf_->write(data, write_offset, &bytes_written)) {
|
||||
return api_error::os_error;
|
||||
}
|
||||
|
||||
@@ -599,7 +586,7 @@ auto file_manager::open_file::write(std::uint64_t write_offset,
|
||||
return set_api_error(res);
|
||||
}
|
||||
|
||||
const auto now = std::to_string(utils::time::get_file_time_now());
|
||||
const auto now = std::to_string(utils::time::get_time_now());
|
||||
res = provider_.set_item_meta(fsi_.api_path, {
|
||||
{META_CHANGED, now},
|
||||
{META_MODIFIED, now},
|
||||
|
||||
@@ -157,7 +157,7 @@ auto file_manager::open_file_base::get_handles() const
|
||||
-> std::vector<std::uint64_t> {
|
||||
recur_mutex_lock file_lock(file_mtx_);
|
||||
std::vector<std::uint64_t> ret;
|
||||
for (const auto &item : open_data_) {
|
||||
for (auto &&item : open_data_) {
|
||||
ret.emplace_back(item.first);
|
||||
}
|
||||
|
||||
|
||||
@@ -64,7 +64,7 @@ file_manager::ring_buffer_open_file::ring_buffer_open_file(
|
||||
ring_state_.set(0U, ring_state_.size(), true);
|
||||
|
||||
buffer_directory = utils::path::absolute(buffer_directory);
|
||||
if (not utils::file::create_full_directory_path(buffer_directory)) {
|
||||
if (not utils::file::directory(buffer_directory).create_directory()) {
|
||||
throw std::runtime_error("failed to create buffer directory|path|" +
|
||||
buffer_directory + "|err|" +
|
||||
std::to_string(utils::get_last_error_code()));
|
||||
@@ -72,8 +72,8 @@ file_manager::ring_buffer_open_file::ring_buffer_open_file(
|
||||
|
||||
fsi_.source_path =
|
||||
utils::path::combine(buffer_directory, {utils::create_uuid_string()});
|
||||
auto res = native_file::create_or_open(fsi_.source_path, nf_);
|
||||
if (res != api_error::success) {
|
||||
nf_ = utils::file::file::open_or_create_file(fsi_.source_path);
|
||||
if (not *nf_) {
|
||||
throw std::runtime_error("failed to create buffer file|err|" +
|
||||
std::to_string(utils::get_last_error_code()));
|
||||
}
|
||||
@@ -93,7 +93,7 @@ file_manager::ring_buffer_open_file::~ring_buffer_open_file() {
|
||||
close();
|
||||
|
||||
nf_->close();
|
||||
if (not utils::file::retry_delete_file(fsi_.source_path)) {
|
||||
if (not utils::file::file(fsi_.source_path).remove()) {
|
||||
utils::error::raise_api_path_error(
|
||||
function_name, fsi_.api_path, fsi_.source_path,
|
||||
utils::get_last_error_code(), "failed to delete file");
|
||||
@@ -128,9 +128,8 @@ auto file_manager::file_manager::ring_buffer_open_file::download_chunk(
|
||||
if (res == api_error::success) {
|
||||
res = do_io([&]() -> api_error {
|
||||
std::size_t bytes_written{};
|
||||
if (not nf_->write_bytes(buffer.data(), buffer.size(),
|
||||
(chunk % ring_state_.size()) * chunk_size_,
|
||||
bytes_written)) {
|
||||
if (not nf_->write(buffer, (chunk % ring_state_.size()) * chunk_size_,
|
||||
&bytes_written)) {
|
||||
return api_error::os_error;
|
||||
}
|
||||
|
||||
@@ -169,8 +168,8 @@ void file_manager::ring_buffer_open_file::forward(std::size_t count) {
|
||||
last_chunk_ =
|
||||
std::min(total_chunks_ - 1U, first_chunk_ + ring_state_.size() - 1U);
|
||||
} else {
|
||||
for (std::size_t i = 0U; i < added; i++) {
|
||||
ring_state_[(first_chunk_ + i) % ring_state_.size()] = true;
|
||||
for (std::size_t idx = 0U; idx < added; ++idx) {
|
||||
ring_state_[(first_chunk_ + idx) % ring_state_.size()] = true;
|
||||
}
|
||||
first_chunk_ += added;
|
||||
current_chunk_ += count;
|
||||
@@ -221,8 +220,8 @@ void file_manager::ring_buffer_open_file::reverse(std::size_t count) {
|
||||
last_chunk_ =
|
||||
std::min(total_chunks_ - 1U, first_chunk_ + ring_state_.size() - 1U);
|
||||
} else {
|
||||
for (std::size_t i = 0U; i < removed; i++) {
|
||||
ring_state_[(last_chunk_ - i) % ring_state_.size()] = true;
|
||||
for (std::size_t idx = 0U; idx < removed; ++idx) {
|
||||
ring_state_[(last_chunk_ - idx) % ring_state_.size()] = true;
|
||||
}
|
||||
first_chunk_ -= removed;
|
||||
current_chunk_ -= count;
|
||||
@@ -255,7 +254,7 @@ auto file_manager::ring_buffer_open_file::read(std::size_t read_size,
|
||||
|
||||
auto res = api_error::success;
|
||||
for (std::size_t chunk = start_chunk_index;
|
||||
(res == api_error::success) && (read_size > 0U); chunk++) {
|
||||
(res == api_error::success) && (read_size > 0U); ++chunk) {
|
||||
if (chunk > current_chunk_) {
|
||||
forward(chunk - current_chunk_);
|
||||
} else if (chunk < current_chunk_) {
|
||||
@@ -270,11 +269,11 @@ auto file_manager::ring_buffer_open_file::read(std::size_t read_size,
|
||||
res = do_io([this, &buffer, &chunk, &data, read_offset,
|
||||
&to_read]() -> api_error {
|
||||
std::size_t bytes_read{};
|
||||
auto ret = nf_->read_bytes(buffer.data(), buffer.size(),
|
||||
((chunk % ring_state_.size()) * chunk_size_),
|
||||
bytes_read)
|
||||
? api_error::success
|
||||
: api_error::os_error;
|
||||
auto ret =
|
||||
nf_->read(buffer, ((chunk % ring_state_.size()) * chunk_size_),
|
||||
&bytes_read)
|
||||
? api_error::success
|
||||
: api_error::os_error;
|
||||
if (ret == api_error::success) {
|
||||
data.insert(data.end(),
|
||||
buffer.begin() + static_cast<std::int64_t>(read_offset),
|
||||
|
||||
@@ -29,8 +29,8 @@
|
||||
|
||||
#if defined(PROJECT_REQUIRE_ALPINE) && !defined(PROJECT_IS_MINGW)
|
||||
#include <filesystem>
|
||||
#include <stdlib.h>
|
||||
#include <pthread.h>
|
||||
#include <stdlib.h>
|
||||
#endif // defined(PROJECT_REQUIRE_ALPINE) && !defined (PROJECT_IS_MINGW)
|
||||
|
||||
#if defined(PROJECT_ENABLE_LIBSODIUM)
|
||||
@@ -44,6 +44,9 @@
|
||||
#include "spdlog/spdlog.h"
|
||||
|
||||
#include "initialize.hpp"
|
||||
#if defined(PROJECT_REQUIRE_ALPINE) && !defined(PROJECT_IS_MINGW)
|
||||
#include "utils/path.hpp"
|
||||
#endif // defined(PROJECT_REQUIRE_ALPINE) && !defined (PROJECT_IS_MINGW)
|
||||
|
||||
namespace repertory {
|
||||
auto project_initialize() -> bool {
|
||||
@@ -61,11 +64,7 @@ auto project_initialize() -> bool {
|
||||
pthread_attr_setguardsize(&attr, guard_size);
|
||||
pthread_setattr_default_np(&attr);
|
||||
|
||||
const auto icu_dir =
|
||||
std::filesystem::absolute(std::filesystem::path{"./icu"})
|
||||
.lexically_normal()
|
||||
.string();
|
||||
setenv("ICU_DATA", icu_dir.c_str(), 1);
|
||||
setenv("ICU_DATA", utils::path::combine(".", {"/icu"}).c_str(), 1);
|
||||
}
|
||||
#endif // defined(PROJECT_REQUIRE_ALPINE) && !defined (PROJECT_IS_MINGW)
|
||||
|
||||
|
||||
@@ -57,7 +57,7 @@ lock_data::~lock_data() {
|
||||
|
||||
auto lock_data::get_lock_data_file() -> std::string {
|
||||
const auto dir = get_state_directory();
|
||||
if (not utils::file::create_full_directory_path(dir)) {
|
||||
if (not utils::file::directory(dir).create_directory()) {
|
||||
throw startup_exception("failed to create directory|sp|" + dir + "|err|" +
|
||||
std::to_string(utils::get_last_error_code()));
|
||||
}
|
||||
@@ -67,7 +67,7 @@ auto lock_data::get_lock_data_file() -> std::string {
|
||||
|
||||
auto lock_data::get_lock_file() -> std::string {
|
||||
const auto dir = get_state_directory();
|
||||
if (not utils::file::create_full_directory_path(dir)) {
|
||||
if (not utils::file::directory(dir).create_directory()) {
|
||||
throw startup_exception("failed to create directory|sp|" + dir + "|err|" +
|
||||
std::to_string(utils::get_last_error_code()));
|
||||
}
|
||||
@@ -184,8 +184,11 @@ auto lock_data::wait_for_lock(int fd, std::uint8_t retry_count) -> int {
|
||||
if (lock_status == -1) {
|
||||
lock_status = errno;
|
||||
if (lock_status == EWOULDBLOCK) {
|
||||
auto sleep_ms =
|
||||
utils::generate_random_between(1U, std::min(remain, max_sleep));
|
||||
auto sleep_ms = std::min(remain, max_sleep);
|
||||
if (sleep_ms > 1U) {
|
||||
sleep_ms = utils::generate_random_between(1U, sleep_ms);
|
||||
}
|
||||
|
||||
std::this_thread::sleep_for(std::chrono::milliseconds(sleep_ms));
|
||||
remain -= sleep_ms;
|
||||
}
|
||||
|
||||
@@ -37,10 +37,10 @@ auto base_provider::create_api_file(std::string path, std::string key,
|
||||
api_file file{};
|
||||
file.api_path = utils::path::create_api_path(path);
|
||||
file.api_parent = utils::path::get_parent_api_path(file.api_path);
|
||||
file.accessed_date = utils::time::get_file_time_now();
|
||||
file.changed_date = utils::time::get_file_time_now();
|
||||
file.creation_date = utils::time::get_file_time_now();
|
||||
file.modified_date = utils::time::get_file_time_now();
|
||||
file.accessed_date = utils::time::get_time_now();
|
||||
file.changed_date = utils::time::get_time_now();
|
||||
file.creation_date = utils::time::get_time_now();
|
||||
file.modified_date = utils::time::get_time_now();
|
||||
file.key = key;
|
||||
file.file_size = size;
|
||||
return file;
|
||||
@@ -455,7 +455,7 @@ void base_provider::remove_deleted_files() {
|
||||
|
||||
std::vector<removed_item> removed_list{};
|
||||
|
||||
for (const auto &api_path : db3_->get_api_path_list()) {
|
||||
for (auto &&api_path : db3_->get_api_path_list()) {
|
||||
api_meta_map meta{};
|
||||
if (get_item_meta(api_path, meta) == api_error::success) {
|
||||
if (utils::string::to_bool(meta[META_DIRECTORY])) {
|
||||
@@ -480,12 +480,12 @@ void base_provider::remove_deleted_files() {
|
||||
}
|
||||
}
|
||||
|
||||
for (const auto &item : removed_list) {
|
||||
for (auto &&item : removed_list) {
|
||||
if (not item.directory) {
|
||||
if (utils::file::is_file(item.source_path)) {
|
||||
if (utils::file::file(item.source_path).exists()) {
|
||||
const auto orphaned_directory =
|
||||
utils::path::combine(config_.get_data_directory(), {"orphaned"});
|
||||
if (utils::file::create_full_directory_path(orphaned_directory)) {
|
||||
if (utils::file::directory(orphaned_directory).create_directory()) {
|
||||
const auto parts = utils::string::split(item.api_path, '/', false);
|
||||
const auto orphaned_file = utils::path::combine(
|
||||
orphaned_directory,
|
||||
@@ -495,7 +495,8 @@ void base_provider::remove_deleted_files() {
|
||||
event_system::instance().raise<orphaned_file_detected>(
|
||||
item.source_path);
|
||||
if (utils::file::reset_modified_time(item.source_path) &&
|
||||
utils::file::copy_file(item.source_path, orphaned_file)) {
|
||||
utils::file::file(item.source_path)
|
||||
.copy_to(orphaned_file, true)) {
|
||||
event_system::instance().raise<orphaned_file_processed>(
|
||||
item.source_path, orphaned_file);
|
||||
} else {
|
||||
@@ -506,7 +507,7 @@ void base_provider::remove_deleted_files() {
|
||||
} else {
|
||||
utils::error::raise_error(
|
||||
function_name, std::to_string(utils::get_last_error_code()),
|
||||
"failed to create orphaned director|sp|" + orphaned_directory);
|
||||
"failed to create orphaned directory|sp|" + orphaned_directory);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
@@ -519,7 +520,7 @@ void base_provider::remove_deleted_files() {
|
||||
}
|
||||
}
|
||||
|
||||
for (const auto &item : removed_list) {
|
||||
for (auto &&item : removed_list) {
|
||||
if (item.directory) {
|
||||
db3_->remove_api_path(item.api_path);
|
||||
event_system::instance().raise<directory_removed_externally>(
|
||||
@@ -640,9 +641,9 @@ auto base_provider::start(api_item_added_callback api_item_added,
|
||||
repertory::event_consumer consumer(
|
||||
"unmount_requested",
|
||||
[&unmount_requested](const event &) { unmount_requested = true; });
|
||||
for (std::uint16_t i = 0U; not online && not unmount_requested &&
|
||||
(i < config_.get_online_check_retry_secs());
|
||||
i++) {
|
||||
for (std::uint16_t idx = 0U; not online && not unmount_requested &&
|
||||
(idx < config_.get_online_check_retry_secs());
|
||||
++idx) {
|
||||
online = is_online();
|
||||
if (not online) {
|
||||
event_system::instance().raise<provider_offline>(
|
||||
|
||||
@@ -28,12 +28,11 @@
|
||||
#include "events/events.hpp"
|
||||
#include "types/repertory.hpp"
|
||||
#include "utils/collection.hpp"
|
||||
#include "utils/encrypt.hpp"
|
||||
#include "utils/encrypting_reader.hpp"
|
||||
#include "utils/encryption.hpp"
|
||||
#include "utils/file_utils.hpp"
|
||||
#include "utils/path.hpp"
|
||||
#include "utils/polling.hpp"
|
||||
#include "utils/time.hpp"
|
||||
|
||||
namespace {
|
||||
const std::string directory_table = "directory";
|
||||
@@ -72,61 +71,24 @@ encrypt_provider::encrypt_provider(app_config &config) : config_(config) {}
|
||||
auto encrypt_provider::create_api_file(
|
||||
const std::string &api_path, bool directory,
|
||||
const std::string &source_path) -> api_file {
|
||||
#if defined(_WIN32)
|
||||
struct _stat64 buf {};
|
||||
_stat64(source_path.c_str(), &buf);
|
||||
#else
|
||||
struct stat buf {};
|
||||
stat(source_path.c_str(), &buf);
|
||||
#endif
|
||||
auto times = utils::file::get_times(source_path);
|
||||
if (not times.has_value()) {
|
||||
throw std::runtime_error("failed to get file times");
|
||||
}
|
||||
|
||||
api_file file{};
|
||||
file.accessed_date = times->get(utils::file::time_type::accessed);
|
||||
file.api_path = api_path;
|
||||
file.api_parent = utils::path::get_parent_api_path(api_path);
|
||||
file.changed_date = times->get(utils::file::time_type::modified);
|
||||
file.creation_date = times->get(utils::file::time_type::created);
|
||||
file.file_size =
|
||||
directory
|
||||
? 0U
|
||||
: utils::encryption::encrypting_reader::calculate_encrypted_size(
|
||||
source_path);
|
||||
file.modified_date = times->get(utils::file::time_type::written);
|
||||
file.source_path = source_path;
|
||||
#if defined(__APPLE__)
|
||||
file.changed_date =
|
||||
buf.st_ctimespec.tv_nsec + (buf.st_ctimespec.tv_sec * NANOS_PER_SECOND);
|
||||
file.accessed_date =
|
||||
buf.st_atimespec.tv_nsec + (buf.st_atimespec.tv_sec * NANOS_PER_SECOND);
|
||||
file.creation_date = buf.st_birthtimespec.tv_nsec +
|
||||
(buf.st_birthtimespec.tv_sec * NANOS_PER_SECOND);
|
||||
file.modified_date =
|
||||
buf.st_mtimespec.tv_nsec + (buf.st_mtimespec.tv_sec * NANOS_PER_SECOND);
|
||||
#elif defined(_WIN32)
|
||||
auto ft = utils::time::unix_time_to_filetime(
|
||||
utils::time::time64_to_unix_time(buf.st_atime));
|
||||
file.accessed_date =
|
||||
(static_cast<std::uint64_t>(ft.dwHighDateTime) << 32U) | ft.dwLowDateTime;
|
||||
|
||||
ft = utils::time::unix_time_to_filetime(
|
||||
utils::time::time64_to_unix_time(buf.st_mtime));
|
||||
file.changed_date =
|
||||
(static_cast<std::uint64_t>(ft.dwHighDateTime) << 32U) | ft.dwLowDateTime;
|
||||
|
||||
ft = utils::time::unix_time_to_filetime(
|
||||
utils::time::time64_to_unix_time(buf.st_ctime));
|
||||
file.creation_date =
|
||||
(static_cast<std::uint64_t>(ft.dwHighDateTime) << 32U) | ft.dwLowDateTime;
|
||||
|
||||
ft = utils::time::unix_time_to_filetime(utils::time::time64_to_unix_time(buf.st_mtime));
|
||||
file.modified_date =
|
||||
(static_cast<std::uint64_t>(ft.dwHighDateTime) << 32U) | ft.dwLowDateTime;
|
||||
#else
|
||||
file.changed_date = static_cast<std::uint64_t>(
|
||||
buf.st_mtim.tv_nsec + (buf.st_mtim.tv_sec * NANOS_PER_SECOND));
|
||||
file.accessed_date = static_cast<std::uint64_t>(
|
||||
buf.st_atim.tv_nsec + (buf.st_atim.tv_sec * NANOS_PER_SECOND));
|
||||
file.creation_date = static_cast<std::uint64_t>(
|
||||
buf.st_ctim.tv_nsec + (buf.st_ctim.tv_sec * NANOS_PER_SECOND));
|
||||
file.modified_date = static_cast<std::uint64_t>(
|
||||
buf.st_mtim.tv_nsec + (buf.st_mtim.tv_sec * NANOS_PER_SECOND));
|
||||
#endif
|
||||
|
||||
return file;
|
||||
}
|
||||
@@ -136,19 +98,21 @@ void encrypt_provider::create_item_meta(api_meta_map &meta, bool directory,
|
||||
#if defined(_WIN32)
|
||||
struct _stat64 buf {};
|
||||
_stat64(file.source_path.c_str(), &buf);
|
||||
#else
|
||||
#else // !defined(_WIN32)
|
||||
struct stat buf {};
|
||||
stat(file.source_path.c_str(), &buf);
|
||||
#endif
|
||||
#endif // defined(_WIN32)
|
||||
|
||||
meta[META_ACCESSED] = std::to_string(file.accessed_date);
|
||||
#if defined(_WIN32)
|
||||
meta[META_ATTRIBUTES] =
|
||||
std::to_string(::GetFileAttributesA(file.source_path.c_str()));
|
||||
#endif
|
||||
std::to_string(::GetFileAttributesA(file.source_path.c_str()) &
|
||||
~static_cast<DWORD>(FILE_ATTRIBUTE_REPARSE_POINT));
|
||||
|
||||
#endif // defined(_WIN32)
|
||||
#if defined(__APPLE__)
|
||||
meta[META_BACKUP];
|
||||
#endif
|
||||
#endif // defined(__APPLE__)
|
||||
meta[META_CHANGED] = std::to_string(file.changed_date);
|
||||
meta[META_CREATION] = std::to_string(file.creation_date);
|
||||
meta[META_DIRECTORY] = utils::string::from_bool(directory);
|
||||
@@ -157,7 +121,7 @@ void encrypt_provider::create_item_meta(api_meta_map &meta, bool directory,
|
||||
meta[META_MODIFIED] = std::to_string(file.modified_date);
|
||||
#if defined(__APPLE__)
|
||||
meta[META_OSXFLAGS];
|
||||
#endif
|
||||
#endif // defined(__APPLE__)
|
||||
meta[META_SIZE] = std::to_string(file.file_size);
|
||||
meta[META_SOURCE] = file.source_path;
|
||||
meta[META_UID] = std::to_string(buf.st_uid);
|
||||
@@ -180,13 +144,10 @@ auto encrypt_provider::do_fs_operation(
|
||||
callback) const -> api_error {
|
||||
auto cfg = config_.get_encrypt_config();
|
||||
std::string source_path{api_path};
|
||||
if (api_path != "/") {
|
||||
auto res =
|
||||
utils::encryption::decrypt_file_path(cfg.encryption_token, source_path);
|
||||
if (res != api_error::success) {
|
||||
return directory ? api_error::directory_not_found
|
||||
: api_error::item_not_found;
|
||||
}
|
||||
if (api_path != "/" && not utils::encryption::decrypt_file_path(
|
||||
cfg.encryption_token, source_path)) {
|
||||
return directory ? api_error::directory_not_found
|
||||
: api_error::item_not_found;
|
||||
}
|
||||
|
||||
source_path = utils::path::combine(cfg.path, {source_path});
|
||||
@@ -197,7 +158,11 @@ auto encrypt_provider::do_fs_operation(
|
||||
: api_error::item_not_found;
|
||||
}
|
||||
|
||||
auto exists = utils::file::is_file(source_path);
|
||||
auto exists =
|
||||
utils::file::file{
|
||||
source_path,
|
||||
}
|
||||
.exists();
|
||||
if (exists && directory) {
|
||||
return api_error::item_exists;
|
||||
}
|
||||
@@ -205,7 +170,11 @@ auto encrypt_provider::do_fs_operation(
|
||||
return api_error::item_not_found;
|
||||
}
|
||||
|
||||
exists = utils::file::is_directory(source_path);
|
||||
exists =
|
||||
utils::file::directory{
|
||||
source_path,
|
||||
}
|
||||
.exists();
|
||||
if (exists && not directory) {
|
||||
return api_error::item_exists;
|
||||
}
|
||||
@@ -271,10 +240,7 @@ auto encrypt_provider::get_directory_item_count(
|
||||
[&api_path, &count](const encrypt_config & /* cfg */,
|
||||
const std::string &source_path) -> api_error {
|
||||
try {
|
||||
for ([[maybe_unused]] const auto &dir_entry :
|
||||
std::filesystem::directory_iterator(source_path)) {
|
||||
count++;
|
||||
}
|
||||
count = utils::file::directory{source_path}.count();
|
||||
} catch (const std::exception &ex) {
|
||||
utils::error::raise_api_path_error(
|
||||
function_name, api_path, source_path, ex,
|
||||
@@ -301,15 +267,15 @@ auto encrypt_provider::get_directory_items(
|
||||
[this, &list](const encrypt_config &cfg,
|
||||
const std::string &source_path) -> api_error {
|
||||
try {
|
||||
for (const auto &dir_entry :
|
||||
std::filesystem::directory_iterator(source_path)) {
|
||||
for (auto &&dir_entry :
|
||||
utils::file::directory{source_path}.get_items()) {
|
||||
try {
|
||||
std::string current_api_path{};
|
||||
if (dir_entry.is_directory()) {
|
||||
if (dir_entry->is_directory_item()) {
|
||||
auto result = db::db_select{*db_, directory_table}
|
||||
.column("api_path")
|
||||
.where("source_path")
|
||||
.equals(dir_entry.path().string())
|
||||
.equals(dir_entry->get_path())
|
||||
.go();
|
||||
std::optional<db::db_select::row> row;
|
||||
if (result.get_row(row) && row.has_value()) {
|
||||
@@ -317,12 +283,13 @@ auto encrypt_provider::get_directory_items(
|
||||
row->get_column("api_path").get_value<std::string>();
|
||||
}
|
||||
if (current_api_path.empty()) {
|
||||
process_directory_entry(dir_entry, cfg, current_api_path);
|
||||
process_directory_entry(*dir_entry.get(), cfg,
|
||||
current_api_path);
|
||||
|
||||
result = db::db_select{*db_, directory_table}
|
||||
.column("api_path")
|
||||
.where("source_path")
|
||||
.equals(dir_entry.path().string())
|
||||
.equals(dir_entry->get_path())
|
||||
.go();
|
||||
row.reset();
|
||||
if (not(result.get_row(row) && row.has_value())) {
|
||||
@@ -337,7 +304,7 @@ auto encrypt_provider::get_directory_items(
|
||||
auto result = db::db_select{*db_, file_table}
|
||||
.column("data")
|
||||
.where("source_path")
|
||||
.equals(dir_entry.path().string())
|
||||
.equals(dir_entry->get_path())
|
||||
.go();
|
||||
std::optional<db::db_select::row> row;
|
||||
if (result.get_row(row) && row.has_value()) {
|
||||
@@ -346,7 +313,7 @@ auto encrypt_provider::get_directory_items(
|
||||
}
|
||||
|
||||
if (api_path_data.empty()) {
|
||||
if (not process_directory_entry(dir_entry, cfg,
|
||||
if (not process_directory_entry(*dir_entry.get(), cfg,
|
||||
current_api_path)) {
|
||||
continue;
|
||||
}
|
||||
@@ -357,14 +324,14 @@ auto encrypt_provider::get_directory_items(
|
||||
}
|
||||
}
|
||||
|
||||
auto file =
|
||||
create_api_file(current_api_path, dir_entry.is_directory(),
|
||||
dir_entry.path().string());
|
||||
auto file = create_api_file(current_api_path,
|
||||
dir_entry->is_directory_item(),
|
||||
dir_entry->get_path());
|
||||
|
||||
directory_item dir_item{};
|
||||
dir_item.api_parent = file.api_parent;
|
||||
dir_item.api_path = file.api_path;
|
||||
dir_item.directory = dir_entry.is_directory();
|
||||
dir_item.directory = dir_entry->is_directory_item();
|
||||
dir_item.resolved = true;
|
||||
dir_item.size = file.file_size;
|
||||
create_item_meta(dir_item.meta, dir_item.directory, file);
|
||||
@@ -372,7 +339,7 @@ auto encrypt_provider::get_directory_items(
|
||||
list.emplace_back(std::move(dir_item));
|
||||
} catch (const std::exception &ex) {
|
||||
utils::error::raise_error(function_name, ex,
|
||||
dir_entry.path().string(),
|
||||
dir_entry->get_path(),
|
||||
"failed to process directory item");
|
||||
}
|
||||
}
|
||||
@@ -405,28 +372,40 @@ auto encrypt_provider::get_directory_items(
|
||||
|
||||
auto encrypt_provider::get_file(const std::string &api_path,
|
||||
api_file &file) const -> api_error {
|
||||
bool exists{};
|
||||
auto res = is_directory(api_path, exists);
|
||||
if (res != api_error::success) {
|
||||
return res;
|
||||
}
|
||||
if (exists) {
|
||||
return api_error::directory_exists;
|
||||
static constexpr const std::string_view function_name{
|
||||
static_cast<const char *>(__FUNCTION__),
|
||||
};
|
||||
|
||||
try {
|
||||
bool exists{};
|
||||
auto res = is_directory(api_path, exists);
|
||||
if (res != api_error::success) {
|
||||
return res;
|
||||
}
|
||||
if (exists) {
|
||||
return api_error::directory_exists;
|
||||
}
|
||||
|
||||
auto result = db::db_select{*db_, source_table}
|
||||
.column("source_path")
|
||||
.where("api_path")
|
||||
.equals(api_path)
|
||||
.go();
|
||||
std::optional<db::db_select::row> row;
|
||||
if (not(result.get_row(row) && row.has_value())) {
|
||||
return api_error::item_not_found;
|
||||
}
|
||||
|
||||
file = create_api_file(
|
||||
api_path, false,
|
||||
row->get_column("source_path").get_value<std::string>());
|
||||
return api_error::success;
|
||||
} catch (const std::exception &ex) {
|
||||
utils::error::raise_error(function_name, ex, api_path,
|
||||
"failed to get file");
|
||||
}
|
||||
|
||||
auto result = db::db_select{*db_, source_table}
|
||||
.column("source_path")
|
||||
.where("api_path")
|
||||
.equals(api_path)
|
||||
.go();
|
||||
std::optional<db::db_select::row> row;
|
||||
if (not(result.get_row(row) && row.has_value())) {
|
||||
return api_error::item_not_found;
|
||||
}
|
||||
|
||||
file = create_api_file(
|
||||
api_path, false, row->get_column("source_path").get_value<std::string>());
|
||||
return api_error::success;
|
||||
return api_error::error;
|
||||
}
|
||||
|
||||
auto encrypt_provider::get_file_list(api_file_list &list) const -> api_error {
|
||||
@@ -435,14 +414,15 @@ auto encrypt_provider::get_file_list(api_file_list &list) const -> api_error {
|
||||
};
|
||||
|
||||
const auto cfg = config_.get_encrypt_config();
|
||||
event_system::instance().raise<debug_log>(std::string{function_name},
|
||||
cfg.path, "");
|
||||
|
||||
try {
|
||||
for (const auto &dir_entry :
|
||||
std::filesystem::recursive_directory_iterator(cfg.path)) {
|
||||
for (auto &&dir_entry : utils::file::directory{cfg.path}.get_items()) {
|
||||
std::string api_path{};
|
||||
if (process_directory_entry(dir_entry, cfg, api_path)) {
|
||||
list.emplace_back(create_api_file(api_path, dir_entry.is_directory(),
|
||||
dir_entry.path().string()));
|
||||
if (process_directory_entry(*dir_entry.get(), cfg, api_path)) {
|
||||
list.emplace_back(create_api_file(
|
||||
api_path, dir_entry->is_directory_item(), dir_entry->get_path()));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -565,22 +545,33 @@ auto encrypt_provider::get_filesystem_item_from_source_path(
|
||||
auto encrypt_provider::get_filesystem_item_and_file(
|
||||
const std::string &api_path, api_file &file,
|
||||
filesystem_item &fsi) const -> api_error {
|
||||
bool exists{};
|
||||
auto res = is_directory(api_path, exists);
|
||||
if (res != api_error::success) {
|
||||
return res;
|
||||
}
|
||||
if (exists) {
|
||||
return api_error::directory_exists;
|
||||
static constexpr const std::string_view function_name{
|
||||
static_cast<const char *>(__FUNCTION__),
|
||||
};
|
||||
|
||||
try {
|
||||
bool exists{};
|
||||
auto res = is_directory(api_path, exists);
|
||||
if (res != api_error::success) {
|
||||
return res;
|
||||
}
|
||||
if (exists) {
|
||||
return api_error::directory_exists;
|
||||
}
|
||||
|
||||
auto ret = get_filesystem_item(api_path, exists, fsi);
|
||||
if (ret != api_error::success) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
file = create_api_file(api_path, false, fsi.source_path);
|
||||
return api_error::success;
|
||||
} catch (const std::exception &ex) {
|
||||
utils::error::raise_error(function_name, ex, api_path,
|
||||
"failed to get filesystem_item and file");
|
||||
}
|
||||
|
||||
auto ret = get_filesystem_item(api_path, exists, fsi);
|
||||
if (ret != api_error::success) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
file = create_api_file(api_path, false, fsi.source_path);
|
||||
return api_error::success;
|
||||
return api_error::error;
|
||||
}
|
||||
|
||||
auto encrypt_provider::get_pinned_files() const -> std::vector<std::string> {
|
||||
@@ -589,27 +580,38 @@ auto encrypt_provider::get_pinned_files() const -> std::vector<std::string> {
|
||||
|
||||
auto encrypt_provider::get_item_meta(const std::string &api_path,
|
||||
api_meta_map &meta) const -> api_error {
|
||||
auto result = db::db_select{*db_, source_table}
|
||||
.column("source_path")
|
||||
.where("api_path")
|
||||
.equals(api_path)
|
||||
.go();
|
||||
std::optional<db::db_select::row> row;
|
||||
if (not(result.get_row(row) && row.has_value())) {
|
||||
return api_error::item_not_found;
|
||||
static constexpr const std::string_view function_name{
|
||||
static_cast<const char *>(__FUNCTION__),
|
||||
};
|
||||
|
||||
try {
|
||||
auto result = db::db_select{*db_, source_table}
|
||||
.column("source_path")
|
||||
.where("api_path")
|
||||
.equals(api_path)
|
||||
.go();
|
||||
std::optional<db::db_select::row> row;
|
||||
if (not(result.get_row(row) && row.has_value())) {
|
||||
return api_error::item_not_found;
|
||||
}
|
||||
|
||||
auto source_path = row->get_column("source_path").get_value<std::string>();
|
||||
|
||||
bool exists{};
|
||||
auto res = is_directory(api_path, exists);
|
||||
if (res != api_error::success) {
|
||||
return res;
|
||||
}
|
||||
|
||||
auto file = create_api_file(api_path, exists, source_path);
|
||||
create_item_meta(meta, exists, file);
|
||||
return api_error::success;
|
||||
} catch (const std::exception &ex) {
|
||||
utils::error::raise_error(function_name, ex, api_path,
|
||||
"failed to get item meta");
|
||||
}
|
||||
|
||||
auto source_path = row->get_column("source_path").get_value<std::string>();
|
||||
|
||||
bool exists{};
|
||||
auto res = is_directory(api_path, exists);
|
||||
if (res != api_error::success) {
|
||||
return res;
|
||||
}
|
||||
|
||||
auto file = create_api_file(api_path, exists, source_path);
|
||||
create_item_meta(meta, exists, file);
|
||||
return api_error::success;
|
||||
return api_error::error;
|
||||
}
|
||||
|
||||
auto encrypt_provider::get_item_meta(const std::string &api_path,
|
||||
@@ -626,8 +628,9 @@ auto encrypt_provider::get_item_meta(const std::string &api_path,
|
||||
}
|
||||
|
||||
auto encrypt_provider::get_total_drive_space() const -> std::uint64_t {
|
||||
const auto cfg = config_.get_encrypt_config();
|
||||
return utils::file::get_total_drive_space(cfg.path);
|
||||
auto total_space =
|
||||
utils::file::get_total_drive_space(config_.get_encrypt_config().path);
|
||||
return total_space.value_or(0U);
|
||||
}
|
||||
|
||||
auto encrypt_provider::get_total_item_count() const -> std::uint64_t {
|
||||
@@ -644,8 +647,10 @@ auto encrypt_provider::get_total_item_count() const -> std::uint64_t {
|
||||
}
|
||||
|
||||
auto encrypt_provider::get_used_drive_space() const -> std::uint64_t {
|
||||
const auto cfg = config_.get_encrypt_config();
|
||||
return get_total_drive_space() - utils::file::get_free_drive_space(cfg.path);
|
||||
auto free_space =
|
||||
utils::file::get_free_drive_space(config_.get_encrypt_config().path);
|
||||
return free_space.has_value() ? get_total_drive_space() - free_space.value()
|
||||
: 0U;
|
||||
}
|
||||
|
||||
auto encrypt_provider::is_directory(const std::string &api_path,
|
||||
@@ -661,8 +666,11 @@ auto encrypt_provider::is_directory(const std::string &api_path,
|
||||
return api_error::success;
|
||||
}
|
||||
|
||||
exists = utils::file::is_directory(
|
||||
row->get_column("source_path").get_value<std::string>());
|
||||
exists =
|
||||
utils::file::directory{
|
||||
row->get_column("source_path").get_value<std::string>(),
|
||||
}
|
||||
.exists();
|
||||
return api_error::success;
|
||||
}
|
||||
|
||||
@@ -679,8 +687,11 @@ auto encrypt_provider::is_file(const std::string &api_path,
|
||||
return api_error::success;
|
||||
}
|
||||
|
||||
exists = utils::file::is_file(
|
||||
row->get_column("source_path").get_value<std::string>());
|
||||
exists =
|
||||
utils::file::file{
|
||||
row->get_column("source_path").get_value<std::string>(),
|
||||
}
|
||||
.exists();
|
||||
return api_error::success;
|
||||
}
|
||||
|
||||
@@ -690,20 +701,24 @@ auto encrypt_provider::is_file_writeable(const std::string & /*api_path*/) const
|
||||
}
|
||||
|
||||
auto encrypt_provider::is_online() const -> bool {
|
||||
return std::filesystem::exists(config_.get_encrypt_config().path);
|
||||
return utils::file::directory{
|
||||
config_.get_encrypt_config().path,
|
||||
}
|
||||
.exists();
|
||||
}
|
||||
|
||||
auto encrypt_provider::is_rename_supported() const -> bool { return false; }
|
||||
|
||||
auto encrypt_provider::process_directory_entry(
|
||||
const std::filesystem::directory_entry &dir_entry,
|
||||
const encrypt_config &cfg, std::string &api_path) const -> bool {
|
||||
const auto add_directory = [this, &cfg](auto dir_path) -> std::string {
|
||||
const utils::file::i_fs_item &dir_entry, const encrypt_config &cfg,
|
||||
std::string &api_path) const -> bool {
|
||||
const auto add_directory = [this,
|
||||
&cfg](std::string_view dir_path) -> std::string {
|
||||
auto encrypted_parts = utils::string::split(
|
||||
utils::path::create_api_path(dir_path.string()), '/', false);
|
||||
utils::path::create_api_path(dir_path), '/', false);
|
||||
|
||||
for (std::size_t part_idx = 1U; part_idx < encrypted_parts.size();
|
||||
part_idx++) {
|
||||
++part_idx) {
|
||||
data_buffer encrypted_data;
|
||||
utils::encryption::encrypt_data(
|
||||
cfg.encryption_token,
|
||||
@@ -718,14 +733,9 @@ auto encrypt_provider::process_directory_entry(
|
||||
|
||||
std::size_t current_idx{1U};
|
||||
std::string current_encrypted_path{};
|
||||
std::string current_source_path{cfg.path};
|
||||
for (const auto &part : dir_path) {
|
||||
if (part.string() == "/") {
|
||||
continue;
|
||||
}
|
||||
|
||||
current_source_path =
|
||||
utils::path::combine(current_source_path, {part.string()});
|
||||
auto current_source_path{cfg.path};
|
||||
for (auto &&part : utils::path::get_parts(dir_path)) {
|
||||
current_source_path = utils::path::combine(current_source_path, {part});
|
||||
|
||||
std::string current_api_path{};
|
||||
auto result = db::db_select{*db_, directory_table}
|
||||
@@ -767,19 +777,21 @@ auto encrypt_provider::process_directory_entry(
|
||||
return current_encrypted_path;
|
||||
};
|
||||
|
||||
if (dir_entry.is_directory()) {
|
||||
api_path = add_directory(dir_entry.path().lexically_relative(cfg.path));
|
||||
if (dir_entry.is_directory_item()) {
|
||||
api_path = add_directory(
|
||||
utils::path::get_relative_path(dir_entry.get_path(), cfg.path));
|
||||
return false;
|
||||
}
|
||||
|
||||
if (dir_entry.is_regular_file() && not dir_entry.is_symlink()) {
|
||||
const auto relative_path = dir_entry.path().lexically_relative(cfg.path);
|
||||
if (dir_entry.is_file_item() && not dir_entry.is_symlink()) {
|
||||
auto relative_path =
|
||||
utils::path::get_relative_path(dir_entry.get_path(), cfg.path);
|
||||
|
||||
std::string api_path_data{};
|
||||
auto result = db::db_select{*db_, file_table}
|
||||
.column("data")
|
||||
.where("source_path")
|
||||
.equals(dir_entry.path().string())
|
||||
.equals(dir_entry.get_path())
|
||||
.go();
|
||||
std::optional<db::db_select::row> row;
|
||||
if (result.get_row(row) && row.has_value()) {
|
||||
@@ -790,7 +802,7 @@ auto encrypt_provider::process_directory_entry(
|
||||
result = db::db_select{*db_, directory_table}
|
||||
.column("api_path")
|
||||
.where("source_path")
|
||||
.equals(dir_entry.path().parent_path().string())
|
||||
.equals(utils::path::get_parent_path(dir_entry.get_path()))
|
||||
.go();
|
||||
row.reset();
|
||||
if (result.get_row(row) && row.has_value()) {
|
||||
@@ -798,15 +810,15 @@ auto encrypt_provider::process_directory_entry(
|
||||
}
|
||||
|
||||
if (api_parent.empty()) {
|
||||
api_parent = add_directory(relative_path.parent_path());
|
||||
api_parent = add_directory(utils::path::get_parent_path(relative_path));
|
||||
}
|
||||
|
||||
if (api_path_data.empty()) {
|
||||
stop_type stop_requested = false;
|
||||
utils::encryption::encrypting_reader reader(
|
||||
relative_path.filename().string(), dir_entry.path().string(),
|
||||
utils::path::strip_to_file_name(relative_path), dir_entry.get_path(),
|
||||
stop_requested, cfg.encryption_token,
|
||||
relative_path.parent_path().string());
|
||||
utils::path::get_parent_path(relative_path));
|
||||
api_path = utils::path::create_api_path(api_parent + "/" +
|
||||
reader.get_encrypted_file_name());
|
||||
|
||||
@@ -814,17 +826,22 @@ auto encrypt_provider::process_directory_entry(
|
||||
json data = {
|
||||
{"api_path", api_path},
|
||||
{"iv_list", iv_list},
|
||||
{"original_file_size", dir_entry.file_size()},
|
||||
{
|
||||
"original_file_size",
|
||||
(dynamic_cast<const utils::file::i_file *>(&dir_entry)
|
||||
->size()
|
||||
.value_or(0U)),
|
||||
},
|
||||
};
|
||||
auto ins_res = db::db_insert{*db_, file_table}
|
||||
.column_value("source_path", dir_entry.path().string())
|
||||
.column_value("source_path", dir_entry.get_path())
|
||||
.column_value("data", data.dump())
|
||||
.go();
|
||||
// TODO handle error
|
||||
|
||||
ins_res = db::db_insert{*db_, source_table}
|
||||
.column_value("api_path", api_path)
|
||||
.column_value("source_path", dir_entry.path().string())
|
||||
.column_value("source_path", dir_entry.get_path())
|
||||
.go();
|
||||
// TODO handle error
|
||||
event_system::instance().raise<filesystem_item_added>(api_path,
|
||||
@@ -874,11 +891,13 @@ auto encrypt_provider::read_file_bytes(const std::string &api_path,
|
||||
|
||||
auto file_data = row->get_column("data").get_value_as_json();
|
||||
|
||||
std::uint64_t file_size{};
|
||||
if (not utils::file::get_file_size(source_path, file_size)) {
|
||||
auto opt_size = utils::file::file{source_path}.size();
|
||||
if (not opt_size.has_value()) {
|
||||
return api_error::os_error;
|
||||
}
|
||||
|
||||
auto file_size{opt_size.value()};
|
||||
|
||||
std::vector<
|
||||
std::array<unsigned char, crypto_aead_xchacha20poly1305_IETF_NPUBBYTES>>
|
||||
iv_list{};
|
||||
@@ -888,13 +907,12 @@ auto encrypt_provider::read_file_bytes(const std::string &api_path,
|
||||
unique_recur_mutex_lock reader_lookup_lock(reader_lookup_mtx_);
|
||||
|
||||
if (file_data.at("original_file_size").get<std::uint64_t>() != file_size) {
|
||||
const auto relative_path =
|
||||
std::filesystem::path(source_path).lexically_relative(cfg.path);
|
||||
auto relative_path = utils::path::get_relative_path(source_path, cfg.path);
|
||||
|
||||
auto info = std::make_shared<reader_info>();
|
||||
info->reader = std::make_unique<utils::encryption::encrypting_reader>(
|
||||
relative_path.filename().string(), source_path, stop_requested,
|
||||
cfg.encryption_token, relative_path.parent_path().string());
|
||||
relative_path, source_path, stop_requested, cfg.encryption_token,
|
||||
utils::path::get_parent_path(relative_path));
|
||||
reader_lookup_[source_path] = info;
|
||||
iv_list = info->reader->get_iv_list();
|
||||
|
||||
@@ -965,9 +983,9 @@ void encrypt_provider::remove_deleted_files() {
|
||||
}
|
||||
}
|
||||
|
||||
for (const auto &row : row_list) {
|
||||
for (auto &&row : row_list) {
|
||||
auto source_path = row.get_column("source_path").get_value<std::string>();
|
||||
if (not std::filesystem::exists(source_path)) {
|
||||
if (not utils::path::exists(source_path)) {
|
||||
auto api_path = row.get_column("api_path").get_value<std::string>();
|
||||
result = db::db_select{*db_, file_table}
|
||||
.column("source_path")
|
||||
@@ -979,7 +997,7 @@ void encrypt_provider::remove_deleted_files() {
|
||||
}
|
||||
}
|
||||
|
||||
for (const auto &item : removed_list) {
|
||||
for (auto &&item : removed_list) {
|
||||
if (not item.directory) {
|
||||
auto del_res = db::db_select{*db_, source_table}
|
||||
.delete_query()
|
||||
@@ -998,7 +1016,7 @@ void encrypt_provider::remove_deleted_files() {
|
||||
}
|
||||
}
|
||||
|
||||
for (const auto &item : removed_list) {
|
||||
for (auto &&item : removed_list) {
|
||||
if (item.directory) {
|
||||
auto del_res = db::db_select{*db_, source_table}
|
||||
.delete_query()
|
||||
@@ -1043,7 +1061,7 @@ auto encrypt_provider::start(api_item_added_callback /*api_item_added*/,
|
||||
}
|
||||
db_.reset(db3);
|
||||
|
||||
for (const auto &create : sql_create_tables) {
|
||||
for (auto &&create : sql_create_tables) {
|
||||
std::string err;
|
||||
if (not db::execute_sql(*db_, create.second, err)) {
|
||||
utils::error::raise_error(function_name, "failed to create table|" +
|
||||
|
||||
@@ -288,7 +288,7 @@ auto meta_db::set_item_meta(const std::string &api_path,
|
||||
// TODO handle error
|
||||
}
|
||||
|
||||
for (const auto &item : meta) {
|
||||
for (auto &&item : meta) {
|
||||
existing_meta[item.first] = item.second;
|
||||
}
|
||||
|
||||
|
||||
@@ -27,12 +27,11 @@
|
||||
#include "file_manager/i_file_manager.hpp"
|
||||
#include "types/repertory.hpp"
|
||||
#include "types/s3.hpp"
|
||||
#include "types/startup_exception.hpp"
|
||||
#include "utils/collection.hpp"
|
||||
#include "utils/encrypt.hpp"
|
||||
#include "utils/encrypting_reader.hpp"
|
||||
#include "utils/encryption.hpp"
|
||||
#include "utils/error_utils.hpp"
|
||||
#include "utils/file_utils.hpp"
|
||||
#include "utils/file.hpp"
|
||||
#include "utils/path.hpp"
|
||||
#include "utils/polling.hpp"
|
||||
#include "utils/string.hpp"
|
||||
@@ -60,6 +59,24 @@ auto s3_provider::add_if_not_found(
|
||||
return api_error::success;
|
||||
}
|
||||
|
||||
auto s3_provider::convert_api_date(std::string_view date) -> std::uint64_t {
|
||||
// 2009-10-12T17:50:30.000Z
|
||||
auto date_parts = utils::string::split(date, '.', true);
|
||||
auto date_time = date_parts.at(0U);
|
||||
auto nanos = utils::string::to_uint64(
|
||||
utils::string::split(date_parts.at(1U), 'Z', true).at(0U));
|
||||
|
||||
struct tm tm1 {};
|
||||
#if defined(_WIN32)
|
||||
utils::time::strptime(date_time.c_str(), "%Y-%m-%dT%T", &tm1);
|
||||
#else
|
||||
strptime(date_time.c_str(), "%Y-%m-%dT%T", &tm1);
|
||||
#endif
|
||||
|
||||
return nanos + (static_cast<std::uint64_t>(mktime(&tm1)) *
|
||||
utils::time::NANOS_PER_SECOND);
|
||||
}
|
||||
|
||||
auto s3_provider::create_directory_impl(const std::string &api_path,
|
||||
api_meta_map &meta) -> api_error {
|
||||
static constexpr const std::string_view function_name{
|
||||
@@ -162,13 +179,13 @@ auto s3_provider::create_path_directories(
|
||||
|
||||
std::string cur_key{'/'};
|
||||
std::string cur_path{'/'};
|
||||
for (std::size_t i = 0U; i < path_parts.size(); i++) {
|
||||
for (std::size_t idx = 0U; idx < path_parts.size(); ++idx) {
|
||||
if (is_encrypted) {
|
||||
cur_key = utils::path::create_api_path(
|
||||
utils::path::combine(cur_key, {key_parts.at(i)}));
|
||||
utils::path::combine(cur_key, {key_parts.at(idx)}));
|
||||
}
|
||||
cur_path = utils::path::create_api_path(
|
||||
utils::path::combine(cur_path, {path_parts.at(i)}));
|
||||
utils::path::combine(cur_path, {path_parts.at(idx)}));
|
||||
|
||||
api_meta_map meta{};
|
||||
auto res = get_item_meta(cur_path, meta);
|
||||
@@ -189,11 +206,10 @@ auto s3_provider::create_path_directories(
|
||||
auto s3_provider::decrypt_object_name(std::string &object_name) const
|
||||
-> api_error {
|
||||
auto parts = utils::string::split(object_name, '/', false);
|
||||
for (auto &part : parts) {
|
||||
auto err = utils::encryption::decrypt_file_name(
|
||||
get_config().get_s3_config().encryption_token, part);
|
||||
if (err != api_error::success) {
|
||||
return err;
|
||||
for (auto &&part : parts) {
|
||||
if (not utils::encryption::decrypt_file_name(
|
||||
get_config().get_s3_config().encryption_token, part)) {
|
||||
return api_error::decryption_error;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -313,10 +329,9 @@ auto s3_provider::get_directory_items_impl(
|
||||
std::string child_object_name;
|
||||
if (is_encrypted) {
|
||||
child_object_name = child_api_path;
|
||||
ret = utils::encryption::decrypt_file_path(cfg.encryption_token,
|
||||
child_api_path);
|
||||
if (ret != api_error::success) {
|
||||
return ret;
|
||||
if (not utils::encryption::decrypt_file_path(cfg.encryption_token,
|
||||
child_api_path)) {
|
||||
return api_error::decryption_error;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -353,14 +368,14 @@ auto s3_provider::get_directory_items_impl(
|
||||
};
|
||||
|
||||
auto node_list = doc.select_nodes("/ListBucketResult/CommonPrefixes/Prefix");
|
||||
for (const auto &node : node_list) {
|
||||
for (auto &&node : node_list) {
|
||||
add_directory_item(
|
||||
true, node.node().text().as_string(),
|
||||
[](const directory_item &) -> std::uint64_t { return 0U; });
|
||||
}
|
||||
|
||||
node_list = doc.select_nodes("/ListBucketResult/Contents");
|
||||
for (const auto &node : node_list) {
|
||||
for (auto &&node : node_list) {
|
||||
auto child_object_name = utils::path::create_api_path(
|
||||
node.node().select_node("Key").node().text().as_string());
|
||||
if (child_object_name != utils::path::create_api_path(prefix)) {
|
||||
@@ -394,7 +409,7 @@ auto s3_provider::get_file(const std::string &api_path,
|
||||
return res;
|
||||
}
|
||||
|
||||
file.accessed_date = utils::time::get_file_time_now();
|
||||
file.accessed_date = utils::time::get_time_now();
|
||||
file.api_path = api_path;
|
||||
file.api_parent = utils::path::get_parent_api_path(file.api_path);
|
||||
file.changed_date = utils::aws::format_time(result.last_modified);
|
||||
@@ -431,7 +446,7 @@ auto s3_provider::get_file_list(api_file_list &list) const -> api_error {
|
||||
}
|
||||
|
||||
auto node_list = doc.select_nodes("/ListBucketResult/Contents");
|
||||
for (const auto &node : node_list) {
|
||||
for (auto &&node : node_list) {
|
||||
auto api_path =
|
||||
std::string{node.node().select_node("Key").node().text().as_string()};
|
||||
if (not utils::string::ends_with(api_path, "/")) {
|
||||
@@ -449,8 +464,8 @@ auto s3_provider::get_file_list(api_file_list &list) const -> api_error {
|
||||
api_file file{};
|
||||
file.api_path = utils::path::create_api_path(api_path);
|
||||
file.api_parent = utils::path::get_parent_api_path(file.api_path);
|
||||
file.accessed_date = utils::time::get_file_time_now();
|
||||
file.changed_date = utils::convert_api_date(
|
||||
file.accessed_date = utils::time::get_time_now();
|
||||
file.changed_date = convert_api_date(
|
||||
node.node().select_node("LastModified").node().text().as_string());
|
||||
file.creation_date = file.changed_date;
|
||||
file.file_size =
|
||||
@@ -674,10 +689,10 @@ auto s3_provider::read_file_bytes(const std::string &api_path, std::size_t size,
|
||||
&stop_requested](std::size_t read_size, std::size_t read_offset,
|
||||
data_buffer &read_buffer) -> api_error {
|
||||
auto res = api_error::error;
|
||||
for (std::uint32_t i = 0U;
|
||||
for (std::uint32_t idx = 0U;
|
||||
not stop_requested && res != api_error::success &&
|
||||
i < get_config().get_retry_read_count() + 1U;
|
||||
i++) {
|
||||
idx < get_config().get_retry_read_count() + 1U;
|
||||
++idx) {
|
||||
curl::requests::http_get get{};
|
||||
get.aws_service = "aws:amz:" + cfg.region + ":s3";
|
||||
get.headers["response-content-type"] = "binary/octet-stream";
|
||||
@@ -698,13 +713,13 @@ auto s3_provider::read_file_bytes(const std::string &api_path, std::size_t size,
|
||||
function_name, api_path, api_error::comm_error,
|
||||
"read file bytes failed|offset|" + std::to_string(read_offset) +
|
||||
"|size|" + std::to_string(read_size) + "|retry|" +
|
||||
std::to_string(i + 1U));
|
||||
std::to_string(idx + 1U));
|
||||
} else {
|
||||
utils::error::raise_api_path_error(
|
||||
function_name, api_path, response_code,
|
||||
"read file bytes failed|offset|" + std::to_string(read_offset) +
|
||||
"|size|" + std::to_string(read_size) + "|retry|" +
|
||||
std::to_string(i + 1U));
|
||||
std::to_string(idx + 1U));
|
||||
}
|
||||
std::this_thread::sleep_for(1s);
|
||||
};
|
||||
@@ -735,15 +750,18 @@ auto s3_provider::read_file_bytes(const std::string &api_path, std::size_t size,
|
||||
const auto total_size = utils::string::to_uint64(temp);
|
||||
|
||||
return utils::encryption::read_encrypted_range(
|
||||
{offset, offset + size - 1U},
|
||||
utils::encryption::generate_key<utils::encryption::hash_256_t>(
|
||||
cfg.encryption_token),
|
||||
[&](data_buffer &ct_buffer, std::uint64_t start_offset,
|
||||
std::uint64_t end_offset) -> api_error {
|
||||
return read_bytes((end_offset - start_offset + 1U), start_offset,
|
||||
ct_buffer);
|
||||
},
|
||||
total_size, data);
|
||||
{offset, offset + size - 1U},
|
||||
utils::encryption::generate_key<utils::encryption::hash_256_t>(
|
||||
cfg.encryption_token),
|
||||
[&](data_buffer &ct_buffer, std::uint64_t start_offset,
|
||||
std::uint64_t end_offset) -> bool {
|
||||
return read_bytes((end_offset - start_offset + 1U),
|
||||
start_offset,
|
||||
ct_buffer) == api_error::success;
|
||||
},
|
||||
total_size, data)
|
||||
? api_error::success
|
||||
: api_error::decryption_error;
|
||||
}
|
||||
|
||||
return read_bytes(size, offset, data);
|
||||
@@ -865,9 +883,12 @@ auto s3_provider::upload_file_impl(const std::string &api_path,
|
||||
const std::string &source_path,
|
||||
stop_type &stop_requested) -> api_error {
|
||||
std::uint64_t file_size{};
|
||||
if (utils::file::is_file(source_path) &&
|
||||
not utils::file::get_file_size(source_path, file_size)) {
|
||||
return api_error::comm_error;
|
||||
if (utils::file::file{source_path}.exists()) {
|
||||
auto opt_size = utils::file::file{source_path}.size();
|
||||
if (not opt_size.has_value()) {
|
||||
return api_error::comm_error;
|
||||
}
|
||||
file_size = opt_size.value();
|
||||
}
|
||||
|
||||
const auto cfg = get_config().get_s3_config();
|
||||
|
||||
@@ -80,7 +80,7 @@ auto sia_provider::get_directory_item_count(const std::string &api_path) const
|
||||
|
||||
std::uint64_t item_count{};
|
||||
if (object_list.contains("entries")) {
|
||||
for (const auto &entry : object_list.at("entries")) {
|
||||
for (auto &&entry : object_list.at("entries")) {
|
||||
try {
|
||||
auto name = entry.at("name").get<std::string>();
|
||||
auto entry_api_path = utils::path::create_api_path(name);
|
||||
@@ -118,7 +118,7 @@ auto sia_provider::get_directory_items_impl(
|
||||
}
|
||||
|
||||
if (object_list.contains("entries")) {
|
||||
for (const auto &entry : object_list.at("entries")) {
|
||||
for (auto &&entry : object_list.at("entries")) {
|
||||
try {
|
||||
auto name = entry.at("name").get<std::string>();
|
||||
auto entry_api_path = utils::path::create_api_path(name);
|
||||
@@ -208,7 +208,7 @@ auto sia_provider::get_file_list(api_file_list &list) const -> api_error {
|
||||
}
|
||||
|
||||
if (object_list.contains("entries")) {
|
||||
for (const auto &entry : object_list.at("entries")) {
|
||||
for (auto &&entry : object_list.at("entries")) {
|
||||
auto name = entry.at("name").get<std::string>();
|
||||
auto entry_api_path = utils::path::create_api_path(name);
|
||||
|
||||
@@ -534,9 +534,10 @@ auto sia_provider::read_file_bytes(const std::string &api_path,
|
||||
long /*response_code*/) { buffer = data; };
|
||||
|
||||
auto res = api_error::comm_error;
|
||||
for (std::uint32_t i = 0U; not stop_requested && res != api_error::success &&
|
||||
i < get_config().get_retry_read_count() + 1U;
|
||||
i++) {
|
||||
for (std::uint32_t idx = 0U;
|
||||
not stop_requested && res != api_error::success &&
|
||||
idx < get_config().get_retry_read_count() + 1U;
|
||||
++idx) {
|
||||
long response_code{};
|
||||
const auto notify_retry = [&]() {
|
||||
if (response_code == 0) {
|
||||
@@ -544,13 +545,13 @@ auto sia_provider::read_file_bytes(const std::string &api_path,
|
||||
function_name, api_path, api_error::comm_error,
|
||||
"read file bytes failed|offset|" + std::to_string(offset) +
|
||||
"|size|" + std::to_string(size) + "|retry|" +
|
||||
std::to_string(i + 1U));
|
||||
std::to_string(idx + 1U));
|
||||
} else {
|
||||
utils::error::raise_api_path_error(
|
||||
function_name, api_path, response_code,
|
||||
"read file bytes failed|offset|" + std::to_string(offset) +
|
||||
"|size|" + std::to_string(size) + "|retry|" +
|
||||
std::to_string(i + 1U));
|
||||
std::to_string(idx + 1U));
|
||||
}
|
||||
std::this_thread::sleep_for(1s);
|
||||
};
|
||||
|
||||
@@ -22,12 +22,11 @@
|
||||
#include "rpc/server/full_server.hpp"
|
||||
|
||||
#include "app_config.hpp"
|
||||
#include "drives/directory_iterator.hpp"
|
||||
#include "file_manager/i_file_manager.hpp"
|
||||
#include "providers/i_provider.hpp"
|
||||
#include "types/repertory.hpp"
|
||||
#include "types/rpc.hpp"
|
||||
#include "utils/file_utils.hpp"
|
||||
#include "utils/file.hpp"
|
||||
#include "utils/path.hpp"
|
||||
|
||||
namespace repertory {
|
||||
@@ -51,11 +50,11 @@ void full_server::handle_get_directory_items(const httplib::Request &req,
|
||||
|
||||
void full_server::handle_get_drive_information(const httplib::Request & /*req*/,
|
||||
httplib::Response &res) {
|
||||
auto dir_size =
|
||||
utils::file::directory(get_config().get_cache_directory()).size();
|
||||
res.set_content(
|
||||
json({
|
||||
{"cache_space_used",
|
||||
utils::file::calculate_used_space(
|
||||
get_config().get_cache_directory(), false)},
|
||||
{"cache_space_used", dir_size},
|
||||
{"drive_space_total", provider_.get_total_drive_space()},
|
||||
{"drive_space_used", provider_.get_used_drive_space()},
|
||||
{"item_count", provider_.get_total_item_count()},
|
||||
|
||||
@@ -1,21 +0,0 @@
|
||||
#include "utils/action_queue.hpp"
|
||||
|
||||
#include "types/repertory.hpp"
|
||||
|
||||
namespace repertory::utils::action_queue {
|
||||
action_queue::action_queue(const std::string &id,
|
||||
std::uint8_t max_concurrent_actions)
|
||||
: single_thread_service_base("action_queue_" + id),
|
||||
id_(id),
|
||||
max_concurrent_actions_(max_concurrent_actions) {}
|
||||
|
||||
void action_queue::service_function() {
|
||||
//
|
||||
}
|
||||
|
||||
void action_queue::push(std::function<void()> action) {
|
||||
unique_mutex_lock queue_lock(queue_mtx_);
|
||||
queue_.emplace_back(action);
|
||||
queue_notify_.notify_all();
|
||||
}
|
||||
} // namespace repertory::utils::action_queue
|
||||
@@ -23,7 +23,8 @@
|
||||
|
||||
#include "app_config.hpp"
|
||||
#include "utils/collection.hpp"
|
||||
#include "utils/file_utils.hpp"
|
||||
#include "utils/common.hpp"
|
||||
#include "utils/file.hpp"
|
||||
#include "utils/path.hpp"
|
||||
#include "utils/string.hpp"
|
||||
#include "utils/utils.hpp"
|
||||
@@ -38,7 +39,7 @@ void get_api_authentication_data(std::string &user, std::string &password,
|
||||
{"config.json"});
|
||||
|
||||
json data;
|
||||
const auto success = utils::retryable_action([&]() -> bool {
|
||||
const auto success = utils::retry_action([&]() -> bool {
|
||||
return utils::file::read_json_file(cfg_file_path, data);
|
||||
});
|
||||
|
||||
|
||||
@@ -1,117 +0,0 @@
|
||||
/*
|
||||
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 "utils/encrypt.hpp"
|
||||
|
||||
#include "events/event_system.hpp"
|
||||
#include "events/events.hpp"
|
||||
#include "types/repertory.hpp"
|
||||
#include "utils/collection.hpp"
|
||||
#include "utils/encrypting_reader.hpp"
|
||||
#include "utils/encryption.hpp"
|
||||
#include "utils/utils.hpp"
|
||||
|
||||
namespace repertory::utils::encryption {
|
||||
auto decrypt_file_path(std::string_view encryption_token,
|
||||
std::string &file_path) -> api_error {
|
||||
std::string decrypted_file_path{};
|
||||
for (const auto &part : std::filesystem::path(file_path)) {
|
||||
auto file_name = part.string();
|
||||
if (file_name == "/") {
|
||||
continue;
|
||||
}
|
||||
|
||||
auto res = decrypt_file_name(encryption_token, file_name);
|
||||
if (res != api_error::success) {
|
||||
return res;
|
||||
}
|
||||
|
||||
decrypted_file_path += '/' + file_name;
|
||||
}
|
||||
|
||||
file_path = decrypted_file_path;
|
||||
return api_error::success;
|
||||
}
|
||||
|
||||
auto decrypt_file_name(std::string_view encryption_token,
|
||||
std::string &file_name) -> api_error {
|
||||
data_buffer buffer;
|
||||
if (not utils::collection::from_hex_string(file_name, buffer)) {
|
||||
return api_error::error;
|
||||
}
|
||||
|
||||
file_name.clear();
|
||||
if (not utils::encryption::decrypt_data(encryption_token, buffer,
|
||||
file_name)) {
|
||||
return api_error::decryption_error;
|
||||
}
|
||||
|
||||
return api_error::success;
|
||||
}
|
||||
|
||||
auto read_encrypted_range(const http_range &range,
|
||||
const utils::encryption::hash_256_t &key,
|
||||
reader_func reader, std::uint64_t total_size,
|
||||
data_buffer &data) -> api_error {
|
||||
const auto encrypted_chunk_size =
|
||||
utils::encryption::encrypting_reader::get_encrypted_chunk_size();
|
||||
const auto data_chunk_size =
|
||||
utils::encryption::encrypting_reader::get_data_chunk_size();
|
||||
|
||||
const auto start_chunk =
|
||||
static_cast<std::size_t>(range.begin / data_chunk_size);
|
||||
const auto end_chunk = static_cast<std::size_t>(range.end / data_chunk_size);
|
||||
auto remain = range.end - range.begin + 1U;
|
||||
auto source_offset = static_cast<std::size_t>(range.begin % data_chunk_size);
|
||||
|
||||
for (std::size_t chunk = start_chunk; chunk <= end_chunk; chunk++) {
|
||||
data_buffer cypher;
|
||||
const auto start_offset = chunk * encrypted_chunk_size;
|
||||
const auto end_offset = std::min(
|
||||
start_offset + (total_size - (chunk * data_chunk_size)) +
|
||||
encryption_header_size - 1U,
|
||||
static_cast<std::uint64_t>(start_offset + encrypted_chunk_size - 1U));
|
||||
|
||||
const auto result = reader(cypher, start_offset, end_offset);
|
||||
if (result != api_error::success) {
|
||||
return result;
|
||||
}
|
||||
|
||||
data_buffer source_buffer;
|
||||
if (not utils::encryption::decrypt_data(key, cypher, source_buffer)) {
|
||||
return api_error::decryption_error;
|
||||
}
|
||||
cypher.clear();
|
||||
|
||||
const auto data_size = static_cast<std::size_t>(std::min(
|
||||
remain, static_cast<std::uint64_t>(data_chunk_size - source_offset)));
|
||||
std::copy(std::next(source_buffer.begin(),
|
||||
static_cast<std::int64_t>(source_offset)),
|
||||
std::next(source_buffer.begin(),
|
||||
static_cast<std::int64_t>(source_offset + data_size)),
|
||||
std::back_inserter(data));
|
||||
remain -= data_size;
|
||||
source_offset = 0U;
|
||||
}
|
||||
|
||||
return api_error::success;
|
||||
}
|
||||
} // namespace repertory::utils::encryption
|
||||
@@ -1,405 +0,0 @@
|
||||
/*
|
||||
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 "utils/encrypting_reader.hpp"
|
||||
|
||||
#include "platform/platform.hpp"
|
||||
#include "types/repertory.hpp"
|
||||
#include "utils/collection.hpp"
|
||||
#include "utils/common.hpp"
|
||||
#include "utils/error_utils.hpp"
|
||||
#include "utils/file.hpp"
|
||||
|
||||
namespace repertory::utils::encryption {
|
||||
class encrypting_streambuf final : public encrypting_reader::streambuf {
|
||||
public:
|
||||
encrypting_streambuf(const encrypting_streambuf &) = default;
|
||||
encrypting_streambuf(encrypting_streambuf &&) = delete;
|
||||
auto
|
||||
operator=(const encrypting_streambuf &) -> encrypting_streambuf & = delete;
|
||||
auto operator=(encrypting_streambuf &&) -> encrypting_streambuf & = delete;
|
||||
|
||||
explicit encrypting_streambuf(const encrypting_reader &reader)
|
||||
: reader_(reader) {
|
||||
setg(reinterpret_cast<char *>(0), reinterpret_cast<char *>(0),
|
||||
reinterpret_cast<char *>(reader_.get_total_size()));
|
||||
}
|
||||
|
||||
~encrypting_streambuf() override = default;
|
||||
|
||||
private:
|
||||
encrypting_reader reader_;
|
||||
|
||||
protected:
|
||||
auto seekoff(off_type off, std::ios_base::seekdir dir,
|
||||
std::ios_base::openmode which = std::ios_base::out |
|
||||
std::ios_base::in)
|
||||
-> pos_type override {
|
||||
if ((which & std::ios_base::in) != std::ios_base::in) {
|
||||
throw std::runtime_error("output is not supported");
|
||||
}
|
||||
|
||||
const auto set_position = [this](char *next) -> pos_type {
|
||||
if ((next <= egptr()) && (next >= eback())) {
|
||||
setg(eback(), next, reinterpret_cast<char *>(reader_.get_total_size()));
|
||||
return static_cast<std::streamoff>(
|
||||
reinterpret_cast<std::uintptr_t>(gptr()));
|
||||
}
|
||||
|
||||
return {traits_type::eof()};
|
||||
};
|
||||
|
||||
switch (dir) {
|
||||
case std::ios_base::beg:
|
||||
return set_position(eback() + off);
|
||||
|
||||
case std::ios_base::cur:
|
||||
return set_position(gptr() + off);
|
||||
|
||||
case std::ios_base::end:
|
||||
return set_position(egptr() + off);
|
||||
}
|
||||
|
||||
return encrypting_reader::streambuf::seekoff(off, dir, which);
|
||||
}
|
||||
|
||||
auto seekpos(pos_type pos, std::ios_base::openmode which =
|
||||
std::ios_base::out |
|
||||
std::ios_base::in) -> pos_type override {
|
||||
return seekoff(pos, std::ios_base::beg, which);
|
||||
}
|
||||
|
||||
auto uflow() -> int_type override {
|
||||
auto ret = underflow();
|
||||
if (ret == traits_type::eof()) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
gbump(1);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
auto underflow() -> int_type override {
|
||||
if (gptr() == egptr()) {
|
||||
return traits_type::eof();
|
||||
}
|
||||
|
||||
reader_.set_read_position(reinterpret_cast<std::uintptr_t>(gptr()));
|
||||
|
||||
char c{};
|
||||
const auto res = encrypting_reader::reader_function(&c, 1U, 1U, &reader_);
|
||||
if (res != 1) {
|
||||
return traits_type::eof();
|
||||
}
|
||||
|
||||
return c;
|
||||
}
|
||||
|
||||
auto xsgetn(char *ptr, std::streamsize count) -> std::streamsize override {
|
||||
if (gptr() == egptr()) {
|
||||
return traits_type::eof();
|
||||
}
|
||||
|
||||
reader_.set_read_position(reinterpret_cast<std::uintptr_t>(gptr()));
|
||||
|
||||
const auto res = encrypting_reader::reader_function(
|
||||
ptr, 1U, static_cast<std::size_t>(count), &reader_);
|
||||
if ((res == reader_.get_error_return()) ||
|
||||
(reader_.get_stop_requested() && (res == CURL_READFUNC_ABORT))) {
|
||||
return traits_type::eof();
|
||||
}
|
||||
|
||||
setg(eback(), gptr() + res,
|
||||
reinterpret_cast<char *>(reader_.get_total_size()));
|
||||
return static_cast<std::streamsize>(res);
|
||||
}
|
||||
};
|
||||
|
||||
class encrypting_reader_iostream final : public encrypting_reader::iostream {
|
||||
public:
|
||||
encrypting_reader_iostream(const encrypting_reader_iostream &) = delete;
|
||||
encrypting_reader_iostream(encrypting_reader_iostream &&) = delete;
|
||||
|
||||
auto operator=(const encrypting_reader_iostream &)
|
||||
-> encrypting_reader_iostream & = delete;
|
||||
auto operator=(encrypting_reader_iostream &&)
|
||||
-> encrypting_reader_iostream & = delete;
|
||||
|
||||
explicit encrypting_reader_iostream(
|
||||
std::unique_ptr<encrypting_streambuf> buffer)
|
||||
: encrypting_reader::iostream(buffer.get()), buffer_(std::move(buffer)) {}
|
||||
|
||||
~encrypting_reader_iostream() override = default;
|
||||
|
||||
private:
|
||||
std::unique_ptr<encrypting_streambuf> buffer_;
|
||||
};
|
||||
|
||||
const std::size_t encrypting_reader::header_size_ = ([]() {
|
||||
return crypto_aead_xchacha20poly1305_IETF_NPUBBYTES +
|
||||
crypto_aead_xchacha20poly1305_IETF_ABYTES;
|
||||
})();
|
||||
const std::size_t encrypting_reader::data_chunk_size_ = (8UL * 1024UL * 1024UL);
|
||||
const std::size_t encrypting_reader::encrypted_chunk_size_ =
|
||||
data_chunk_size_ + header_size_;
|
||||
|
||||
encrypting_reader::encrypting_reader(
|
||||
std::string_view file_name, std::string_view source_path,
|
||||
stop_type &stop_requested, std::string_view token,
|
||||
std::optional<std::string_view> relative_parent_path,
|
||||
std::size_t error_return)
|
||||
: key_(utils::encryption::generate_key<utils::encryption::hash_256_t>(
|
||||
token)),
|
||||
stop_requested_(stop_requested),
|
||||
error_return_(error_return) {
|
||||
const auto res = native_file::create_or_open(source_path, true, source_file_);
|
||||
if (res != api_error::success) {
|
||||
throw std::runtime_error("file open failed|src|" +
|
||||
std::string{source_path} + '|' +
|
||||
api_error_to_string(res));
|
||||
}
|
||||
|
||||
data_buffer result;
|
||||
utils::encryption::encrypt_data(
|
||||
key_, reinterpret_cast<const unsigned char *>(file_name.data()),
|
||||
file_name.size(), result);
|
||||
encrypted_file_name_ = utils::collection::to_hex_string(result);
|
||||
|
||||
if (relative_parent_path.has_value()) {
|
||||
for (auto &&part : std::filesystem::path(relative_parent_path.value())) {
|
||||
utils::encryption::encrypt_data(
|
||||
key_, reinterpret_cast<const unsigned char *>(part.string().c_str()),
|
||||
strnlen(part.string().c_str(), part.string().size()), result);
|
||||
encrypted_file_path_ += '/' + utils::collection::to_hex_string(result);
|
||||
}
|
||||
encrypted_file_path_ += '/' + encrypted_file_name_;
|
||||
}
|
||||
|
||||
std::uint64_t file_size{};
|
||||
if (not utils::file::get_file_size(source_path, file_size)) {
|
||||
throw std::runtime_error("get file size failed|src|" +
|
||||
std::string{source_path} + '|' +
|
||||
std::to_string(utils::get_last_error_code()));
|
||||
}
|
||||
|
||||
const auto total_chunks = utils::divide_with_ceiling(
|
||||
file_size, static_cast<std::uint64_t>(data_chunk_size_));
|
||||
total_size_ = file_size + (total_chunks * encryption_header_size);
|
||||
last_data_chunk_ = total_chunks - 1U;
|
||||
last_data_chunk_size_ = (file_size <= data_chunk_size_) ? file_size
|
||||
: (file_size % data_chunk_size_) == 0U
|
||||
? data_chunk_size_
|
||||
: file_size % data_chunk_size_;
|
||||
iv_list_.resize(total_chunks);
|
||||
for (auto &iv : iv_list_) {
|
||||
randombytes_buf(iv.data(), iv.size());
|
||||
}
|
||||
}
|
||||
|
||||
encrypting_reader::encrypting_reader(std::string_view encrypted_file_path,
|
||||
std::string_view source_path,
|
||||
stop_type &stop_requested,
|
||||
std::string_view token,
|
||||
std::size_t error_return)
|
||||
: key_(utils::encryption::generate_key<utils::encryption::hash_256_t>(
|
||||
token)),
|
||||
stop_requested_(stop_requested),
|
||||
error_return_(error_return) {
|
||||
const auto res = native_file::create_or_open(source_path, true, source_file_);
|
||||
if (res != api_error::success) {
|
||||
throw std::runtime_error("file open failed|src|" +
|
||||
std::string{source_path} + '|' +
|
||||
api_error_to_string(res));
|
||||
}
|
||||
|
||||
encrypted_file_path_ = encrypted_file_path;
|
||||
encrypted_file_name_ =
|
||||
std::filesystem::path(encrypted_file_path_).filename().string();
|
||||
|
||||
std::uint64_t file_size{};
|
||||
if (not utils::file::get_file_size(source_path, file_size)) {
|
||||
throw std::runtime_error("get file size failed|src|" +
|
||||
std::string{source_path} + '|' +
|
||||
std::to_string(utils::get_last_error_code()));
|
||||
}
|
||||
|
||||
const auto total_chunks = utils::divide_with_ceiling(
|
||||
file_size, static_cast<std::uint64_t>(data_chunk_size_));
|
||||
total_size_ = file_size + (total_chunks * encryption_header_size);
|
||||
last_data_chunk_ = total_chunks - 1U;
|
||||
last_data_chunk_size_ = (file_size <= data_chunk_size_) ? file_size
|
||||
: (file_size % data_chunk_size_) == 0U
|
||||
? data_chunk_size_
|
||||
: file_size % data_chunk_size_;
|
||||
iv_list_.resize(total_chunks);
|
||||
for (auto &iv : iv_list_) {
|
||||
randombytes_buf(iv.data(), iv.size());
|
||||
}
|
||||
}
|
||||
|
||||
encrypting_reader::encrypting_reader(
|
||||
std::string_view encrypted_file_path, std::string_view source_path,
|
||||
stop_type &stop_requested, std::string_view token,
|
||||
std::vector<
|
||||
std::array<unsigned char, crypto_aead_xchacha20poly1305_IETF_NPUBBYTES>>
|
||||
iv_list,
|
||||
std::size_t error_return)
|
||||
: key_(utils::encryption::generate_key<utils::encryption::hash_256_t>(
|
||||
token)),
|
||||
stop_requested_(stop_requested),
|
||||
error_return_(error_return) {
|
||||
const auto res = native_file::create_or_open(source_path, true, source_file_);
|
||||
if (res != api_error::success) {
|
||||
throw std::runtime_error("file open failed|src|" +
|
||||
std::string{source_path} + '|' +
|
||||
api_error_to_string(res));
|
||||
}
|
||||
|
||||
encrypted_file_path_ = encrypted_file_path;
|
||||
encrypted_file_name_ =
|
||||
std::filesystem::path(encrypted_file_path_).filename().string();
|
||||
|
||||
std::uint64_t file_size{};
|
||||
if (not utils::file::get_file_size(source_path, file_size)) {
|
||||
throw std::runtime_error("get file size failed|src|" +
|
||||
std::string{source_path} + '|' +
|
||||
std::to_string(utils::get_last_error_code()));
|
||||
}
|
||||
|
||||
const auto total_chunks = utils::divide_with_ceiling(
|
||||
file_size, static_cast<std::uint64_t>(data_chunk_size_));
|
||||
total_size_ = file_size + (total_chunks * encryption_header_size);
|
||||
last_data_chunk_ = total_chunks - 1U;
|
||||
last_data_chunk_size_ = (file_size <= data_chunk_size_) ? file_size
|
||||
: (file_size % data_chunk_size_) == 0U
|
||||
? data_chunk_size_
|
||||
: file_size % data_chunk_size_;
|
||||
iv_list_ = std::move(iv_list);
|
||||
}
|
||||
|
||||
encrypting_reader::encrypting_reader(const encrypting_reader &reader)
|
||||
: key_(reader.key_),
|
||||
stop_requested_(reader.stop_requested_),
|
||||
error_return_(reader.error_return_),
|
||||
chunk_buffers_(reader.chunk_buffers_),
|
||||
encrypted_file_name_(reader.encrypted_file_name_),
|
||||
encrypted_file_path_(reader.encrypted_file_path_),
|
||||
iv_list_(reader.iv_list_),
|
||||
last_data_chunk_(reader.last_data_chunk_),
|
||||
last_data_chunk_size_(reader.last_data_chunk_size_),
|
||||
read_offset_(reader.read_offset_),
|
||||
source_file_(native_file::clone(reader.source_file_)),
|
||||
total_size_(reader.total_size_) {}
|
||||
|
||||
encrypting_reader::~encrypting_reader() {
|
||||
if (source_file_) {
|
||||
source_file_->close();
|
||||
}
|
||||
}
|
||||
|
||||
auto encrypting_reader::calculate_decrypted_size(std::uint64_t total_size)
|
||||
-> std::uint64_t {
|
||||
return total_size - (utils::divide_with_ceiling(
|
||||
total_size, static_cast<std::uint64_t>(
|
||||
get_encrypted_chunk_size())) *
|
||||
encryption_header_size);
|
||||
}
|
||||
|
||||
auto encrypting_reader::calculate_encrypted_size(std::string_view source_path)
|
||||
-> std::uint64_t {
|
||||
std::uint64_t file_size{};
|
||||
if (not utils::file::get_file_size(source_path, file_size)) {
|
||||
throw std::runtime_error("get file size failed|src|" +
|
||||
std::string{source_path} + '|' +
|
||||
std::to_string(utils::get_last_error_code()));
|
||||
}
|
||||
|
||||
const auto total_chunks = utils::divide_with_ceiling(
|
||||
file_size, static_cast<std::uint64_t>(data_chunk_size_));
|
||||
return file_size + (total_chunks * encryption_header_size);
|
||||
}
|
||||
|
||||
auto encrypting_reader::create_iostream() const
|
||||
-> std::shared_ptr<encrypting_reader::iostream> {
|
||||
return std::make_shared<encrypting_reader_iostream>(
|
||||
std::make_unique<encrypting_streambuf>(*this));
|
||||
}
|
||||
|
||||
auto encrypting_reader::reader_function(char *buffer, size_t size,
|
||||
size_t nitems) -> size_t {
|
||||
static constexpr const std::string_view function_name{
|
||||
static_cast<const char *>(__FUNCTION__),
|
||||
};
|
||||
|
||||
const auto read_size = static_cast<std::size_t>(std::min(
|
||||
static_cast<std::uint64_t>(size * nitems), total_size_ - read_offset_));
|
||||
|
||||
auto chunk = read_offset_ / encrypted_chunk_size_;
|
||||
auto chunk_offset = read_offset_ % encrypted_chunk_size_;
|
||||
std::size_t total_read{};
|
||||
|
||||
auto ret = false;
|
||||
if (read_offset_ < total_size_) {
|
||||
try {
|
||||
ret = true;
|
||||
auto remain = read_size;
|
||||
while (not stop_requested_ && ret && (remain != 0U)) {
|
||||
if (chunk_buffers_.find(chunk) == chunk_buffers_.end()) {
|
||||
auto &chunk_buffer = chunk_buffers_[chunk];
|
||||
data_buffer file_data(chunk == last_data_chunk_
|
||||
? last_data_chunk_size_
|
||||
: data_chunk_size_);
|
||||
chunk_buffer.resize(file_data.size() + encryption_header_size);
|
||||
|
||||
std::size_t bytes_read{};
|
||||
if ((ret = source_file_->read_bytes(&file_data[0u], file_data.size(),
|
||||
chunk * data_chunk_size_,
|
||||
bytes_read))) {
|
||||
utils::encryption::encrypt_data(iv_list_.at(chunk), key_, file_data,
|
||||
chunk_buffer);
|
||||
}
|
||||
} else if (chunk) {
|
||||
chunk_buffers_.erase(chunk - 1u);
|
||||
}
|
||||
|
||||
auto &chunk_buffer = chunk_buffers_[chunk];
|
||||
const auto to_read = std::min(
|
||||
static_cast<std::size_t>(chunk_buffer.size() - chunk_offset),
|
||||
remain);
|
||||
std::memcpy(buffer + total_read, &chunk_buffer[chunk_offset], to_read);
|
||||
total_read += to_read;
|
||||
remain -= to_read;
|
||||
chunk_offset = 0u;
|
||||
chunk++;
|
||||
read_offset_ += to_read;
|
||||
}
|
||||
} catch (const std::exception &e) {
|
||||
utils::error::raise_error(function_name, e, "exception occurred");
|
||||
ret = false;
|
||||
}
|
||||
}
|
||||
|
||||
return stop_requested_ ? CURL_READFUNC_ABORT
|
||||
: ret ? total_read
|
||||
: error_return_;
|
||||
}
|
||||
} // namespace repertory::utils::encryption
|
||||
@@ -21,392 +21,77 @@
|
||||
*/
|
||||
#include "utils/file_utils.hpp"
|
||||
|
||||
#include "types/repertory.hpp"
|
||||
#include "utils/collection.hpp"
|
||||
#include "utils/error_utils.hpp"
|
||||
#include "utils/file.hpp"
|
||||
#include "utils/path.hpp"
|
||||
#include "utils/string.hpp"
|
||||
#include "utils/time.hpp"
|
||||
#include "utils/utils.hpp"
|
||||
|
||||
namespace repertory::utils::file {
|
||||
auto calculate_used_space(std::string path, bool recursive) -> std::uint64_t {
|
||||
path = utils::path::absolute(path);
|
||||
std::uint64_t ret{};
|
||||
#if defined(_WIN32)
|
||||
WIN32_FIND_DATA fd{};
|
||||
const auto search = utils::path::combine(path, {"*.*"});
|
||||
auto find = ::FindFirstFile(search.c_str(), &fd);
|
||||
if (find != INVALID_HANDLE_VALUE) {
|
||||
do {
|
||||
const auto file_name = std::string(fd.cFileName);
|
||||
if (fd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) {
|
||||
if (recursive && (file_name != ".") && (file_name != "..")) {
|
||||
ret += calculate_used_space(utils::path::combine(path, {file_name}),
|
||||
recursive);
|
||||
}
|
||||
} else {
|
||||
std::uint64_t file_size{};
|
||||
if (get_file_size(utils::path::combine(path, {file_name}), file_size)) {
|
||||
ret += file_size;
|
||||
}
|
||||
}
|
||||
} while (::FindNextFile(find, &fd) != 0);
|
||||
::FindClose(find);
|
||||
}
|
||||
#else
|
||||
auto *root = opendir(path.c_str());
|
||||
if (root) {
|
||||
struct dirent *de{};
|
||||
while ((de = readdir(root)) != nullptr) {
|
||||
if (de->d_type == DT_DIR) {
|
||||
if (recursive && (strcmp(de->d_name, ".") != 0) &&
|
||||
(strcmp(de->d_name, "..") != 0)) {
|
||||
ret += calculate_used_space(utils::path::combine(path, {de->d_name}),
|
||||
recursive);
|
||||
}
|
||||
} else {
|
||||
std::uint64_t file_size{};
|
||||
if (get_file_size(utils::path::combine(path, {de->d_name}),
|
||||
file_size)) {
|
||||
ret += file_size;
|
||||
}
|
||||
}
|
||||
}
|
||||
closedir(root);
|
||||
}
|
||||
#endif
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
void change_to_process_directory() {
|
||||
#if defined(_WIN32)
|
||||
std::string file_name;
|
||||
file_name.resize(MAX_PATH);
|
||||
::GetModuleFileNameA(nullptr, &file_name[0U],
|
||||
static_cast<DWORD>(file_name.size()));
|
||||
|
||||
std::string path = file_name.c_str();
|
||||
::PathRemoveFileSpecA(&path[0U]);
|
||||
::SetCurrentDirectoryA(&path[0U]);
|
||||
#else
|
||||
std::string path;
|
||||
path.resize(PATH_MAX + 1);
|
||||
#if defined(__APPLE__)
|
||||
proc_pidpath(getpid(), &path[0U], path.size());
|
||||
#else
|
||||
readlink("/proc/self/exe", &path[0U], path.size());
|
||||
#endif
|
||||
path = utils::path::get_parent_directory(path);
|
||||
chdir(path.c_str());
|
||||
#endif
|
||||
}
|
||||
|
||||
auto copy_file(std::string from_path, std::string to_path) -> bool {
|
||||
from_path = utils::path::absolute(from_path);
|
||||
to_path = utils::path::absolute(to_path);
|
||||
if (is_file(from_path) && not is_directory(to_path)) {
|
||||
return std::filesystem::copy_file(from_path, to_path);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
auto copy_directory_recursively(std::string from_path,
|
||||
std::string to_path) -> bool {
|
||||
from_path = utils::path::absolute(from_path);
|
||||
to_path = utils::path::absolute(to_path);
|
||||
auto ret = create_full_directory_path(to_path);
|
||||
if (ret) {
|
||||
#if defined(_WIN32)
|
||||
WIN32_FIND_DATA fd{};
|
||||
const auto search = utils::path::combine(from_path, {"*.*"});
|
||||
auto find = ::FindFirstFile(search.c_str(), &fd);
|
||||
if (find != INVALID_HANDLE_VALUE) {
|
||||
ret = true;
|
||||
do {
|
||||
if (fd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) {
|
||||
if ((std::string(fd.cFileName) != ".") &&
|
||||
(std::string(fd.cFileName) != "..")) {
|
||||
ret = copy_directory_recursively(
|
||||
utils::path::combine(from_path, {fd.cFileName}),
|
||||
utils::path::combine(to_path, {fd.cFileName}));
|
||||
}
|
||||
} else {
|
||||
ret = copy_file(utils::path::combine(from_path, {fd.cFileName}),
|
||||
utils::path::combine(to_path, {fd.cFileName}));
|
||||
}
|
||||
} while (ret && (::FindNextFile(find, &fd) != 0));
|
||||
|
||||
::FindClose(find);
|
||||
}
|
||||
#else
|
||||
auto *root = opendir(from_path.c_str());
|
||||
if (root) {
|
||||
struct dirent *de{};
|
||||
while (ret && (de = readdir(root))) {
|
||||
if (de->d_type == DT_DIR) {
|
||||
if ((strcmp(de->d_name, ".") != 0) &&
|
||||
(strcmp(de->d_name, "..") != 0)) {
|
||||
ret = copy_directory_recursively(
|
||||
utils::path::combine(from_path, {de->d_name}),
|
||||
utils::path::combine(to_path, {de->d_name}));
|
||||
}
|
||||
} else {
|
||||
ret = copy_file(utils::path::combine(from_path, {de->d_name}),
|
||||
utils::path::combine(to_path, {de->d_name}));
|
||||
}
|
||||
}
|
||||
|
||||
closedir(root);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
auto create_full_directory_path(std::string path) -> bool {
|
||||
#if defined(_WIN32)
|
||||
const auto unicode_path =
|
||||
utils::string::from_utf8(utils::path::absolute(path));
|
||||
return is_directory(path) ||
|
||||
(::SHCreateDirectory(nullptr, unicode_path.c_str()) == ERROR_SUCCESS);
|
||||
#else
|
||||
auto ret = true;
|
||||
const auto paths = utils::string::split(
|
||||
utils::path::absolute(path), utils::path::directory_seperator[0U], false);
|
||||
std::string current_path;
|
||||
for (std::size_t i = 0U; ret && (i < paths.size()); i++) {
|
||||
if (paths[i].empty()) { // Skip root
|
||||
current_path = utils::path::directory_seperator;
|
||||
} else {
|
||||
current_path = utils::path::combine(current_path, {paths[i]});
|
||||
const auto status = mkdir(current_path.c_str(), S_IRWXU);
|
||||
ret = ((status == 0) || (errno == EEXIST));
|
||||
}
|
||||
}
|
||||
|
||||
return ret;
|
||||
#endif
|
||||
}
|
||||
|
||||
auto delete_directory(std::string path, bool recursive) -> bool {
|
||||
if (recursive) {
|
||||
return delete_directory_recursively(path);
|
||||
}
|
||||
|
||||
path = utils::path::absolute(path);
|
||||
#if defined(_WIN32)
|
||||
return (not is_directory(path) || utils::retryable_action([&]() -> bool {
|
||||
return !!::RemoveDirectoryA(path.c_str());
|
||||
}));
|
||||
#else
|
||||
return not is_directory(path) || (rmdir(path.c_str()) == 0);
|
||||
#endif
|
||||
}
|
||||
|
||||
auto delete_directory_recursively(std::string path) -> bool {
|
||||
path = utils::path::absolute(path);
|
||||
#if defined(_WIN32)
|
||||
|
||||
WIN32_FIND_DATA fd{};
|
||||
const auto search = utils::path::combine(path, {"*.*"});
|
||||
auto find = ::FindFirstFile(search.c_str(), &fd);
|
||||
if (find != INVALID_HANDLE_VALUE) {
|
||||
auto res = true;
|
||||
do {
|
||||
if (fd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) {
|
||||
if ((std::string(fd.cFileName) != ".") &&
|
||||
(std::string(fd.cFileName) != "..")) {
|
||||
res = delete_directory_recursively(
|
||||
utils::path::combine(path, {fd.cFileName}));
|
||||
}
|
||||
} else {
|
||||
res = retry_delete_file(utils::path::combine(path, {fd.cFileName}));
|
||||
}
|
||||
} while (res && (::FindNextFile(find, &fd) != 0));
|
||||
|
||||
::FindClose(find);
|
||||
}
|
||||
#else
|
||||
auto *root = opendir(path.c_str());
|
||||
if (root) {
|
||||
auto res = true;
|
||||
struct dirent *de{};
|
||||
while (res && (de = readdir(root))) {
|
||||
if (de->d_type == DT_DIR) {
|
||||
if ((strcmp(de->d_name, ".") != 0) && (strcmp(de->d_name, "..") != 0)) {
|
||||
res = delete_directory_recursively(
|
||||
utils::path::combine(path, {de->d_name}));
|
||||
}
|
||||
} else {
|
||||
res = retry_delete_file(utils::path::combine(path, {de->d_name}));
|
||||
}
|
||||
}
|
||||
|
||||
closedir(root);
|
||||
}
|
||||
#endif
|
||||
|
||||
return delete_directory(path, false);
|
||||
}
|
||||
|
||||
auto delete_file(std::string path) -> bool {
|
||||
path = utils::path::absolute(path);
|
||||
#if defined(_WIN32)
|
||||
return (not is_file(path) || utils::retryable_action([&]() -> bool {
|
||||
const auto ret = !!::DeleteFileA(path.c_str());
|
||||
if (not ret) {
|
||||
std::cout << "delete failed:" << path << std::endl;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}));
|
||||
#else
|
||||
return (not is_file(path) || (unlink(path.c_str()) == 0));
|
||||
#endif
|
||||
}
|
||||
|
||||
auto generate_sha256(const std::string &file_path) -> std::string {
|
||||
crypto_hash_sha256_state state{};
|
||||
auto res = crypto_hash_sha256_init(&state);
|
||||
if (res != 0) {
|
||||
throw std::runtime_error("failed to initialize sha256|" +
|
||||
std::to_string(res));
|
||||
}
|
||||
|
||||
native_file_ptr nf;
|
||||
if (native_file::open(file_path, nf) != api_error::success) {
|
||||
throw std::runtime_error("failed to open file|" + file_path);
|
||||
}
|
||||
|
||||
{
|
||||
data_buffer buffer(1048576u);
|
||||
std::uint64_t read_offset = 0U;
|
||||
std::size_t bytes_read = 0U;
|
||||
while (
|
||||
nf->read_bytes(buffer.data(), buffer.size(), read_offset, bytes_read)) {
|
||||
if (not bytes_read) {
|
||||
break;
|
||||
}
|
||||
|
||||
read_offset += bytes_read;
|
||||
res = crypto_hash_sha256_update(
|
||||
&state, reinterpret_cast<const unsigned char *>(buffer.data()),
|
||||
bytes_read);
|
||||
if (res != 0) {
|
||||
nf->close();
|
||||
throw std::runtime_error("failed to update sha256|" +
|
||||
std::to_string(res));
|
||||
}
|
||||
}
|
||||
nf->close();
|
||||
}
|
||||
|
||||
std::array<unsigned char, crypto_hash_sha256_BYTES> out{};
|
||||
res = crypto_hash_sha256_final(&state, out.data());
|
||||
if (res != 0) {
|
||||
throw std::runtime_error("failed to finalize sha256|" +
|
||||
std::to_string(res));
|
||||
}
|
||||
|
||||
return utils::collection::to_hex_string(out);
|
||||
}
|
||||
|
||||
auto get_free_drive_space(const std::string &path) -> std::uint64_t {
|
||||
#if defined(_WIN32)
|
||||
ULARGE_INTEGER li{};
|
||||
::GetDiskFreeSpaceEx(path.c_str(), &li, nullptr, nullptr);
|
||||
return li.QuadPart;
|
||||
#endif
|
||||
#if defined(__linux__)
|
||||
std::uint64_t ret = 0;
|
||||
struct statfs64 st {};
|
||||
if (statfs64(path.c_str(), &st) == 0) {
|
||||
ret = st.f_bfree * st.f_bsize;
|
||||
}
|
||||
return ret;
|
||||
#endif
|
||||
#if defined(__APPLE__)
|
||||
struct statvfs st {};
|
||||
statvfs(path.c_str(), &st);
|
||||
return st.f_bfree * st.f_frsize;
|
||||
#endif
|
||||
}
|
||||
|
||||
auto get_total_drive_space(const std::string &path) -> std::uint64_t {
|
||||
#if defined(_WIN32)
|
||||
ULARGE_INTEGER li{};
|
||||
::GetDiskFreeSpaceEx(path.c_str(), nullptr, &li, nullptr);
|
||||
return li.QuadPart;
|
||||
#endif
|
||||
#if defined(__linux__)
|
||||
std::uint64_t ret = 0;
|
||||
struct statfs64 st {};
|
||||
if (statfs64(path.c_str(), &st) == 0) {
|
||||
ret = st.f_blocks * st.f_bsize;
|
||||
}
|
||||
return ret;
|
||||
#endif
|
||||
#if defined(__APPLE__)
|
||||
struct statvfs st {};
|
||||
statvfs(path.c_str(), &st);
|
||||
return st.f_blocks * st.f_frsize;
|
||||
#endif
|
||||
}
|
||||
|
||||
auto get_directory_files(std::string path, bool oldest_first,
|
||||
auto get_directory_files(std::string_view path, bool oldest_first,
|
||||
bool recursive) -> std::deque<std::string> {
|
||||
path = utils::path::absolute(path);
|
||||
static constexpr const std::string_view function_name{
|
||||
static_cast<const char *>(__FUNCTION__),
|
||||
};
|
||||
|
||||
auto abs_path = utils::path::absolute(path);
|
||||
std::deque<std::string> ret;
|
||||
std::unordered_map<std::string, std::uint64_t> lookup;
|
||||
#if defined(_WIN32)
|
||||
WIN32_FIND_DATA fd{};
|
||||
const auto search = utils::path::combine(path, {"*.*"});
|
||||
auto search = utils::path::combine(abs_path, {"*.*"});
|
||||
auto find = ::FindFirstFile(search.c_str(), &fd);
|
||||
if (find != INVALID_HANDLE_VALUE) {
|
||||
do {
|
||||
const auto full_path = utils::path::combine(path, {fd.cFileName});
|
||||
if ((fd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) ==
|
||||
FILE_ATTRIBUTE_DIRECTORY) {
|
||||
if (recursive) {
|
||||
const auto sub_files =
|
||||
get_directory_files(full_path, oldest_first, recursive);
|
||||
ret.insert(ret.end(), sub_files.begin(), sub_files.end());
|
||||
} else {
|
||||
ULARGE_INTEGER li{};
|
||||
li.HighPart = fd.ftLastWriteTime.dwHighDateTime;
|
||||
li.LowPart = fd.ftLastWriteTime.dwLowDateTime;
|
||||
lookup[full_path] = li.QuadPart;
|
||||
ret.emplace_back(full_path);
|
||||
try {
|
||||
do {
|
||||
auto full_path = utils::path::combine(abs_path, {fd.cFileName});
|
||||
if ((fd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) ==
|
||||
FILE_ATTRIBUTE_DIRECTORY) {
|
||||
if (recursive) {
|
||||
auto sub_files =
|
||||
get_directory_files(full_path, oldest_first, recursive);
|
||||
ret.insert(ret.end(), sub_files.begin(), sub_files.end());
|
||||
} else {
|
||||
ULARGE_INTEGER li{};
|
||||
li.HighPart = fd.ftLastWriteTime.dwHighDateTime;
|
||||
li.LowPart = fd.ftLastWriteTime.dwLowDateTime;
|
||||
lookup[full_path] = li.QuadPart;
|
||||
ret.emplace_back(full_path);
|
||||
}
|
||||
}
|
||||
}
|
||||
} while (::FindNextFile(find, &fd) != 0);
|
||||
} while (::FindNextFile(find, &fd) != 0);
|
||||
} catch (const std::exception &e) {
|
||||
utils::error::raise_error(function_name, e,
|
||||
"failed to get directory files");
|
||||
}
|
||||
::FindClose(find);
|
||||
|
||||
std::sort(ret.begin(), ret.end(),
|
||||
[&](const auto &p1, const auto &p2) -> bool {
|
||||
return (oldest_first != 0) == (lookup[p1] < lookup[p2]);
|
||||
});
|
||||
std::sort(ret.begin(), ret.end(), [&](auto &&path1, auto &&path2) -> bool {
|
||||
return (oldest_first != 0) == (lookup[path1] < lookup[path2]);
|
||||
});
|
||||
}
|
||||
#else
|
||||
auto *root = opendir(path.c_str());
|
||||
#else // !defined(_WIN32)
|
||||
auto *root = opendir(abs_path.c_str());
|
||||
if (root) {
|
||||
struct dirent *de{};
|
||||
while ((de = readdir(root)) != nullptr) {
|
||||
if (de->d_type == DT_DIR) {
|
||||
if (recursive) {
|
||||
const auto sub_files =
|
||||
get_directory_files(utils::path::combine(path, {de->d_name}),
|
||||
oldest_first, recursive);
|
||||
ret.insert(ret.end(), sub_files.begin(), sub_files.end());
|
||||
try {
|
||||
struct dirent *de{};
|
||||
while ((de = readdir(root)) != nullptr) {
|
||||
if (de->d_type == DT_DIR) {
|
||||
if (recursive) {
|
||||
auto sub_files = get_directory_files(
|
||||
utils::path::combine(abs_path, {de->d_name}), oldest_first,
|
||||
recursive);
|
||||
ret.insert(ret.end(), sub_files.begin(), sub_files.end());
|
||||
}
|
||||
} else {
|
||||
ret.emplace_back(utils::path::combine(abs_path, {de->d_name}));
|
||||
}
|
||||
} else {
|
||||
ret.emplace_back(utils::path::combine(path, {de->d_name}));
|
||||
}
|
||||
} catch (const std::exception &e) {
|
||||
utils::error::raise_error(function_name, e,
|
||||
"failed to get directory files");
|
||||
}
|
||||
|
||||
closedir(root);
|
||||
|
||||
const auto add_to_lookup = [&](const std::string &lookup_path) {
|
||||
@@ -414,118 +99,32 @@ auto get_directory_files(std::string path, bool oldest_first,
|
||||
struct stat st {};
|
||||
stat(lookup_path.c_str(), &st);
|
||||
#if defined(__APPLE__)
|
||||
lookup[lookup_path] = static_cast<std::uint64_t>(
|
||||
(st.st_mtimespec.tv_sec * NANOS_PER_SECOND) +
|
||||
st.st_mtimespec.tv_nsec);
|
||||
#else
|
||||
lookup[lookup_path] = static_cast<std::uint64_t>(
|
||||
(st.st_mtim.tv_sec * NANOS_PER_SECOND) + st.st_mtim.tv_nsec);
|
||||
#endif
|
||||
lookup[lookup_path] =
|
||||
(static_cast<std::uint64_t>(st.st_mtimespec.tv_sec) *
|
||||
utils::time::NANOS_PER_SECOND) +
|
||||
static_cast<std::uint64_t>(st.st_mtimespec.tv_nsec);
|
||||
#else // !defined(__APPLE__)
|
||||
lookup[lookup_path] = (static_cast<std::uint64_t>(st.st_mtim.tv_sec) *
|
||||
utils::time::NANOS_PER_SECOND) +
|
||||
static_cast<std::uint64_t>(st.st_mtim.tv_nsec);
|
||||
#endif // defined(__APPLE__)
|
||||
}
|
||||
};
|
||||
|
||||
std::sort(ret.begin(), ret.end(),
|
||||
[&](const auto &p1, const auto &p2) -> bool {
|
||||
add_to_lookup(p1);
|
||||
add_to_lookup(p2);
|
||||
return (oldest_first != 0) == (lookup[p1] < lookup[p2]);
|
||||
});
|
||||
std::sort(ret.begin(), ret.end(), [&](auto &&path1, auto &&path2) -> bool {
|
||||
add_to_lookup(path1);
|
||||
add_to_lookup(path2);
|
||||
return (oldest_first != 0) == (lookup.at(path1) < lookup.at(path2));
|
||||
});
|
||||
}
|
||||
#endif
|
||||
return ret;
|
||||
}
|
||||
|
||||
auto get_accessed_time(const std::string &path,
|
||||
std::uint64_t &accessed) -> bool {
|
||||
auto ret = false;
|
||||
accessed = 0;
|
||||
#if defined(_WIN32)
|
||||
struct _stat64 st {};
|
||||
if (_stat64(path.c_str(), &st) != -1) {
|
||||
accessed = static_cast<uint64_t>(st.st_atime);
|
||||
#else
|
||||
struct stat st {};
|
||||
if (stat(path.c_str(), &st) != -1) {
|
||||
#if defined(__APPLE__)
|
||||
accessed = static_cast<uint64_t>(
|
||||
st.st_atimespec.tv_nsec + (st.st_atimespec.tv_sec * NANOS_PER_SECOND));
|
||||
#else
|
||||
accessed = static_cast<uint64_t>(st.st_atim.tv_nsec +
|
||||
(st.st_atim.tv_sec * NANOS_PER_SECOND));
|
||||
#endif
|
||||
#endif
|
||||
ret = true;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
auto get_modified_time(const std::string &path,
|
||||
std::uint64_t &modified) -> bool {
|
||||
auto ret = false;
|
||||
modified = 0U;
|
||||
#if defined(_WIN32)
|
||||
struct _stat64 st {};
|
||||
if (_stat64(path.c_str(), &st) != -1) {
|
||||
modified = static_cast<uint64_t>(st.st_mtime);
|
||||
#else
|
||||
struct stat st {};
|
||||
if (stat(path.c_str(), &st) != -1) {
|
||||
#if defined(__APPLE__)
|
||||
modified = static_cast<uint64_t>(
|
||||
st.st_mtimespec.tv_nsec + (st.st_mtimespec.tv_sec * NANOS_PER_SECOND));
|
||||
#else
|
||||
modified = static_cast<uint64_t>(st.st_mtim.tv_nsec +
|
||||
(st.st_mtim.tv_sec * NANOS_PER_SECOND));
|
||||
#endif
|
||||
#endif
|
||||
ret = true;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
auto is_modified_date_older_than(const std::string &path,
|
||||
const std::chrono::hours &hours) -> bool {
|
||||
auto ret = false;
|
||||
std::uint64_t modified{};
|
||||
if (get_modified_time(path, modified)) {
|
||||
const auto seconds =
|
||||
std::chrono::duration_cast<std::chrono::seconds>(hours);
|
||||
#if defined(_WIN32)
|
||||
return (std::chrono::system_clock::from_time_t(
|
||||
static_cast<time_t>(modified)) +
|
||||
seconds) < std::chrono::system_clock::now();
|
||||
#else
|
||||
return (modified +
|
||||
static_cast<std::uint64_t>(seconds.count() * NANOS_PER_SECOND)) <
|
||||
utils::time::get_time_now();
|
||||
#endif
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
auto move_file(std::string from, std::string to) -> bool {
|
||||
from = utils::path::absolute(from);
|
||||
to = utils::path::absolute(to);
|
||||
|
||||
const auto directory = utils::path::remove_file_name(to);
|
||||
if (not create_full_directory_path(directory)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
#if defined(_WIN32)
|
||||
const bool ret = ::MoveFile(from.c_str(), to.c_str()) != 0;
|
||||
#else
|
||||
const bool ret = (rename(from.c_str(), to.c_str()) == 0);
|
||||
#endif
|
||||
#endif // defined(_WIN32)
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
auto read_file_lines(const std::string &path) -> std::vector<std::string> {
|
||||
std::vector<std::string> ret;
|
||||
if (is_file(path)) {
|
||||
if (utils::file::file(path).exists()) {
|
||||
std::ifstream fs(path);
|
||||
std::string current_line;
|
||||
while (not fs.eof() && std::getline(fs, current_line)) {
|
||||
@@ -538,7 +137,7 @@ auto read_file_lines(const std::string &path) -> std::vector<std::string> {
|
||||
}
|
||||
|
||||
auto reset_modified_time(const std::string &path) -> bool {
|
||||
auto ret = false;
|
||||
auto ret{false};
|
||||
#if defined(_WIN32)
|
||||
SYSTEMTIME st{};
|
||||
::GetSystemTime(&st);
|
||||
@@ -554,33 +153,14 @@ auto reset_modified_time(const std::string &path) -> bool {
|
||||
::CloseHandle(handle);
|
||||
}
|
||||
}
|
||||
#else
|
||||
#else // !defined(_WIN32)
|
||||
auto fd = open(path.c_str(), O_RDWR);
|
||||
if ((ret = (fd != -1))) {
|
||||
ret = not futimens(fd, nullptr);
|
||||
ret = futimens(fd, nullptr) == 0;
|
||||
close(fd);
|
||||
}
|
||||
#endif
|
||||
#endif // defined(_WIN32)
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
auto retry_delete_directory(const std::string &dir) -> bool {
|
||||
auto deleted = false;
|
||||
for (std::uint8_t i = 0U; not(deleted = delete_directory(dir)) && (i < 200U);
|
||||
i++) {
|
||||
std::this_thread::sleep_for(10ms);
|
||||
}
|
||||
|
||||
return deleted;
|
||||
}
|
||||
|
||||
auto retry_delete_file(const std::string &file) -> bool {
|
||||
auto deleted = false;
|
||||
for (std::uint8_t i = 0U; not(deleted = delete_file(file)) && (i < 200U);
|
||||
i++) {
|
||||
std::this_thread::sleep_for(10ms);
|
||||
}
|
||||
|
||||
return deleted;
|
||||
}
|
||||
} // namespace repertory::utils::file
|
||||
|
||||
@@ -1,319 +0,0 @@
|
||||
/*
|
||||
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 "utils/native_file.hpp"
|
||||
|
||||
#include "platform/platform.hpp"
|
||||
#include "types/repertory.hpp"
|
||||
#include "utils/string.hpp"
|
||||
#include "utils/utils.hpp"
|
||||
|
||||
namespace repertory {
|
||||
auto native_file::get_handle() -> native_handle { return handle_; }
|
||||
|
||||
native_file::~native_file() {
|
||||
if (auto_close) {
|
||||
close();
|
||||
}
|
||||
}
|
||||
|
||||
auto native_file::clone(const native_file_ptr &ptr) -> native_file_ptr {
|
||||
std::string source_path;
|
||||
|
||||
#if defined(_WIN32)
|
||||
source_path.resize(MAX_PATH + 1);
|
||||
::GetFinalPathNameByHandleA(ptr->get_handle(), source_path.data(),
|
||||
MAX_PATH + 1,
|
||||
FILE_NAME_NORMALIZED | VOLUME_NAME_DOS);
|
||||
#else
|
||||
source_path.resize(PATH_MAX + 1);
|
||||
#if defined(__APPLE__)
|
||||
fcntl(ptr->get_handle(), F_GETPATH, source_path.data());
|
||||
#else
|
||||
readlink(("/proc/self/fd/" + std::to_string(ptr->get_handle())).c_str(),
|
||||
source_path.data(), source_path.size());
|
||||
#endif
|
||||
#endif
|
||||
source_path = source_path.c_str();
|
||||
|
||||
native_file_ptr clone;
|
||||
auto res = native_file::open(source_path, clone);
|
||||
if (res != api_error::success) {
|
||||
throw std::runtime_error("unable to open file|sp|" + source_path + "|err|" +
|
||||
api_error_to_string(res));
|
||||
}
|
||||
|
||||
return clone;
|
||||
}
|
||||
|
||||
auto native_file::create_or_open(std::string_view source_path, bool read_only,
|
||||
native_file_ptr &ptr) -> api_error {
|
||||
#if defined(_WIN32)
|
||||
auto handle =
|
||||
read_only ? ::CreateFileA(std::string{source_path}.c_str(), GENERIC_READ,
|
||||
FILE_SHARE_READ | FILE_SHARE_WRITE, nullptr,
|
||||
OPEN_ALWAYS, FILE_FLAG_RANDOM_ACCESS, nullptr)
|
||||
: ::CreateFileA(std::string{source_path}.c_str(),
|
||||
GENERIC_READ | GENERIC_WRITE,
|
||||
FILE_SHARE_READ | FILE_SHARE_WRITE, nullptr,
|
||||
OPEN_ALWAYS, FILE_FLAG_RANDOM_ACCESS, nullptr);
|
||||
#else
|
||||
auto handle = read_only ? ::open(std::string{source_path}.c_str(),
|
||||
O_CREAT | O_RDONLY | O_CLOEXEC, 0600U)
|
||||
: ::open(std::string{source_path}.c_str(),
|
||||
O_CREAT | O_RDWR | O_CLOEXEC, 0600U);
|
||||
if (not read_only) {
|
||||
chmod(std::string{source_path}.c_str(), 0600U);
|
||||
}
|
||||
#endif
|
||||
ptr = native_file::attach(handle);
|
||||
return ((handle == REPERTORY_INVALID_HANDLE) ? api_error::os_error
|
||||
: api_error::success);
|
||||
}
|
||||
|
||||
auto native_file::create_or_open(std::string_view source_path,
|
||||
native_file_ptr &ptr) -> api_error {
|
||||
return create_or_open(source_path, false, ptr);
|
||||
}
|
||||
|
||||
auto native_file::open(std::string_view source_path,
|
||||
native_file_ptr &ptr) -> api_error {
|
||||
return open(source_path, false, ptr);
|
||||
}
|
||||
|
||||
auto native_file::open(std::string_view source_path, bool read_only,
|
||||
native_file_ptr &ptr) -> api_error {
|
||||
#if defined(_WIN32)
|
||||
auto handle =
|
||||
read_only
|
||||
? ::CreateFileA(std::string{source_path}.c_str(), GENERIC_READ,
|
||||
FILE_SHARE_READ | FILE_SHARE_WRITE, nullptr,
|
||||
OPEN_EXISTING, FILE_FLAG_RANDOM_ACCESS, nullptr)
|
||||
: ::CreateFileA(std::string{source_path}.c_str(),
|
||||
GENERIC_READ | GENERIC_WRITE,
|
||||
FILE_SHARE_READ | FILE_SHARE_WRITE, nullptr,
|
||||
OPEN_EXISTING, FILE_FLAG_RANDOM_ACCESS, nullptr);
|
||||
#else
|
||||
auto handle =
|
||||
read_only ? ::open(std::string{source_path}.c_str(), O_RDONLY | O_CLOEXEC)
|
||||
: ::open(std::string{source_path}.c_str(), O_RDWR | O_CLOEXEC);
|
||||
if (not read_only) {
|
||||
chmod(std::string{source_path}.c_str(), 0600U);
|
||||
}
|
||||
#endif
|
||||
ptr = native_file::attach(handle);
|
||||
return ((handle == REPERTORY_INVALID_HANDLE) ? api_error::os_error
|
||||
: api_error::success);
|
||||
}
|
||||
|
||||
auto native_file::allocate(std::uint64_t file_size) -> bool {
|
||||
#if defined(_WIN32)
|
||||
LARGE_INTEGER li{};
|
||||
li.QuadPart = static_cast<LONGLONG>(file_size);
|
||||
return (::SetFilePointerEx(handle_, li, nullptr, FILE_BEGIN) &&
|
||||
::SetEndOfFile(handle_));
|
||||
#endif
|
||||
#if defined(__linux__)
|
||||
return (fallocate(handle_, 0, 0, static_cast<off_t>(file_size)) >= 0);
|
||||
#endif
|
||||
#if defined(__APPLE__)
|
||||
return (ftruncate(handle_, file_size) >= 0);
|
||||
#endif
|
||||
}
|
||||
|
||||
void native_file::close() {
|
||||
if (handle_ != REPERTORY_INVALID_HANDLE) {
|
||||
#if defined(_WIN32)
|
||||
::CloseHandle(handle_);
|
||||
#else
|
||||
::close(handle_);
|
||||
#endif
|
||||
handle_ = REPERTORY_INVALID_HANDLE;
|
||||
}
|
||||
}
|
||||
|
||||
auto native_file::copy_from(const native_file_ptr &ptr) -> bool {
|
||||
std::uint64_t file_size{};
|
||||
auto ret = ptr->get_file_size(file_size);
|
||||
if (ret) {
|
||||
data_buffer buffer;
|
||||
buffer.resize(65536ULL * 2ULL);
|
||||
std::uint64_t offset{};
|
||||
while (ret && (file_size > 0U)) {
|
||||
std::size_t bytes_read{};
|
||||
ret = ptr->read_bytes(buffer.data(), buffer.size(), offset, bytes_read);
|
||||
if (ret) {
|
||||
std::size_t bytes_written{};
|
||||
ret = write_bytes(buffer.data(), bytes_read, offset, bytes_written);
|
||||
file_size -= bytes_read;
|
||||
offset += bytes_read;
|
||||
}
|
||||
}
|
||||
flush();
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
auto native_file::copy_from(const std::string &path) -> bool {
|
||||
auto ret = false;
|
||||
native_file_ptr ptr;
|
||||
if (native_file::create_or_open(path, ptr) == api_error ::success) {
|
||||
ret = copy_from(ptr);
|
||||
ptr->close();
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
void native_file::flush() {
|
||||
#if defined(_WIN32)
|
||||
recur_mutex_lock l(read_write_mutex_);
|
||||
::FlushFileBuffers(handle_);
|
||||
#else
|
||||
fsync(handle_);
|
||||
#endif
|
||||
}
|
||||
|
||||
auto native_file::get_file_size(std::uint64_t &file_size) -> bool {
|
||||
auto ret = false;
|
||||
#if defined(_WIN32)
|
||||
LARGE_INTEGER li{};
|
||||
if ((ret = ::GetFileSizeEx(handle_, &li) && (li.QuadPart >= 0))) {
|
||||
file_size = static_cast<std::uint64_t>(li.QuadPart);
|
||||
}
|
||||
#else
|
||||
#if defined(__APPLE__)
|
||||
struct stat unix_st {};
|
||||
if (fstat(handle_, &unix_st) >= 0) {
|
||||
#else
|
||||
struct stat64 unix_st {};
|
||||
if (fstat64(handle_, &unix_st) >= 0) {
|
||||
#endif
|
||||
ret = (unix_st.st_size >= 0);
|
||||
if (ret) {
|
||||
file_size = static_cast<uint64_t>(unix_st.st_size);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
return ret;
|
||||
}
|
||||
|
||||
#if defined(_WIN32)
|
||||
auto native_file::read_bytes(unsigned char *buffer, std::size_t read_size,
|
||||
std::uint64_t read_offset,
|
||||
std::size_t &bytes_read) -> bool {
|
||||
recur_mutex_lock l(read_write_mutex_);
|
||||
|
||||
auto ret = false;
|
||||
bytes_read = 0u;
|
||||
LARGE_INTEGER li{};
|
||||
li.QuadPart = static_cast<LONGLONG>(read_offset);
|
||||
if ((ret = !!::SetFilePointerEx(handle_, li, nullptr, FILE_BEGIN))) {
|
||||
DWORD current_read = 0u;
|
||||
do {
|
||||
current_read = 0u;
|
||||
ret = !!::ReadFile(handle_, &buffer[bytes_read],
|
||||
static_cast<DWORD>(read_size - bytes_read),
|
||||
¤t_read, nullptr);
|
||||
bytes_read += current_read;
|
||||
} while (ret && (bytes_read < read_size) && (current_read != 0));
|
||||
}
|
||||
|
||||
if (ret && (read_size != bytes_read)) {
|
||||
::SetLastError(ERROR_HANDLE_EOF);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
#else
|
||||
auto native_file::read_bytes(unsigned char *buffer, std::size_t read_size,
|
||||
std::uint64_t read_offset,
|
||||
std::size_t &bytes_read) -> bool {
|
||||
bytes_read = 0U;
|
||||
ssize_t result = 0;
|
||||
do {
|
||||
result = pread64(handle_, &buffer[bytes_read], read_size - bytes_read,
|
||||
static_cast<off_t>(read_offset + bytes_read));
|
||||
if (result > 0) {
|
||||
bytes_read += static_cast<size_t>(result);
|
||||
}
|
||||
} while ((result > 0) && (bytes_read < read_size));
|
||||
|
||||
return (result >= 0);
|
||||
}
|
||||
#endif
|
||||
auto native_file::truncate(std::uint64_t file_size) -> bool {
|
||||
#if defined(_WIN32)
|
||||
recur_mutex_lock l(read_write_mutex_);
|
||||
LARGE_INTEGER li{};
|
||||
li.QuadPart = static_cast<LONGLONG>(file_size);
|
||||
return (::SetFilePointerEx(handle_, li, nullptr, FILE_BEGIN) &&
|
||||
::SetEndOfFile(handle_));
|
||||
#else
|
||||
return (ftruncate(handle_, static_cast<off_t>(file_size)) >= 0);
|
||||
#endif
|
||||
}
|
||||
|
||||
#if defined(_WIN32)
|
||||
auto native_file::write_bytes(const unsigned char *buffer,
|
||||
std::size_t write_size,
|
||||
std::uint64_t write_offset,
|
||||
std::size_t &bytes_written) -> bool {
|
||||
recur_mutex_lock l(read_write_mutex_);
|
||||
|
||||
bytes_written = 0u;
|
||||
auto ret = true;
|
||||
|
||||
LARGE_INTEGER li{};
|
||||
li.QuadPart = static_cast<LONGLONG>(write_offset);
|
||||
if ((ret = !!::SetFilePointerEx(handle_, li, nullptr, FILE_BEGIN))) {
|
||||
do {
|
||||
DWORD current_write = 0u;
|
||||
ret = !!::WriteFile(handle_, &buffer[bytes_written],
|
||||
static_cast<DWORD>(write_size - bytes_written),
|
||||
¤t_write, nullptr);
|
||||
bytes_written += current_write;
|
||||
} while (ret && (bytes_written < write_size));
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
#else
|
||||
auto native_file::write_bytes(const unsigned char *buffer,
|
||||
std::size_t write_size,
|
||||
std::uint64_t write_offset,
|
||||
std::size_t &bytes_written) -> bool {
|
||||
bytes_written = 0U;
|
||||
ssize_t result{};
|
||||
do {
|
||||
result =
|
||||
pwrite64(handle_, &buffer[bytes_written], write_size - bytes_written,
|
||||
static_cast<off_t>(write_offset + bytes_written));
|
||||
if (result > 0) {
|
||||
bytes_written += static_cast<size_t>(result);
|
||||
}
|
||||
} while ((result >= 0) && (bytes_written < write_size));
|
||||
|
||||
return (bytes_written == write_size);
|
||||
}
|
||||
#endif
|
||||
} // namespace repertory
|
||||
@@ -201,10 +201,6 @@ auto unix_error_to_windows(int err) -> std::uint32_t {
|
||||
}
|
||||
}
|
||||
|
||||
auto unix_time_to_windows_time(const remote::file_time &file_time) -> UINT64 {
|
||||
return (file_time / 100ULL) + 116444736000000000ULL;
|
||||
}
|
||||
|
||||
void windows_create_to_unix(const UINT32 &create_options,
|
||||
const UINT32 &granted_access, std::uint32_t &flags,
|
||||
remote::file_mode &mode) {
|
||||
@@ -221,10 +217,6 @@ void windows_create_to_unix(const UINT32 &create_options,
|
||||
mode |= (S_IXUSR);
|
||||
}
|
||||
}
|
||||
|
||||
auto windows_time_to_unix_time(std::uint64_t win_time) -> remote::file_time {
|
||||
return (win_time - 116444736000000000ULL) * 100ULL;
|
||||
}
|
||||
} // namespace repertory::utils
|
||||
|
||||
#endif // !_WIN32
|
||||
|
||||
@@ -22,16 +22,8 @@
|
||||
#include "utils/utils.hpp"
|
||||
|
||||
#include "app_config.hpp"
|
||||
#include "events/event_system.hpp"
|
||||
#include "events/events.hpp"
|
||||
#include "providers/i_provider.hpp"
|
||||
#include "types/startup_exception.hpp"
|
||||
#include "utils/com_init_wrapper.hpp"
|
||||
#include "utils/common.hpp"
|
||||
#include "utils/native_file.hpp"
|
||||
#include "utils/path.hpp"
|
||||
#include "utils/string.hpp"
|
||||
#include "utils/time.hpp"
|
||||
|
||||
namespace repertory::utils {
|
||||
void calculate_allocation_size(bool directory, std::uint64_t file_size,
|
||||
@@ -53,32 +45,6 @@ void calculate_allocation_size(bool directory, std::uint64_t file_size,
|
||||
allocation_meta_size = std::to_string(allocation_size);
|
||||
}
|
||||
|
||||
auto convert_api_date(const std::string &date) -> std::uint64_t {
|
||||
// 2009-10-12T17:50:30.000Z
|
||||
const auto date_parts = utils::string::split(date, '.', true);
|
||||
const auto date_time = date_parts[0U];
|
||||
const auto nanos = utils::string::to_uint64(
|
||||
utils::string::split(date_parts[1U], 'Z', true)[0U]);
|
||||
|
||||
struct tm tm1 {};
|
||||
#if defined(_WIN32)
|
||||
utils::time::strptime(date_time.c_str(), "%Y-%m-%dT%T", &tm1);
|
||||
#else
|
||||
strptime(date_time.c_str(), "%Y-%m-%dT%T", &tm1);
|
||||
#endif
|
||||
return nanos + (static_cast<std::uint64_t>(mktime(&tm1)) * NANOS_PER_SECOND);
|
||||
}
|
||||
|
||||
auto create_curl() -> CURL * {
|
||||
static std::recursive_mutex mtx;
|
||||
|
||||
unique_recur_mutex_lock lock(mtx);
|
||||
curl_global_init(CURL_GLOBAL_DEFAULT);
|
||||
lock.unlock();
|
||||
|
||||
return reset_curl(curl_easy_init());
|
||||
}
|
||||
|
||||
auto create_volume_label(const provider_type &prov) -> std::string {
|
||||
return "repertory_" + app_config::get_provider_name(prov);
|
||||
}
|
||||
@@ -86,54 +52,4 @@ auto create_volume_label(const provider_type &prov) -> std::string {
|
||||
auto get_attributes_from_meta(const api_meta_map &meta) -> DWORD {
|
||||
return static_cast<DWORD>(utils::string::to_uint32(meta.at(META_ATTRIBUTES)));
|
||||
}
|
||||
|
||||
auto reset_curl(CURL *curl_handle) -> CURL * {
|
||||
curl_easy_reset(curl_handle);
|
||||
#if defined(__APPLE__)
|
||||
curl_easy_setopt(curl_handle, CURLOPT_NOSIGNAL, 1);
|
||||
#endif
|
||||
return curl_handle;
|
||||
}
|
||||
|
||||
auto retryable_action(const std::function<bool()> &action) -> bool {
|
||||
static constexpr const auto retry_count = 20U;
|
||||
|
||||
auto succeeded = false;
|
||||
for (std::uint8_t i = 0U; not(succeeded = action()) && (i < retry_count);
|
||||
i++) {
|
||||
std::this_thread::sleep_for(100ms);
|
||||
}
|
||||
return succeeded;
|
||||
}
|
||||
|
||||
void spin_wait_for_mutex(std::function<bool()> complete,
|
||||
std::condition_variable &cond, std::mutex &mtx,
|
||||
const std::string &text) {
|
||||
while (not complete()) {
|
||||
unique_mutex_lock lock(mtx);
|
||||
if (not complete()) {
|
||||
if (not text.empty()) {
|
||||
/* event_system::instance().raise<DebugLog>(__FUNCTION__,
|
||||
* "spin_wait_for_mutex", text); */
|
||||
}
|
||||
cond.wait_for(lock, 1s);
|
||||
}
|
||||
lock.unlock();
|
||||
}
|
||||
}
|
||||
|
||||
void spin_wait_for_mutex(bool &complete, std::condition_variable &cond,
|
||||
std::mutex &mtx, const std::string &text) {
|
||||
while (not complete) {
|
||||
unique_mutex_lock lock(mtx);
|
||||
if (not complete) {
|
||||
if (not text.empty()) {
|
||||
/* event_system::instance().raise<DebugLog>(__FUNCTION__,
|
||||
* "spin_wait_for_mutex", text); */
|
||||
}
|
||||
cond.wait_for(lock, 1s);
|
||||
}
|
||||
lock.unlock();
|
||||
}
|
||||
}
|
||||
} // namespace repertory::utils
|
||||
|
||||
@@ -23,9 +23,8 @@
|
||||
|
||||
#include "utils/windows/windows_utils.hpp"
|
||||
|
||||
#include "types/startup_exception.hpp"
|
||||
#include "utils/com_init_wrapper.hpp"
|
||||
#include "utils/string.hpp"
|
||||
#include "utils/time.hpp"
|
||||
|
||||
#if !defined(STATUS_DEVICE_INSUFFICIENT_RESOURCES)
|
||||
#define STATUS_DEVICE_INSUFFICIENT_RESOURCES static_cast<NTSTATUS>(0xC0000468L)
|
||||
@@ -88,19 +87,23 @@ auto from_api_error(const api_error &e) -> NTSTATUS {
|
||||
}
|
||||
|
||||
auto get_accessed_time_from_meta(const api_meta_map &meta) -> std::uint64_t {
|
||||
return utils::string::to_uint64(meta.at(META_ACCESSED));
|
||||
return utils::time::unix_time_to_windows_time(
|
||||
utils::string::to_uint64(meta.at(META_ACCESSED)));
|
||||
}
|
||||
|
||||
auto get_changed_time_from_meta(const api_meta_map &meta) -> std::uint64_t {
|
||||
return utils::string::to_uint64(meta.at(META_MODIFIED));
|
||||
return utils::time::unix_time_to_windows_time(
|
||||
utils::string::to_uint64(meta.at(META_MODIFIED)));
|
||||
}
|
||||
|
||||
auto get_creation_time_from_meta(const api_meta_map &meta) -> std::uint64_t {
|
||||
return utils::string::to_uint64(meta.at(META_CREATION));
|
||||
return utils::time::unix_time_to_windows_time(
|
||||
utils::string::to_uint64(meta.at(META_CREATION)));
|
||||
}
|
||||
|
||||
auto get_written_time_from_meta(const api_meta_map &meta) -> std::uint64_t {
|
||||
return utils::string::to_uint64(meta.at(META_WRITTEN));
|
||||
return utils::time::unix_time_to_windows_time(
|
||||
utils::string::to_uint64(meta.at(META_WRITTEN)));
|
||||
}
|
||||
|
||||
auto unix_access_mask_to_windows(std::int32_t mask) -> int {
|
||||
|
||||
@@ -80,7 +80,7 @@ mount(std::vector<const char *> args, std::string data_directory,
|
||||
std::cout << "Generated " << app_config::get_provider_display_name(prov)
|
||||
<< " Configuration" << std::endl;
|
||||
std::cout << config.get_config_file_path() << std::endl;
|
||||
ret = utils::file::is_file(config.get_config_file_path())
|
||||
ret = utils::file::file(config.get_config_file_path()).exists()
|
||||
? exit_code::success
|
||||
: exit_code::file_creation_failed;
|
||||
} else {
|
||||
|
||||
@@ -21,7 +21,7 @@
|
||||
*/
|
||||
#if defined(PROJECT_ENABLE_BACKWARD_CPP)
|
||||
#include "backward.hpp"
|
||||
#endif
|
||||
#endif // defined(PROJECT_ENABLE_BACKWARD_CPP)
|
||||
|
||||
#include "cli/actions.hpp"
|
||||
#include "initialize.hpp"
|
||||
@@ -34,7 +34,7 @@ using namespace repertory;
|
||||
auto main(int argc, char **argv) -> int {
|
||||
#if defined(PROJECT_ENABLE_BACKWARD_CPP)
|
||||
static backward::SignalHandling sh;
|
||||
#endif
|
||||
#endif // defined(PROJECT_ENABLE_BACKWARD_CPP)
|
||||
|
||||
if (not repertory::project_initialize()) {
|
||||
std::cerr << "fatal: failed to initialize repertory" << std::endl;
|
||||
|
||||
235
repertory/repertory_test/include/fixtures/fuse_fixture.hpp
Normal file
235
repertory/repertory_test/include/fixtures/fuse_fixture.hpp
Normal file
@@ -0,0 +1,235 @@
|
||||
/*
|
||||
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 REPERTORY_TEST_INCLUDE_FIXTURES_FUSE_FIXTURE_HPP
|
||||
#define REPERTORY_TEST_INCLUDE_FIXTURES_FUSE_FIXTURE_HPP
|
||||
#if !defined(_WIN32)
|
||||
|
||||
#include "test_common.hpp"
|
||||
|
||||
#include "app_config.hpp"
|
||||
#include "comm/curl/curl_comm.hpp"
|
||||
#include "drives/fuse/fuse_drive.hpp"
|
||||
#include "platform/platform.hpp"
|
||||
#include "providers/encrypt/encrypt_provider.hpp"
|
||||
#include "providers/s3/s3_provider.hpp"
|
||||
#include "providers/sia/sia_provider.hpp"
|
||||
#include "utils/file_utils.hpp"
|
||||
#include "utils/path.hpp"
|
||||
|
||||
#if !defined(ACCESSPERMS)
|
||||
#define ACCESSPERMS (S_IRWXU | S_IRWXG | S_IRWXO) /* 0777 */
|
||||
#endif
|
||||
|
||||
namespace repertory {
|
||||
inline constexpr const auto SLEEP_SECONDS{1.5s};
|
||||
|
||||
template <typename provider_t> class fuse_test : public ::testing::Test {
|
||||
public:
|
||||
static std::string cfg_directory;
|
||||
static std::unique_ptr<curl_comm> comm;
|
||||
static std::unique_ptr<app_config> config;
|
||||
static std::filesystem::path current_directory;
|
||||
static std::unique_ptr<fuse_drive> drive;
|
||||
static lock_data lock_data_;
|
||||
static std::string mount_location;
|
||||
static std::unique_ptr<i_provider> provider;
|
||||
static std::string test_directory;
|
||||
|
||||
protected:
|
||||
static void SetUpTestCase() {
|
||||
current_directory = std::filesystem::current_path();
|
||||
|
||||
test_directory = utils::path::combine(
|
||||
test::get_test_output_dir(),
|
||||
{
|
||||
"fuse_test",
|
||||
std::to_string(static_cast<std::uint8_t>(provider_t::type)),
|
||||
});
|
||||
|
||||
ASSERT_TRUE(utils::file::directory(test_directory).remove_recursively());
|
||||
|
||||
mount_location = utils::path::combine(test_directory, {"mount"});
|
||||
ASSERT_TRUE(utils::file::directory(mount_location).create_directory());
|
||||
|
||||
cfg_directory = utils::path::combine(test_directory, {"cfg"});
|
||||
ASSERT_TRUE(utils::file::directory(cfg_directory).create_directory());
|
||||
|
||||
config = std::make_unique<app_config>(provider_t::type, cfg_directory);
|
||||
|
||||
std::vector<std::string> drive_args{};
|
||||
switch (provider_t::type) {
|
||||
case provider_type::s3: {
|
||||
{
|
||||
app_config src_cfg{
|
||||
provider_type::s3,
|
||||
utils::path::combine(test::get_test_input_dir(), {"storj"}),
|
||||
};
|
||||
config->set_enable_drive_events(true);
|
||||
config->set_event_level(event_level::trace);
|
||||
config->set_s3_config(src_cfg.get_s3_config());
|
||||
}
|
||||
|
||||
comm = std::make_unique<curl_comm>(config->get_s3_config());
|
||||
drive_args = std::vector<std::string>({
|
||||
"-s3",
|
||||
"-na",
|
||||
"storj",
|
||||
});
|
||||
} break;
|
||||
|
||||
case provider_type::sia: {
|
||||
{
|
||||
app_config src_cfg{
|
||||
provider_type::sia,
|
||||
utils::path::combine(test::get_test_input_dir(), {"sia"}),
|
||||
};
|
||||
config->set_enable_drive_events(true);
|
||||
config->set_event_level(event_level::debug);
|
||||
config->set_host_config(src_cfg.get_host_config());
|
||||
}
|
||||
|
||||
comm = std::make_unique<curl_comm>(config->get_host_config());
|
||||
} break;
|
||||
// case 0U: {
|
||||
// config =
|
||||
// std::make_unique<app_config>(provider_type::encrypt,
|
||||
// cfg_directory);
|
||||
// {
|
||||
// app_config src_cfg(
|
||||
// provider_type::s3,
|
||||
// utils::path::combine(test::get_test_input_dir(), {"encrypt"}));
|
||||
// config->set_enable_drive_events(true);
|
||||
// config->set_event_level(event_level::trace);
|
||||
// config->set_s3_config(src_cfg.get_s3_config());
|
||||
// }
|
||||
//
|
||||
// comm = std::make_unique<curl_comm>(config->get_s3_config());
|
||||
// provider = std::make_unique<s3_provider>(*config, *comm);
|
||||
// drive_args = std::vector<std::string>({"-en"});
|
||||
// } break;
|
||||
|
||||
default:
|
||||
throw std::runtime_error("provider type is not implemented");
|
||||
return;
|
||||
}
|
||||
|
||||
provider = std::make_unique<provider_t>(*config, *comm);
|
||||
drive_args.push_back(mount_location);
|
||||
execute_mount(drive_args);
|
||||
}
|
||||
|
||||
static void TearDownTestCase() {
|
||||
execute_unmount();
|
||||
std::filesystem::current_path(current_directory);
|
||||
|
||||
[[maybe_unused]] auto ret =
|
||||
utils::file::directory(test_directory).remove_recursively();
|
||||
}
|
||||
|
||||
public:
|
||||
static auto create_file_and_test(std::string name) -> std::string {
|
||||
auto file_path = utils::path::combine(mount_location, {name});
|
||||
|
||||
auto fd =
|
||||
open(file_path.c_str(), O_CREAT | O_RDWR, S_IRUSR | S_IWUSR | S_IRGRP);
|
||||
EXPECT_LE(1, fd);
|
||||
|
||||
EXPECT_TRUE(utils::file::file(file_path).exists());
|
||||
EXPECT_FALSE(utils::file::directory(file_path).exists());
|
||||
|
||||
auto opt_size = utils::file::file{file_path}.size();
|
||||
EXPECT_TRUE(opt_size.has_value());
|
||||
EXPECT_EQ(0U, opt_size.value());
|
||||
|
||||
EXPECT_EQ(0, close(fd));
|
||||
std::this_thread::sleep_for(SLEEP_SECONDS);
|
||||
|
||||
return file_path;
|
||||
}
|
||||
|
||||
static void execute_mount(auto &&drive_args) {
|
||||
auto mount_cmd = "./repertory -dd \"" + config->get_data_directory() +
|
||||
"\"" + " " + utils::string::join(drive_args, ' ');
|
||||
std::cout << "mount command: " << mount_cmd << std::endl;
|
||||
ASSERT_EQ(0, system(mount_cmd.c_str()));
|
||||
std::this_thread::sleep_for(5s);
|
||||
EXPECT_EQ(0, system(("mount|grep \"" + mount_location + "\"").c_str()));
|
||||
}
|
||||
|
||||
static void execute_unmount() {
|
||||
auto unmounted{false};
|
||||
for (int i = 0; not unmounted && (i < 50); i++) {
|
||||
unmounted = (fuse_base::unmount(mount_location) == 0);
|
||||
if (not unmounted) {
|
||||
std::this_thread::sleep_for(100ms);
|
||||
}
|
||||
}
|
||||
|
||||
EXPECT_TRUE(unmounted);
|
||||
}
|
||||
|
||||
static void unlink_file_and_test(const std::string &file_path) {
|
||||
int ret = 0;
|
||||
for (auto i = 0; ((ret = unlink(file_path.c_str())) != 0) && (i < 20);
|
||||
i++) {
|
||||
std::this_thread::sleep_for(100ms);
|
||||
}
|
||||
|
||||
EXPECT_EQ(0, ret);
|
||||
|
||||
std::this_thread::sleep_for(SLEEP_SECONDS);
|
||||
EXPECT_FALSE(utils::file::directory(file_path).exists());
|
||||
EXPECT_FALSE(utils::file::file(file_path).exists());
|
||||
}
|
||||
};
|
||||
|
||||
template <typename provider_t>
|
||||
std::string fuse_test<provider_t>::cfg_directory{};
|
||||
|
||||
template <typename provider_t>
|
||||
std::unique_ptr<curl_comm> fuse_test<provider_t>::comm{};
|
||||
|
||||
template <typename provider_t>
|
||||
std::unique_ptr<app_config> fuse_test<provider_t>::config{};
|
||||
|
||||
template <typename provider_t>
|
||||
std::filesystem::path fuse_test<provider_t>::current_directory{};
|
||||
|
||||
template <typename provider_t>
|
||||
std::unique_ptr<fuse_drive> fuse_test<provider_t>::drive{};
|
||||
|
||||
template <typename provider_t> lock_data fuse_test<provider_t>::lock_data_{};
|
||||
|
||||
template <typename provider_t>
|
||||
std::string fuse_test<provider_t>::mount_location{};
|
||||
|
||||
template <typename provider_t>
|
||||
std::unique_ptr<i_provider> fuse_test<provider_t>::provider{};
|
||||
|
||||
template <typename provider_t>
|
||||
std::string fuse_test<provider_t>::test_directory;
|
||||
|
||||
typedef ::testing::Types<s3_provider, sia_provider> fuse_provider_types;
|
||||
} // namespace repertory
|
||||
|
||||
#endif // !defined(_WIN32)
|
||||
#endif // REPERTORY_TEST_INCLUDE_FIXTURES_FUSE_FIXTURE_HPP
|
||||
@@ -19,8 +19,8 @@
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
*/
|
||||
#ifndef REPERTORY_WINFSP_FIXTURE_HPP
|
||||
#define REPERTORY_WINFSP_FIXTURE_HPP
|
||||
#ifndef REPERTORY_TEST_INCLUDE_FIXTURES_WINFSP_FIXTURE_HPP
|
||||
#define REPERTORY_TEST_INCLUDE_FIXTURES_WINFSP_FIXTURE_HPP
|
||||
#if defined(_WIN32)
|
||||
|
||||
#include "test_common.hpp"
|
||||
@@ -31,6 +31,8 @@
|
||||
#include "platform/platform.hpp"
|
||||
#include "providers/s3/s3_provider.hpp"
|
||||
#include "providers/sia/sia_provider.hpp"
|
||||
#include "utils/file_utils.hpp"
|
||||
#include "utils/path.hpp"
|
||||
|
||||
extern std::size_t PROVIDER_INDEX;
|
||||
|
||||
@@ -47,14 +49,20 @@ protected:
|
||||
void SetUp() override {
|
||||
if (PROVIDER_INDEX != 0) {
|
||||
if (PROVIDER_INDEX == 1) {
|
||||
EXPECT_TRUE(utils::file::delete_directory_recursively(
|
||||
"./test_config/winfsp_test" + std::to_string(PROVIDER_INDEX)));
|
||||
EXPECT_TRUE(utils::file::directory(
|
||||
utils::path::combine(
|
||||
test::get_test_output_dir(),
|
||||
{"winfsp_test" + std::to_string(PROVIDER_INDEX)}))
|
||||
.remove_recursively());
|
||||
|
||||
app_config src_cfg(provider_type::s3,
|
||||
utils::path::combine(get_test_dir(), {"storj"}));
|
||||
app_config src_cfg(
|
||||
provider_type::s3,
|
||||
utils::path::combine(test::get_test_input_dir(), {"storj"}));
|
||||
config = std::make_unique<app_config>(
|
||||
provider_type::s3,
|
||||
"./test_config/winfsp_test" + std::to_string(PROVIDER_INDEX));
|
||||
utils::path::combine(
|
||||
test::get_test_output_dir(),
|
||||
{"winfsp_test" + std::to_string(PROVIDER_INDEX)}));
|
||||
EXPECT_FALSE(config
|
||||
->set_value_by_name("S3Config.AccessKey",
|
||||
src_cfg.get_s3_config().access_key)
|
||||
@@ -89,14 +97,20 @@ protected:
|
||||
}
|
||||
|
||||
if (PROVIDER_INDEX == 2) {
|
||||
EXPECT_TRUE(utils::file::delete_directory_recursively(
|
||||
"./test_config/winfsp_test" + std::to_string(PROVIDER_INDEX)));
|
||||
EXPECT_TRUE(utils::file::directory(
|
||||
utils::path::combine(
|
||||
test::get_test_output_dir(),
|
||||
{"winfsp_test" + std::to_string(PROVIDER_INDEX)}))
|
||||
.remove_recursively());
|
||||
|
||||
app_config src_cfg(provider_type::sia,
|
||||
utils::path::combine(get_test_dir(), {"sia"}));
|
||||
app_config src_cfg(
|
||||
provider_type::sia,
|
||||
utils::path::combine(test::get_test_input_dir(), {"sia"}));
|
||||
config = std::make_unique<app_config>(
|
||||
provider_type::sia,
|
||||
"./test_config/winfsp_test" + std::to_string(PROVIDER_INDEX));
|
||||
utils::path::combine(
|
||||
test::get_test_output_dir(),
|
||||
{"winfsp_test" + std::to_string(PROVIDER_INDEX)}));
|
||||
[[maybe_unused]] auto val = config->set_value_by_name(
|
||||
"HostConfig.AgentString", src_cfg.get_host_config().agent_string);
|
||||
EXPECT_FALSE(
|
||||
@@ -135,12 +149,15 @@ protected:
|
||||
config.reset();
|
||||
|
||||
event_system::instance().stop();
|
||||
EXPECT_TRUE(utils::file::delete_directory_recursively(
|
||||
"./test_config/winfsp_test" + std::to_string(PROVIDER_INDEX)));
|
||||
EXPECT_TRUE(utils::file::directory(
|
||||
utils::path::combine(
|
||||
test::get_test_output_dir(),
|
||||
{"winfsp_test" + std::to_string(PROVIDER_INDEX)}))
|
||||
.remove_recursively());
|
||||
}
|
||||
}
|
||||
};
|
||||
} // namespace repertory
|
||||
|
||||
#endif
|
||||
#endif // REPERTORY_WINFSP_FIXTURE_HPP
|
||||
#endif // REPERTORY_TEST_INCLUDE_FIXTURES_WINFSP_FIXTURE_HPP
|
||||
|
||||
@@ -19,8 +19,8 @@
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
*/
|
||||
#ifndef TESTS_MOCKS_MOCK_FUSE_DRIVE_HPP_
|
||||
#define TESTS_MOCKS_MOCK_FUSE_DRIVE_HPP_
|
||||
#ifndef REPERTORY_TEST_INCLUDE_FIXTURES_MOCKS_MOCK_FUSE_DRIVE_HPP_
|
||||
#define REPERTORY_TEST_INCLUDE_FIXTURES_MOCKS_MOCK_FUSE_DRIVE_HPP_
|
||||
#if !defined(_WIN32)
|
||||
|
||||
#include "test_common.hpp"
|
||||
@@ -68,10 +68,10 @@ public:
|
||||
dir_item.size = 0;
|
||||
dir_item.meta = {
|
||||
{META_ATTRIBUTES, "16"},
|
||||
{META_MODIFIED, std::to_string(utils::time::get_file_time_now())},
|
||||
{META_WRITTEN, std::to_string(utils::time::get_file_time_now())},
|
||||
{META_ACCESSED, std::to_string(utils::time::get_file_time_now())},
|
||||
{META_CREATION, std::to_string(utils::time::get_file_time_now())}};
|
||||
{META_MODIFIED, std::to_string(utils::time::get_time_now())},
|
||||
{META_WRITTEN, std::to_string(utils::time::get_time_now())},
|
||||
{META_ACCESSED, std::to_string(utils::time::get_time_now())},
|
||||
{META_CREATION, std::to_string(utils::time::get_time_now())}};
|
||||
list.emplace_back(dir_item);
|
||||
|
||||
dir_item.api_path = "..";
|
||||
@@ -132,11 +132,11 @@ public:
|
||||
utils::path::combine(mount_location_, {to_api_path});
|
||||
|
||||
if (overwrite) {
|
||||
if (not utils::file::retry_delete_file(to_file_path)) {
|
||||
if (not utils::file::file(to_file_path).remove()) {
|
||||
return -1;
|
||||
}
|
||||
} else if (utils::file::is_directory(to_file_path) ||
|
||||
utils::file::is_file(to_file_path)) {
|
||||
} else if (utils::file::directory(to_file_path).exists() ||
|
||||
utils::file::file(to_file_path).exists()) {
|
||||
errno = EEXIST;
|
||||
return -1;
|
||||
}
|
||||
@@ -155,5 +155,5 @@ public:
|
||||
};
|
||||
} // namespace repertory
|
||||
|
||||
#endif // _WIN32
|
||||
#endif // TESTS_MOCKS_MOCK_FUSE_DRIVE_HPP_
|
||||
#endif // !defined(_WIN32)
|
||||
#endif // REPERTORY_TEST_INCLUDE_FIXTURES_MOCKS_MOCK_FUSE_DRIVE_HPP_
|
||||
|
||||
@@ -19,8 +19,8 @@
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
*/
|
||||
#ifndef TESTS_MOCKS_MOCK_OPEN_FILE_HPP_
|
||||
#define TESTS_MOCKS_MOCK_OPEN_FILE_HPP_
|
||||
#ifndef REPERTORY_TEST_INCLUDE_MOCKS_MOCK_OPEN_FILE_HPP_
|
||||
#define REPERTORY_TEST_INCLUDE_MOCKS_MOCK_OPEN_FILE_HPP_
|
||||
|
||||
#include "test_common.hpp"
|
||||
|
||||
@@ -95,4 +95,4 @@ public:
|
||||
};
|
||||
} // namespace repertory
|
||||
|
||||
#endif // TESTS_MOCKS_MOCK_OPEN_FILE_HPP_
|
||||
#endif // REPERTORY_TEST_INCLUDE_MOCKS_MOCK_OPEN_FILE_HPP_
|
||||
|
||||
@@ -19,8 +19,8 @@
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
*/
|
||||
#ifndef TESTS_MOCKS_MOCK_PROVIDER_HPP_
|
||||
#define TESTS_MOCKS_MOCK_PROVIDER_HPP_
|
||||
#ifndef REPERTORY_TEST_INCLUDE_MOCKS_MOCK_PROVIDER_HPP_
|
||||
#define REPERTORY_TEST_INCLUDE_MOCKS_MOCK_PROVIDER_HPP_
|
||||
|
||||
#include "test_common.hpp"
|
||||
|
||||
@@ -159,4 +159,4 @@ public:
|
||||
};
|
||||
} // namespace repertory
|
||||
|
||||
#endif // TESTS_MOCKS_MOCK_PROVIDER_HPP_
|
||||
#endif // REPERTORY_TEST_INCLUDE_MOCKS_MOCK_PROVIDER_HPP_
|
||||
|
||||
@@ -19,8 +19,8 @@
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
*/
|
||||
#ifndef TESTS_MOCKS_MOCK_UPLOAD_MANAGER_HPP_
|
||||
#define TESTS_MOCKS_MOCK_UPLOAD_MANAGER_HPP_
|
||||
#ifndef REPERTORY_TEST_INCLUDE_MOCKS_MOCK_UPLOAD_MANAGER_HPP_
|
||||
#define REPERTORY_TEST_INCLUDE_MOCKS_MOCK_UPLOAD_MANAGER_HPP_
|
||||
|
||||
#include "test_common.hpp"
|
||||
|
||||
@@ -41,4 +41,4 @@ public:
|
||||
};
|
||||
} // namespace repertory
|
||||
|
||||
#endif // TESTS_MOCKS_MOCK_UPLOAD_MANAGER_HPP_
|
||||
#endif // REPERTORY_TEST_INCLUDE_MOCKS_MOCK_UPLOAD_MANAGER_HPP_
|
||||
|
||||
@@ -19,8 +19,8 @@
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
*/
|
||||
#ifndef TESTS_MOCKS_MOCK_WINFSP_DRIVE_HPP_
|
||||
#define TESTS_MOCKS_MOCK_WINFSP_DRIVE_HPP_
|
||||
#ifndef REPERTORY_TEST_INCLUDE_MOCKS_MOCK_WINFSP_DRIVE_HPP_
|
||||
#define REPERTORY_TEST_INCLUDE_MOCKS_MOCK_WINFSP_DRIVE_HPP_
|
||||
#if defined(_WIN32)
|
||||
|
||||
#include "test_common.hpp"
|
||||
@@ -57,10 +57,10 @@ public:
|
||||
di.size = 0u;
|
||||
di.meta = {
|
||||
{META_ATTRIBUTES, "16"},
|
||||
{META_MODIFIED, std::to_string(utils::time::get_file_time_now())},
|
||||
{META_WRITTEN, std::to_string(utils::time::get_file_time_now())},
|
||||
{META_ACCESSED, std::to_string(utils::time::get_file_time_now())},
|
||||
{META_CREATION, std::to_string(utils::time::get_file_time_now())}};
|
||||
{META_MODIFIED, std::to_string(utils::time::get_time_now())},
|
||||
{META_WRITTEN, std::to_string(utils::time::get_time_now())},
|
||||
{META_ACCESSED, std::to_string(utils::time::get_time_now())},
|
||||
{META_CREATION, std::to_string(utils::time::get_time_now())}};
|
||||
list.emplace_back(di);
|
||||
|
||||
di.api_path = "..";
|
||||
@@ -138,7 +138,7 @@ public:
|
||||
auto populate_file_info(const std::string &api_path,
|
||||
remote::file_info &file_info) -> api_error override {
|
||||
const auto file_path = utils::path::combine(mount_location_, {api_path});
|
||||
const auto directory = utils::file::is_directory(file_path);
|
||||
const auto directory = utils::file::directory(file_path).exists();
|
||||
const auto attributes =
|
||||
FILE_FLAG_BACKUP_SEMANTICS |
|
||||
(directory ? FILE_ATTRIBUTE_DIRECTORY : FILE_ATTRIBUTE_NORMAL);
|
||||
@@ -148,8 +148,14 @@ public:
|
||||
FILE_BASIC_INFO fi{};
|
||||
::GetFileInformationByHandleEx(handle, FileBasicInfo, &fi, sizeof(fi));
|
||||
if (not directory) {
|
||||
utils::file::get_file_size(file_path, file_info.FileSize);
|
||||
auto opt_size = utils::file::file{file_path}.size();
|
||||
if (not opt_size.has_value()) {
|
||||
return api_error::os_error;
|
||||
}
|
||||
|
||||
file_info.FileSize = opt_size.value();
|
||||
}
|
||||
|
||||
file_info.AllocationSize =
|
||||
directory ? 0
|
||||
: utils::divide_with_ceiling(file_info.FileSize,
|
||||
@@ -167,4 +173,4 @@ public:
|
||||
} // namespace repertory
|
||||
|
||||
#endif // _WIN32
|
||||
#endif // TESTS_MOCKS_MOCK_WINFSP_DRIVE_HPP_
|
||||
#endif // REPERTORY_TEST_INCLUDE_MOCKS_MOCK_WINFSP_DRIVE_HPP_
|
||||
|
||||
@@ -19,47 +19,15 @@
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
*/
|
||||
#ifndef TESTS_TEST_COMMON_HPP_
|
||||
#define TESTS_TEST_COMMON_HPP_
|
||||
|
||||
#if defined(U)
|
||||
#undef U
|
||||
#endif
|
||||
#ifndef REPERTORY_TEST_INCLUDE_TEST_COMMON_HPP_
|
||||
#define REPERTORY_TEST_INCLUDE_TEST_COMMON_HPP_
|
||||
|
||||
REPERTORY_IGNORE_WARNINGS_ENABLE()
|
||||
#include <gmock/gmock.h>
|
||||
#include <gtest/gtest.h>
|
||||
#include "test.hpp"
|
||||
REPERTORY_IGNORE_WARNINGS_DISABLE()
|
||||
|
||||
#include "events/consumers/console_consumer.hpp"
|
||||
#include "events/event_system.hpp"
|
||||
#include "events/events.hpp"
|
||||
#include "utils/encrypt.hpp"
|
||||
#include "utils/file_utils.hpp"
|
||||
#include "utils/native_file.hpp"
|
||||
|
||||
#define COMMA ,
|
||||
|
||||
using ::testing::_;
|
||||
using namespace ::testing;
|
||||
|
||||
namespace repertory {
|
||||
[[nodiscard]] auto create_random_file(std::string path,
|
||||
std::size_t size) -> native_file_ptr;
|
||||
|
||||
void delete_generated_files();
|
||||
|
||||
[[nodiscard]] auto generate_test_file_name(
|
||||
const std::string &directory,
|
||||
const std::string &file_name_no_extension) -> std::string;
|
||||
|
||||
template <typename T, typename T2>
|
||||
static void decrypt_and_verify(const T &buffer, const std::string &token,
|
||||
T2 &result) {
|
||||
EXPECT_TRUE(utils::encryption::decrypt_data(token, buffer, result));
|
||||
}
|
||||
|
||||
[[nodiscard]] auto get_test_dir() -> std::string;
|
||||
} // namespace repertory
|
||||
|
||||
#endif // TESTS_TEST_COMMON_HPP_
|
||||
#endif // REPERTORY_TEST_INCLUDE_TEST_COMMON_HPP_
|
||||
|
||||
@@ -19,8 +19,8 @@
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
*/
|
||||
#ifndef TESTS_UTILS_EVENT_CAPTURE_HPP_
|
||||
#define TESTS_UTILS_EVENT_CAPTURE_HPP_
|
||||
#ifndef REPERTORY_TEST_INCLUDE_UTILS_EVENT_CAPTURE_HPP_
|
||||
#define REPERTORY_TEST_INCLUDE_UTILS_EVENT_CAPTURE_HPP_
|
||||
|
||||
#include "test_common.hpp"
|
||||
|
||||
@@ -106,4 +106,4 @@ public:
|
||||
};
|
||||
} // namespace repertory
|
||||
|
||||
#endif // TESTS_UTILS_EVENT_CAPTURE_HPP_
|
||||
#endif // REPERTORY_TEST_INCLUDE_UTILS_EVENT_CAPTURE_HPP_
|
||||
|
||||
@@ -63,8 +63,6 @@ auto main(int argc, char **argv) -> int {
|
||||
::testing::InitGoogleTest(&argc, argv);
|
||||
auto ret = RUN_ALL_TESTS();
|
||||
|
||||
delete_generated_files();
|
||||
|
||||
repertory::project_cleanup();
|
||||
|
||||
return ret;
|
||||
|
||||
@@ -33,20 +33,24 @@ public:
|
||||
static console_consumer cs;
|
||||
|
||||
std::string s3_directory{
|
||||
utils::path::combine("./test_config", {"config_test", "s3"})};
|
||||
utils::path::combine(test::get_test_output_dir(), {"config_test", "s3"})};
|
||||
|
||||
std::string sia_directory{
|
||||
utils::path::combine("./test_config", {"config_test", "sia"})};
|
||||
std::string sia_directory{utils::path::combine(test::get_test_output_dir(),
|
||||
{"config_test", "sia"})};
|
||||
|
||||
void SetUp() override {
|
||||
event_system::instance().start();
|
||||
ASSERT_TRUE(utils::file::delete_directory_recursively(
|
||||
utils::path::combine("./test_config", {"config_test"})));
|
||||
ASSERT_TRUE(
|
||||
utils::file::directory(
|
||||
utils::path::combine(test::get_test_output_dir(), {"config_test"}))
|
||||
.remove_recursively());
|
||||
}
|
||||
|
||||
void TearDown() override {
|
||||
ASSERT_TRUE(utils::file::delete_directory_recursively(
|
||||
utils::path::combine("./test_config", {"config_test"})));
|
||||
ASSERT_TRUE(
|
||||
utils::file::directory(
|
||||
utils::path::combine(test::get_test_output_dir(), {"config_test"}))
|
||||
.remove_recursively());
|
||||
event_system::instance().stop();
|
||||
}
|
||||
};
|
||||
@@ -163,10 +167,12 @@ TEST_F(config_test, sia_default_settings) {
|
||||
json data;
|
||||
EXPECT_TRUE(utils::file::read_json_file(config_file, data));
|
||||
EXPECT_STREQ(DEFAULT_SIA_CONFIG.c_str(), data.dump(2).c_str());
|
||||
EXPECT_TRUE(utils::file::is_directory(
|
||||
utils::path::combine(sia_directory, {"cache"})));
|
||||
EXPECT_TRUE(utils::file::is_directory(
|
||||
utils::path::combine(sia_directory, {"logs"})));
|
||||
EXPECT_TRUE(
|
||||
utils::file::directory(utils::path::combine(sia_directory, {"cache"}))
|
||||
.exists());
|
||||
EXPECT_TRUE(
|
||||
utils::file::directory(utils::path::combine(sia_directory, {"logs"}))
|
||||
.exists());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -180,10 +186,12 @@ TEST_F(config_test, s3_default_settings) {
|
||||
json data;
|
||||
EXPECT_TRUE(utils::file::read_json_file(config_file, data));
|
||||
EXPECT_STREQ(DEFAULT_S3_CONFIG.c_str(), data.dump(2).c_str());
|
||||
EXPECT_TRUE(utils::file::is_directory(
|
||||
utils::path::combine(s3_directory, {"cache"})));
|
||||
EXPECT_TRUE(utils::file::is_directory(
|
||||
utils::path::combine(s3_directory, {"logs"})));
|
||||
EXPECT_TRUE(
|
||||
utils::file::directory(utils::path::combine(s3_directory, {"cache"}))
|
||||
.exists());
|
||||
EXPECT_TRUE(
|
||||
utils::file::directory(utils::path::combine(s3_directory, {"logs"}))
|
||||
.exists());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -35,8 +35,9 @@ TEST(database, db_insert) {
|
||||
{
|
||||
sqlite3 *db3_ptr{nullptr};
|
||||
auto res = sqlite3_open_v2(
|
||||
utils::path::combine(get_test_dir(), {"test.db3"}).c_str(), &db3_ptr,
|
||||
SQLITE_OPEN_READWRITE, nullptr);
|
||||
utils::path::combine(test::get_test_input_dir(), {"test.db3"})
|
||||
.c_str(),
|
||||
&db3_ptr, SQLITE_OPEN_READWRITE, nullptr);
|
||||
ASSERT_EQ(SQLITE_OK, res);
|
||||
ASSERT_TRUE(db3_ptr != nullptr);
|
||||
|
||||
@@ -78,8 +79,9 @@ TEST(database, db_select) {
|
||||
{
|
||||
sqlite3 *db3_ptr{nullptr};
|
||||
auto res = sqlite3_open_v2(
|
||||
utils::path::combine(get_test_dir(), {"test.db3"}).c_str(), &db3_ptr,
|
||||
SQLITE_OPEN_READWRITE, nullptr);
|
||||
utils::path::combine(test::get_test_input_dir(), {"test.db3"})
|
||||
.c_str(),
|
||||
&db3_ptr, SQLITE_OPEN_READWRITE, nullptr);
|
||||
ASSERT_EQ(SQLITE_OK, res);
|
||||
ASSERT_TRUE(db3_ptr != nullptr);
|
||||
|
||||
|
||||
@@ -1,283 +0,0 @@
|
||||
/*
|
||||
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 "test_common.hpp"
|
||||
|
||||
#include "types/repertory.hpp"
|
||||
#include "utils/encrypting_reader.hpp"
|
||||
#include "utils/file_utils.hpp"
|
||||
#include "utils/path.hpp"
|
||||
|
||||
namespace repertory {
|
||||
static auto get_source_file_name() -> std::string {
|
||||
return generate_test_file_name("./test_data", "encrypting_reader");
|
||||
}
|
||||
|
||||
TEST(encrypting_reader, get_encrypted_file_name) {
|
||||
const auto source_file_name = get_source_file_name();
|
||||
ASSERT_TRUE(utils::file::retry_delete_file(source_file_name));
|
||||
|
||||
const auto token = std::string("moose");
|
||||
auto source_file = create_random_file(source_file_name, 1024UL);
|
||||
EXPECT_TRUE(source_file != nullptr);
|
||||
if (source_file) {
|
||||
stop_type stop_requested = false;
|
||||
utils::encryption::encrypting_reader reader(
|
||||
"test.dat", source_file_name, stop_requested, token, std::nullopt);
|
||||
|
||||
auto file_name = reader.get_encrypted_file_name();
|
||||
|
||||
EXPECT_EQ(api_error::success,
|
||||
utils::encryption::decrypt_file_name(token, file_name));
|
||||
EXPECT_STREQ("test.dat", file_name.c_str());
|
||||
|
||||
source_file->close();
|
||||
}
|
||||
|
||||
EXPECT_TRUE(utils::file::retry_delete_file(source_file_name));
|
||||
}
|
||||
|
||||
TEST(encrypting_reader, file_data) {
|
||||
const auto source_file_name = get_source_file_name();
|
||||
EXPECT_TRUE(utils::file::retry_delete_file(source_file_name));
|
||||
|
||||
const auto token = std::string("moose");
|
||||
auto source_file = create_random_file(
|
||||
source_file_name,
|
||||
8U * utils::encryption::encrypting_reader::get_data_chunk_size());
|
||||
EXPECT_TRUE(source_file != nullptr);
|
||||
if (source_file) {
|
||||
stop_type stop_requested = false;
|
||||
utils::encryption::encrypting_reader reader("test.dat", source_file_name,
|
||||
stop_requested, token);
|
||||
|
||||
for (std::uint8_t i = 0U; i < 8U; i++) {
|
||||
data_buffer buffer(
|
||||
utils::encryption::encrypting_reader::get_encrypted_chunk_size());
|
||||
for (std::uint8_t j = 0U; j < 2U; j++) {
|
||||
EXPECT_EQ(
|
||||
buffer.size() / 2U,
|
||||
utils::encryption::encrypting_reader::reader_function(
|
||||
reinterpret_cast<char *>(&buffer[(buffer.size() / 2U) * j]),
|
||||
buffer.size() / 2U, 1U, &reader));
|
||||
}
|
||||
|
||||
data_buffer decrypted_data;
|
||||
EXPECT_TRUE(
|
||||
utils::encryption::decrypt_data(token, buffer, decrypted_data));
|
||||
|
||||
EXPECT_EQ(utils::encryption::encrypting_reader::get_data_chunk_size(),
|
||||
decrypted_data.size());
|
||||
|
||||
std::size_t bytes_read{};
|
||||
data_buffer file_data(decrypted_data.size());
|
||||
EXPECT_TRUE(source_file->read_bytes(
|
||||
file_data.data(), file_data.size(),
|
||||
utils::encryption::encrypting_reader::get_data_chunk_size() * i,
|
||||
bytes_read));
|
||||
EXPECT_EQ(0, std::memcmp(file_data.data(), decrypted_data.data(),
|
||||
file_data.size()));
|
||||
}
|
||||
|
||||
source_file->close();
|
||||
}
|
||||
EXPECT_TRUE(utils::file::retry_delete_file(source_file_name));
|
||||
}
|
||||
|
||||
TEST(encrypting_reader, file_data_in_multiple_chunks) {
|
||||
const auto source_file_name = get_source_file_name();
|
||||
ASSERT_TRUE(utils::file::retry_delete_file(source_file_name));
|
||||
|
||||
const auto token = std::string("moose");
|
||||
auto source_file = create_random_file(
|
||||
source_file_name,
|
||||
8U * utils::encryption::encrypting_reader::get_data_chunk_size());
|
||||
EXPECT_TRUE(source_file != nullptr);
|
||||
if (source_file) {
|
||||
stop_type stop_requested = false;
|
||||
utils::encryption::encrypting_reader reader("test.dat", source_file_name,
|
||||
stop_requested, token);
|
||||
|
||||
for (std::uint8_t i = 0U; i < 8U; i += 2U) {
|
||||
data_buffer buffer(
|
||||
utils::encryption::encrypting_reader::get_encrypted_chunk_size() *
|
||||
2U);
|
||||
EXPECT_EQ(buffer.size(),
|
||||
utils::encryption::encrypting_reader::reader_function(
|
||||
reinterpret_cast<char *>(buffer.data()), buffer.size(), 1U,
|
||||
&reader));
|
||||
|
||||
for (std::uint8_t j = 0U; j < 2U; j++) {
|
||||
data_buffer decrypted_data;
|
||||
const auto offset = (j * (buffer.size() / 2U));
|
||||
EXPECT_TRUE(utils::encryption::decrypt_data(
|
||||
token,
|
||||
data_buffer(
|
||||
std::next(buffer.begin(), static_cast<std::int64_t>(offset)),
|
||||
std::next(buffer.begin(), static_cast<std::int64_t>(
|
||||
offset + (buffer.size() / 2U)))),
|
||||
decrypted_data));
|
||||
|
||||
EXPECT_EQ(utils::encryption::encrypting_reader::get_data_chunk_size(),
|
||||
decrypted_data.size());
|
||||
|
||||
std::size_t bytes_read{};
|
||||
data_buffer file_data(decrypted_data.size());
|
||||
EXPECT_TRUE(source_file->read_bytes(
|
||||
file_data.data(), file_data.size(),
|
||||
(utils::encryption::encrypting_reader::get_data_chunk_size() * i) +
|
||||
(j *
|
||||
utils::encryption::encrypting_reader::get_data_chunk_size()),
|
||||
bytes_read));
|
||||
EXPECT_EQ(0, std::memcmp(file_data.data(), decrypted_data.data(),
|
||||
file_data.size()));
|
||||
}
|
||||
}
|
||||
|
||||
source_file->close();
|
||||
}
|
||||
|
||||
EXPECT_TRUE(utils::file::retry_delete_file(source_file_name));
|
||||
}
|
||||
|
||||
TEST(encrypting_reader, file_data_as_stream) {
|
||||
const auto source_file_name = get_source_file_name();
|
||||
ASSERT_TRUE(utils::file::retry_delete_file(source_file_name));
|
||||
|
||||
const auto token = std::string("moose");
|
||||
auto source_file = create_random_file(
|
||||
source_file_name,
|
||||
8U * utils::encryption::encrypting_reader::get_data_chunk_size());
|
||||
EXPECT_TRUE(source_file != nullptr);
|
||||
if (source_file) {
|
||||
stop_type stop_requested = false;
|
||||
utils::encryption::encrypting_reader reader("test.dat", source_file_name,
|
||||
stop_requested, token);
|
||||
auto io_stream = reader.create_iostream();
|
||||
EXPECT_FALSE(io_stream->seekg(0, std::ios_base::end).fail());
|
||||
EXPECT_TRUE(io_stream->good());
|
||||
EXPECT_EQ(reader.get_total_size(),
|
||||
static_cast<std::uint64_t>(io_stream->tellg()));
|
||||
EXPECT_FALSE(io_stream->seekg(0, std::ios_base::beg).fail());
|
||||
EXPECT_TRUE(io_stream->good());
|
||||
|
||||
for (std::uint8_t i = 0U; i < 8U; i++) {
|
||||
data_buffer buffer(
|
||||
utils::encryption::encrypting_reader::get_encrypted_chunk_size());
|
||||
EXPECT_FALSE(
|
||||
io_stream->seekg(static_cast<std::streamoff>(i * buffer.size()))
|
||||
.fail());
|
||||
EXPECT_TRUE(io_stream->good());
|
||||
for (std::uint8_t j = 0U; j < 2U; j++) {
|
||||
EXPECT_FALSE(
|
||||
io_stream
|
||||
->read(
|
||||
reinterpret_cast<char *>(&buffer[(buffer.size() / 2U) * j]),
|
||||
static_cast<std::streamsize>(buffer.size()) / 2U)
|
||||
.fail());
|
||||
EXPECT_TRUE(io_stream->good());
|
||||
}
|
||||
|
||||
data_buffer decrypted_data;
|
||||
EXPECT_TRUE(
|
||||
utils::encryption::decrypt_data(token, buffer, decrypted_data));
|
||||
|
||||
EXPECT_EQ(utils::encryption::encrypting_reader::get_data_chunk_size(),
|
||||
decrypted_data.size());
|
||||
|
||||
std::size_t bytes_read{};
|
||||
data_buffer file_data(decrypted_data.size());
|
||||
EXPECT_TRUE(source_file->read_bytes(
|
||||
file_data.data(), file_data.size(),
|
||||
utils::encryption::encrypting_reader::get_data_chunk_size() * i,
|
||||
bytes_read));
|
||||
EXPECT_EQ(0, std::memcmp(file_data.data(), decrypted_data.data(),
|
||||
file_data.size()));
|
||||
}
|
||||
|
||||
source_file->close();
|
||||
}
|
||||
EXPECT_TRUE(utils::file::retry_delete_file(source_file_name));
|
||||
}
|
||||
|
||||
TEST(encrypting_reader, file_data_in_multiple_chunks_as_stream) {
|
||||
const auto source_file_name = get_source_file_name();
|
||||
ASSERT_TRUE(utils::file::retry_delete_file(source_file_name));
|
||||
|
||||
const auto token = std::string("moose");
|
||||
auto source_file = create_random_file(
|
||||
source_file_name,
|
||||
8u * utils::encryption::encrypting_reader::get_data_chunk_size());
|
||||
EXPECT_TRUE(source_file != nullptr);
|
||||
if (source_file) {
|
||||
stop_type stop_requested = false;
|
||||
utils::encryption::encrypting_reader reader("test.dat", source_file_name,
|
||||
stop_requested, token);
|
||||
auto io_stream = reader.create_iostream();
|
||||
EXPECT_FALSE(io_stream->seekg(0, std::ios_base::end).fail());
|
||||
EXPECT_TRUE(io_stream->good());
|
||||
EXPECT_EQ(reader.get_total_size(),
|
||||
static_cast<std::uint64_t>(io_stream->tellg()));
|
||||
EXPECT_FALSE(io_stream->seekg(0, std::ios_base::beg).fail());
|
||||
EXPECT_TRUE(io_stream->good());
|
||||
|
||||
for (std::uint8_t i = 0U; i < 8U; i += 2U) {
|
||||
data_buffer buffer(
|
||||
utils::encryption::encrypting_reader::get_encrypted_chunk_size() *
|
||||
2U);
|
||||
EXPECT_FALSE(io_stream
|
||||
->read(reinterpret_cast<char *>(buffer.data()),
|
||||
static_cast<std::streamsize>(buffer.size()))
|
||||
.fail());
|
||||
EXPECT_TRUE(io_stream->good());
|
||||
|
||||
for (std::uint8_t j = 0U; j < 2U; j++) {
|
||||
data_buffer decrypted_data;
|
||||
const auto offset = (j * (buffer.size() / 2U));
|
||||
EXPECT_TRUE(utils::encryption::decrypt_data(
|
||||
token,
|
||||
data_buffer(
|
||||
std::next(buffer.begin(), static_cast<std::int64_t>(offset)),
|
||||
std::next(buffer.begin(), static_cast<std::int64_t>(
|
||||
offset + (buffer.size() / 2U)))),
|
||||
decrypted_data));
|
||||
|
||||
EXPECT_EQ(utils::encryption::encrypting_reader::get_data_chunk_size(),
|
||||
decrypted_data.size());
|
||||
|
||||
std::size_t bytes_read{};
|
||||
data_buffer file_data(decrypted_data.size());
|
||||
EXPECT_TRUE(source_file->read_bytes(
|
||||
file_data.data(), file_data.size(),
|
||||
(utils::encryption::encrypting_reader::get_data_chunk_size() * i) +
|
||||
(j *
|
||||
utils::encryption::encrypting_reader::get_data_chunk_size()),
|
||||
bytes_read));
|
||||
EXPECT_EQ(0, std::memcmp(file_data.data(), decrypted_data.data(),
|
||||
file_data.size()));
|
||||
}
|
||||
}
|
||||
|
||||
source_file->close();
|
||||
}
|
||||
EXPECT_TRUE(utils::file::retry_delete_file(source_file_name));
|
||||
}
|
||||
} // namespace repertory
|
||||
@@ -55,7 +55,7 @@ static void validate_write(file_manager::open_file &o, std::size_t offset,
|
||||
|
||||
TEST(open_file, properly_initializes_state_for_0_byte_file) {
|
||||
const auto source_path =
|
||||
generate_test_file_name("./test_config", "file_manager_open_file_test");
|
||||
test::generate_test_file_name("file_manager_open_file_test");
|
||||
|
||||
mock_provider mp;
|
||||
mock_upload_manager um;
|
||||
@@ -76,7 +76,7 @@ TEST(open_file, properly_initializes_state_for_0_byte_file) {
|
||||
|
||||
TEST(open_file, properly_initializes_state_based_on_chunk_size) {
|
||||
const auto source_path =
|
||||
generate_test_file_name("./test_config", "file_manager_open_file_test");
|
||||
test::generate_test_file_name("file_manager_open_file_test");
|
||||
|
||||
mock_provider mp;
|
||||
mock_upload_manager um;
|
||||
@@ -109,7 +109,7 @@ TEST(open_file, properly_initializes_state_based_on_chunk_size) {
|
||||
|
||||
TEST(open_file, will_not_change_source_path_for_0_byte_file) {
|
||||
const auto source_path =
|
||||
generate_test_file_name("./test_config", "file_manager_open_file_test");
|
||||
test::generate_test_file_name("file_manager_open_file_test");
|
||||
|
||||
mock_provider mp;
|
||||
mock_upload_manager um;
|
||||
@@ -128,12 +128,12 @@ TEST(open_file, will_not_change_source_path_for_0_byte_file) {
|
||||
o.close();
|
||||
EXPECT_EQ(api_error::success, o.get_api_error());
|
||||
EXPECT_STREQ(source_path.c_str(), o.get_source_path().c_str());
|
||||
EXPECT_TRUE(utils::file::is_file(fsi.source_path));
|
||||
EXPECT_TRUE(utils::file::file(fsi.source_path).exists());
|
||||
}
|
||||
|
||||
TEST(open_file, will_change_source_path_if_file_size_is_greater_than_0) {
|
||||
const auto source_path =
|
||||
generate_test_file_name("./test_config", "file_manager_open_file_test");
|
||||
test::generate_test_file_name("file_manager_open_file_test");
|
||||
|
||||
mock_provider mp;
|
||||
mock_upload_manager um;
|
||||
@@ -166,14 +166,14 @@ TEST(open_file, will_change_source_path_if_file_size_is_greater_than_0) {
|
||||
o.close();
|
||||
EXPECT_EQ(api_error::download_stopped, o.get_api_error());
|
||||
EXPECT_STRNE(source_path.c_str(), o.get_source_path().c_str());
|
||||
EXPECT_FALSE(utils::file::is_file(source_path));
|
||||
EXPECT_FALSE(utils::file::file(source_path).exists());
|
||||
}
|
||||
|
||||
TEST(open_file,
|
||||
will_not_change_source_path_if_file_size_matches_existing_source) {
|
||||
const auto source_path =
|
||||
generate_test_file_name("./test_config", "file_manager_open_file_test");
|
||||
create_random_file(source_path, test_chunk_size)->close();
|
||||
auto &rf = test::create_random_file(test_chunk_size);
|
||||
const auto source_path = rf.get_path();
|
||||
rf.close();
|
||||
|
||||
mock_provider mp;
|
||||
mock_upload_manager um;
|
||||
@@ -192,15 +192,12 @@ TEST(open_file,
|
||||
o.close();
|
||||
EXPECT_EQ(api_error::success, o.get_api_error());
|
||||
EXPECT_STREQ(source_path.c_str(), o.get_source_path().c_str());
|
||||
EXPECT_TRUE(utils::file::is_file(source_path));
|
||||
EXPECT_TRUE(utils::file::file(source_path).exists());
|
||||
}
|
||||
|
||||
TEST(open_file, write_with_incomplete_download) {
|
||||
const auto source_path =
|
||||
generate_test_file_name("./test_config", "file_manager_open_file_test");
|
||||
auto nf = create_random_file(
|
||||
generate_test_file_name("./test_config", "file_manager_open_file_test"),
|
||||
test_chunk_size * 2u);
|
||||
const auto source_path = test::generate_test_file_name("test");
|
||||
auto &nf = test::create_random_file(test_chunk_size * 2u);
|
||||
|
||||
mock_provider mp;
|
||||
mock_upload_manager um;
|
||||
@@ -236,9 +233,8 @@ TEST(open_file, write_with_incomplete_download) {
|
||||
if (offset == 0u) {
|
||||
std::size_t bytes_read{};
|
||||
data.resize(size);
|
||||
auto ret = nf->read_bytes(&data[0u], size, offset, bytes_read)
|
||||
? api_error::success
|
||||
: api_error::os_error;
|
||||
auto ret = nf.read(data, offset, &bytes_read) ? api_error::success
|
||||
: api_error::os_error;
|
||||
EXPECT_EQ(bytes_read, data.size());
|
||||
return ret;
|
||||
}
|
||||
@@ -278,18 +274,18 @@ TEST(open_file, write_with_incomplete_download) {
|
||||
test_state();
|
||||
|
||||
o.close();
|
||||
nf->close();
|
||||
nf.close();
|
||||
|
||||
test_state();
|
||||
|
||||
EXPECT_EQ(api_error::download_incomplete, o.get_api_error());
|
||||
|
||||
EXPECT_TRUE(utils::file::is_file(fsi.source_path));
|
||||
EXPECT_TRUE(utils::file::file(fsi.source_path).exists());
|
||||
}
|
||||
|
||||
TEST(open_file, write_new_file) {
|
||||
const auto source_path =
|
||||
generate_test_file_name("./test_config", "file_manager_open_file_test");
|
||||
test::generate_test_file_name("file_manager_open_file_test");
|
||||
|
||||
mock_provider mp;
|
||||
mock_upload_manager um;
|
||||
@@ -357,12 +353,12 @@ TEST(open_file, write_new_file) {
|
||||
|
||||
EXPECT_EQ(api_error::success, o.get_api_error());
|
||||
|
||||
EXPECT_TRUE(utils::file::is_file(fsi.source_path));
|
||||
EXPECT_TRUE(utils::file::file(fsi.source_path).exists());
|
||||
}
|
||||
|
||||
TEST(open_file, write_new_file_multiple_chunks) {
|
||||
const auto source_path =
|
||||
generate_test_file_name("./test_config", "file_manager_open_file_test");
|
||||
test::generate_test_file_name("file_manager_open_file_test");
|
||||
|
||||
mock_provider mp;
|
||||
mock_upload_manager um;
|
||||
@@ -449,13 +445,13 @@ TEST(open_file, write_new_file_multiple_chunks) {
|
||||
|
||||
EXPECT_EQ(api_error::success, o.get_api_error());
|
||||
|
||||
EXPECT_TRUE(utils::file::is_file(fsi.source_path));
|
||||
EXPECT_TRUE(utils::file::file(fsi.source_path).exists());
|
||||
}
|
||||
|
||||
TEST(open_file, resize_file_to_0_bytes) {
|
||||
const auto source_path =
|
||||
generate_test_file_name("./test_config", "file_manager_open_file_test");
|
||||
create_random_file(source_path, test_chunk_size * 4u)->close();
|
||||
auto &rf = test::create_random_file(test_chunk_size * 4u);
|
||||
const auto source_path = rf.get_path();
|
||||
rf.close();
|
||||
|
||||
mock_provider mp;
|
||||
mock_upload_manager um;
|
||||
@@ -503,9 +499,9 @@ TEST(open_file, resize_file_to_0_bytes) {
|
||||
}
|
||||
|
||||
TEST(open_file, resize_file_by_full_chunk) {
|
||||
const auto source_path =
|
||||
generate_test_file_name("./test_config", "file_manager_open_file_test");
|
||||
create_random_file(source_path, test_chunk_size * 4u)->close();
|
||||
auto &rf = test::create_random_file(test_chunk_size * 4u);
|
||||
const auto source_path = rf.get_path();
|
||||
rf.close();
|
||||
|
||||
mock_provider mp;
|
||||
mock_upload_manager um;
|
||||
@@ -556,7 +552,7 @@ TEST(open_file, can_add_handle) {
|
||||
event_system::instance().start();
|
||||
console_consumer c;
|
||||
const auto source_path =
|
||||
generate_test_file_name("./test_config", "file_manager_open_file_test");
|
||||
test::generate_test_file_name("file_manager_open_file_test");
|
||||
|
||||
mock_provider mp;
|
||||
mock_upload_manager um;
|
||||
@@ -618,7 +614,7 @@ TEST(open_file, can_remove_handle) {
|
||||
console_consumer c;
|
||||
|
||||
const auto source_path =
|
||||
generate_test_file_name("./test_config", "file_manager_open_file_test");
|
||||
test::generate_test_file_name("file_manager_open_file_test");
|
||||
|
||||
mock_provider mp;
|
||||
mock_upload_manager um;
|
||||
|
||||
@@ -31,11 +31,11 @@
|
||||
namespace repertory {
|
||||
static constexpr const std::size_t test_chunk_size = 1024u;
|
||||
static std::string ring_buffer_dir = utils::path::combine(
|
||||
"./test_config", {"file_manager_ring_buffer_open_file_test"});
|
||||
test::get_test_output_dir(), {"file_manager_ring_buffer_open_file_test"});
|
||||
|
||||
TEST(ring_buffer_open_file, can_forward_to_last_chunk) {
|
||||
const auto source_path =
|
||||
generate_test_file_name("./test_config", "ring_buffer_open_file");
|
||||
test::generate_test_file_name("ring_buffer_open_file");
|
||||
|
||||
mock_provider mp;
|
||||
|
||||
@@ -61,13 +61,13 @@ TEST(ring_buffer_open_file, can_forward_to_last_chunk) {
|
||||
}
|
||||
}
|
||||
|
||||
EXPECT_TRUE(utils::file::delete_directory_recursively(ring_buffer_dir));
|
||||
EXPECT_TRUE(utils::file::directory(ring_buffer_dir).remove_recursively());
|
||||
}
|
||||
|
||||
TEST(ring_buffer_open_file,
|
||||
can_forward_to_last_chunk_if_count_is_greater_than_remaining) {
|
||||
const auto source_path =
|
||||
generate_test_file_name("./test_config", "ring_buffer_open_file");
|
||||
test::generate_test_file_name("ring_buffer_open_file");
|
||||
|
||||
mock_provider mp;
|
||||
|
||||
@@ -93,12 +93,12 @@ TEST(ring_buffer_open_file,
|
||||
}
|
||||
}
|
||||
|
||||
EXPECT_TRUE(utils::file::delete_directory_recursively(ring_buffer_dir));
|
||||
EXPECT_TRUE(utils::file::directory(ring_buffer_dir).remove_recursively());
|
||||
}
|
||||
|
||||
TEST(ring_buffer_open_file, can_forward_after_last_chunk) {
|
||||
const auto source_path =
|
||||
generate_test_file_name("./test_config", "ring_buffer_open_file");
|
||||
test::generate_test_file_name("ring_buffer_open_file");
|
||||
|
||||
mock_provider mp;
|
||||
|
||||
@@ -125,12 +125,12 @@ TEST(ring_buffer_open_file, can_forward_after_last_chunk) {
|
||||
}
|
||||
}
|
||||
|
||||
EXPECT_TRUE(utils::file::delete_directory_recursively(ring_buffer_dir));
|
||||
EXPECT_TRUE(utils::file::directory(ring_buffer_dir).remove_recursively());
|
||||
}
|
||||
|
||||
TEST(ring_buffer_open_file, can_forward_and_rollover_after_last_chunk) {
|
||||
const auto source_path =
|
||||
generate_test_file_name("./test_config", "ring_buffer_open_file");
|
||||
test::generate_test_file_name("ring_buffer_open_file");
|
||||
|
||||
mock_provider mp;
|
||||
|
||||
@@ -153,12 +153,12 @@ TEST(ring_buffer_open_file, can_forward_and_rollover_after_last_chunk) {
|
||||
EXPECT_EQ(std::size_t(28u), rb.get_last_chunk());
|
||||
}
|
||||
|
||||
EXPECT_TRUE(utils::file::delete_directory_recursively(ring_buffer_dir));
|
||||
EXPECT_TRUE(utils::file::directory(ring_buffer_dir).remove_recursively());
|
||||
}
|
||||
|
||||
TEST(ring_buffer_open_file, can_reverse_to_first_chunk) {
|
||||
const auto source_path =
|
||||
generate_test_file_name("./test_config", "ring_buffer_open_file");
|
||||
test::generate_test_file_name("ring_buffer_open_file");
|
||||
|
||||
mock_provider mp;
|
||||
|
||||
@@ -184,13 +184,13 @@ TEST(ring_buffer_open_file, can_reverse_to_first_chunk) {
|
||||
}
|
||||
}
|
||||
|
||||
EXPECT_TRUE(utils::file::delete_directory_recursively(ring_buffer_dir));
|
||||
EXPECT_TRUE(utils::file::directory(ring_buffer_dir).remove_recursively());
|
||||
}
|
||||
|
||||
TEST(ring_buffer_open_file,
|
||||
can_reverse_to_first_chunk_if_count_is_greater_than_remaining) {
|
||||
const auto source_path =
|
||||
generate_test_file_name("./test_config", "ring_buffer_open_file");
|
||||
test::generate_test_file_name("ring_buffer_open_file");
|
||||
|
||||
mock_provider mp;
|
||||
|
||||
@@ -216,12 +216,12 @@ TEST(ring_buffer_open_file,
|
||||
}
|
||||
}
|
||||
|
||||
EXPECT_TRUE(utils::file::delete_directory_recursively(ring_buffer_dir));
|
||||
EXPECT_TRUE(utils::file::directory(ring_buffer_dir).remove_recursively());
|
||||
}
|
||||
|
||||
TEST(ring_buffer_open_file, can_reverse_before_first_chunk) {
|
||||
const auto source_path =
|
||||
generate_test_file_name("./test_config", "ring_buffer_open_file");
|
||||
test::generate_test_file_name("ring_buffer_open_file");
|
||||
|
||||
mock_provider mp;
|
||||
|
||||
@@ -248,12 +248,12 @@ TEST(ring_buffer_open_file, can_reverse_before_first_chunk) {
|
||||
}
|
||||
}
|
||||
|
||||
EXPECT_TRUE(utils::file::delete_directory_recursively(ring_buffer_dir));
|
||||
EXPECT_TRUE(utils::file::directory(ring_buffer_dir).remove_recursively());
|
||||
}
|
||||
|
||||
TEST(ring_buffer_open_file, can_reverse_and_rollover_before_first_chunk) {
|
||||
const auto source_path =
|
||||
generate_test_file_name("./test_config", "ring_buffer_open_file");
|
||||
test::generate_test_file_name("ring_buffer_open_file");
|
||||
|
||||
mock_provider mp;
|
||||
|
||||
@@ -284,12 +284,12 @@ TEST(ring_buffer_open_file, can_reverse_and_rollover_before_first_chunk) {
|
||||
}
|
||||
}
|
||||
|
||||
EXPECT_TRUE(utils::file::delete_directory_recursively(ring_buffer_dir));
|
||||
EXPECT_TRUE(utils::file::directory(ring_buffer_dir).remove_recursively());
|
||||
}
|
||||
|
||||
TEST(ring_buffer_open_file, can_reverse_full_ring) {
|
||||
const auto source_path =
|
||||
generate_test_file_name("./test_config", "ring_buffer_open_file");
|
||||
test::generate_test_file_name("ring_buffer_open_file");
|
||||
|
||||
mock_provider mp;
|
||||
|
||||
@@ -316,16 +316,14 @@ TEST(ring_buffer_open_file, can_reverse_full_ring) {
|
||||
}
|
||||
}
|
||||
|
||||
EXPECT_TRUE(utils::file::delete_directory_recursively(ring_buffer_dir));
|
||||
EXPECT_TRUE(utils::file::directory(ring_buffer_dir).remove_recursively());
|
||||
}
|
||||
|
||||
TEST(ring_buffer_open_file, read_full_file) {
|
||||
const auto download_source_path =
|
||||
generate_test_file_name("./test_config", "ring_buffer_open_file");
|
||||
auto nf = create_random_file(download_source_path, test_chunk_size * 32u);
|
||||
auto &nf = test::create_random_file(test_chunk_size * 32u);
|
||||
const auto download_source_path = nf.get_path();
|
||||
|
||||
const auto dest_path =
|
||||
generate_test_file_name("./test_config", "ring_buffer_open_file");
|
||||
const auto dest_path = test::generate_test_file_name("ring_buffer_open_file");
|
||||
|
||||
mock_provider mp;
|
||||
|
||||
@@ -335,8 +333,7 @@ TEST(ring_buffer_open_file, read_full_file) {
|
||||
fsi.directory = false;
|
||||
fsi.api_path = "/test.txt";
|
||||
fsi.size = test_chunk_size * 32u;
|
||||
fsi.source_path =
|
||||
generate_test_file_name("./test_config", "ring_buffer_open_file");
|
||||
fsi.source_path = test::generate_test_file_name("ring_buffer_open_file");
|
||||
|
||||
EXPECT_CALL(mp, read_file_bytes)
|
||||
.WillRepeatedly([&nf](const std::string & /* api_path */,
|
||||
@@ -346,9 +343,8 @@ TEST(ring_buffer_open_file, read_full_file) {
|
||||
EXPECT_FALSE(stop_requested);
|
||||
std::size_t bytes_read{};
|
||||
data.resize(size);
|
||||
auto ret = nf->read_bytes(&data[0u], size, offset, bytes_read)
|
||||
? api_error::success
|
||||
: api_error::os_error;
|
||||
auto ret = nf.read(data, offset, &bytes_read) ? api_error::success
|
||||
: api_error::os_error;
|
||||
EXPECT_EQ(bytes_read, data.size());
|
||||
return ret;
|
||||
});
|
||||
@@ -356,8 +352,9 @@ TEST(ring_buffer_open_file, read_full_file) {
|
||||
file_manager::ring_buffer_open_file rb(ring_buffer_dir, test_chunk_size,
|
||||
30U, fsi, mp, 8u);
|
||||
|
||||
native_file_ptr nf2;
|
||||
EXPECT_EQ(api_error::success, native_file::create_or_open(dest_path, nf2));
|
||||
auto ptr = utils::file::file::open_or_create_file(dest_path);
|
||||
auto &nf2 = *ptr;
|
||||
EXPECT_TRUE(nf2);
|
||||
|
||||
auto to_read = fsi.size;
|
||||
std::size_t chunk = 0u;
|
||||
@@ -367,28 +364,31 @@ TEST(ring_buffer_open_file, read_full_file) {
|
||||
rb.read(test_chunk_size, chunk * test_chunk_size, data));
|
||||
|
||||
std::size_t bytes_written{};
|
||||
EXPECT_TRUE(nf2->write_bytes(data.data(), data.size(),
|
||||
chunk * test_chunk_size, bytes_written));
|
||||
EXPECT_TRUE(nf2.write(data, chunk * test_chunk_size, &bytes_written));
|
||||
chunk++;
|
||||
to_read -= data.size();
|
||||
}
|
||||
nf2->close();
|
||||
nf->close();
|
||||
nf2.close();
|
||||
nf.close();
|
||||
|
||||
EXPECT_STREQ(utils::file::generate_sha256(download_source_path).c_str(),
|
||||
utils::file::generate_sha256(dest_path).c_str());
|
||||
auto hash1 = utils::file::file(download_source_path).sha256();
|
||||
auto hash2 = utils::file::file(dest_path).sha256();
|
||||
|
||||
EXPECT_TRUE(hash1.has_value());
|
||||
EXPECT_TRUE(hash2.has_value());
|
||||
if (hash1.has_value() && hash2.has_value()) {
|
||||
EXPECT_STREQ(hash1.value().c_str(), hash2.value().c_str());
|
||||
}
|
||||
}
|
||||
|
||||
EXPECT_TRUE(utils::file::delete_directory_recursively(ring_buffer_dir));
|
||||
EXPECT_TRUE(utils::file::directory(ring_buffer_dir).remove_recursively());
|
||||
}
|
||||
|
||||
TEST(ring_buffer_open_file, read_full_file_in_reverse) {
|
||||
const auto download_source_path =
|
||||
generate_test_file_name("./test_config", "ring_buffer_open_file");
|
||||
auto nf = create_random_file(download_source_path, test_chunk_size * 32u);
|
||||
auto &nf = test::create_random_file(test_chunk_size * 32u);
|
||||
const auto download_source_path = nf.get_path();
|
||||
|
||||
const auto dest_path =
|
||||
generate_test_file_name("./test_config", "ring_buffer_open_file");
|
||||
const auto dest_path = test::generate_test_file_name("ring_buffer_open_file");
|
||||
|
||||
mock_provider mp;
|
||||
|
||||
@@ -398,8 +398,7 @@ TEST(ring_buffer_open_file, read_full_file_in_reverse) {
|
||||
fsi.directory = false;
|
||||
fsi.api_path = "/test.txt";
|
||||
fsi.size = test_chunk_size * 32u;
|
||||
fsi.source_path =
|
||||
generate_test_file_name("./test_config", "ring_buffer_open_file");
|
||||
fsi.source_path = test::generate_test_file_name("ring_buffer_open_file");
|
||||
|
||||
EXPECT_CALL(mp, read_file_bytes)
|
||||
.WillRepeatedly([&nf](const std::string & /* api_path */,
|
||||
@@ -409,9 +408,8 @@ TEST(ring_buffer_open_file, read_full_file_in_reverse) {
|
||||
EXPECT_FALSE(stop_requested);
|
||||
std::size_t bytes_read{};
|
||||
data.resize(size);
|
||||
auto ret = nf->read_bytes(&data[0u], size, offset, bytes_read)
|
||||
? api_error::success
|
||||
: api_error::os_error;
|
||||
auto ret = nf.read(data, offset, &bytes_read) ? api_error::success
|
||||
: api_error::os_error;
|
||||
EXPECT_EQ(bytes_read, data.size());
|
||||
return ret;
|
||||
});
|
||||
@@ -419,8 +417,9 @@ TEST(ring_buffer_open_file, read_full_file_in_reverse) {
|
||||
file_manager::ring_buffer_open_file rb(ring_buffer_dir, test_chunk_size,
|
||||
30U, fsi, mp, 8u);
|
||||
|
||||
native_file_ptr nf2;
|
||||
EXPECT_EQ(api_error::success, native_file::create_or_open(dest_path, nf2));
|
||||
auto ptr = utils::file::file::open_or_create_file(dest_path);
|
||||
auto &nf2 = *ptr;
|
||||
EXPECT_TRUE(nf2);
|
||||
|
||||
auto to_read = fsi.size;
|
||||
std::size_t chunk = rb.get_total_chunks() - 1u;
|
||||
@@ -430,28 +429,31 @@ TEST(ring_buffer_open_file, read_full_file_in_reverse) {
|
||||
rb.read(test_chunk_size, chunk * test_chunk_size, data));
|
||||
|
||||
std::size_t bytes_written{};
|
||||
EXPECT_TRUE(nf2->write_bytes(data.data(), data.size(),
|
||||
chunk * test_chunk_size, bytes_written));
|
||||
EXPECT_TRUE(nf2.write(data, chunk * test_chunk_size, &bytes_written));
|
||||
chunk--;
|
||||
to_read -= data.size();
|
||||
}
|
||||
nf2->close();
|
||||
nf->close();
|
||||
nf2.close();
|
||||
nf.close();
|
||||
|
||||
EXPECT_STREQ(utils::file::generate_sha256(download_source_path).c_str(),
|
||||
utils::file::generate_sha256(dest_path).c_str());
|
||||
auto hash1 = utils::file::file(download_source_path).sha256();
|
||||
auto hash2 = utils::file::file(dest_path).sha256();
|
||||
|
||||
EXPECT_TRUE(hash1.has_value());
|
||||
EXPECT_TRUE(hash2.has_value());
|
||||
if (hash1.has_value() && hash2.has_value()) {
|
||||
EXPECT_STREQ(hash1.value().c_str(), hash2.value().c_str());
|
||||
}
|
||||
}
|
||||
|
||||
EXPECT_TRUE(utils::file::delete_directory_recursively(ring_buffer_dir));
|
||||
EXPECT_TRUE(utils::file::directory(ring_buffer_dir).remove_recursively());
|
||||
}
|
||||
|
||||
TEST(ring_buffer_open_file, read_full_file_in_partial_chunks) {
|
||||
const auto download_source_path =
|
||||
generate_test_file_name("./test_config", "ring_buffer_open_file");
|
||||
auto nf = create_random_file(download_source_path, test_chunk_size * 32u);
|
||||
auto &nf = test::create_random_file(test_chunk_size * 32u);
|
||||
const auto download_source_path = nf.get_path();
|
||||
|
||||
const auto dest_path =
|
||||
generate_test_file_name("./test_config", "ring_buffer_open_file");
|
||||
const auto dest_path = test::generate_test_file_name("test");
|
||||
|
||||
mock_provider mp;
|
||||
|
||||
@@ -461,8 +463,7 @@ TEST(ring_buffer_open_file, read_full_file_in_partial_chunks) {
|
||||
fsi.directory = false;
|
||||
fsi.api_path = "/test.txt";
|
||||
fsi.size = test_chunk_size * 32u;
|
||||
fsi.source_path =
|
||||
generate_test_file_name("./test_config", "ring_buffer_open_file");
|
||||
fsi.source_path = test::generate_test_file_name("test");
|
||||
|
||||
EXPECT_CALL(mp, read_file_bytes)
|
||||
.WillRepeatedly([&nf](const std::string & /* api_path */,
|
||||
@@ -472,9 +473,8 @@ TEST(ring_buffer_open_file, read_full_file_in_partial_chunks) {
|
||||
EXPECT_FALSE(stop_requested);
|
||||
std::size_t bytes_read{};
|
||||
data.resize(size);
|
||||
auto ret = nf->read_bytes(&data[0u], size, offset, bytes_read)
|
||||
? api_error::success
|
||||
: api_error::os_error;
|
||||
auto ret = nf.read(data, offset, &bytes_read) ? api_error::success
|
||||
: api_error::os_error;
|
||||
EXPECT_EQ(bytes_read, data.size());
|
||||
return ret;
|
||||
});
|
||||
@@ -482,8 +482,11 @@ TEST(ring_buffer_open_file, read_full_file_in_partial_chunks) {
|
||||
file_manager::ring_buffer_open_file rb(ring_buffer_dir, test_chunk_size,
|
||||
30U, fsi, mp, 8u);
|
||||
|
||||
native_file_ptr nf2;
|
||||
EXPECT_EQ(api_error::success, native_file::create_or_open(dest_path, nf2));
|
||||
auto ptr = utils::file::file::open_or_create_file(dest_path);
|
||||
auto &nf2 = *ptr;
|
||||
EXPECT_TRUE(nf2);
|
||||
// EXPECT_EQ(api_error::success, native_file::create_or_open(dest_path,
|
||||
// nf2));
|
||||
|
||||
auto total_read = std::uint64_t(0u);
|
||||
|
||||
@@ -492,27 +495,31 @@ TEST(ring_buffer_open_file, read_full_file_in_partial_chunks) {
|
||||
EXPECT_EQ(api_error::success, rb.read(3u, total_read, data));
|
||||
|
||||
std::size_t bytes_written{};
|
||||
EXPECT_TRUE(nf2->write_bytes(data.data(), data.size(), total_read,
|
||||
bytes_written));
|
||||
EXPECT_TRUE(
|
||||
nf2.write(data.data(), data.size(), total_read, &bytes_written));
|
||||
total_read += data.size();
|
||||
}
|
||||
nf2->close();
|
||||
nf->close();
|
||||
nf2.close();
|
||||
nf.close();
|
||||
|
||||
EXPECT_STREQ(utils::file::generate_sha256(download_source_path).c_str(),
|
||||
utils::file::generate_sha256(dest_path).c_str());
|
||||
auto hash1 = utils::file::file(download_source_path).sha256();
|
||||
auto hash2 = utils::file::file(dest_path).sha256();
|
||||
|
||||
EXPECT_TRUE(hash1.has_value());
|
||||
EXPECT_TRUE(hash2.has_value());
|
||||
if (hash1.has_value() && hash2.has_value()) {
|
||||
EXPECT_STREQ(hash1.value().c_str(), hash2.value().c_str());
|
||||
}
|
||||
}
|
||||
|
||||
EXPECT_TRUE(utils::file::delete_directory_recursively(ring_buffer_dir));
|
||||
EXPECT_TRUE(utils::file::directory(ring_buffer_dir).remove_recursively());
|
||||
}
|
||||
|
||||
TEST(ring_buffer_open_file, read_full_file_in_partial_chunks_in_reverse) {
|
||||
const auto download_source_path =
|
||||
generate_test_file_name("./test_config", "ring_buffer_open_file");
|
||||
auto nf = create_random_file(download_source_path, test_chunk_size * 32u);
|
||||
auto &nf = test::create_random_file(test_chunk_size * 32u);
|
||||
const auto download_source_path = nf.get_path();
|
||||
|
||||
const auto dest_path =
|
||||
generate_test_file_name("./test_config", "ring_buffer_open_file");
|
||||
const auto dest_path = test::generate_test_file_name("ring_buffer_open_file");
|
||||
|
||||
mock_provider mp;
|
||||
|
||||
@@ -522,8 +529,7 @@ TEST(ring_buffer_open_file, read_full_file_in_partial_chunks_in_reverse) {
|
||||
fsi.directory = false;
|
||||
fsi.api_path = "/test.txt";
|
||||
fsi.size = test_chunk_size * 32u;
|
||||
fsi.source_path =
|
||||
generate_test_file_name("./test_config", "ring_buffer_open_file");
|
||||
fsi.source_path = test::generate_test_file_name("ring_buffer_open_file");
|
||||
|
||||
EXPECT_CALL(mp, read_file_bytes)
|
||||
.WillRepeatedly([&nf](const std::string & /* api_path */,
|
||||
@@ -533,9 +539,8 @@ TEST(ring_buffer_open_file, read_full_file_in_partial_chunks_in_reverse) {
|
||||
EXPECT_FALSE(stop_requested);
|
||||
std::size_t bytes_read{};
|
||||
data.resize(size);
|
||||
auto ret = nf->read_bytes(&data[0u], size, offset, bytes_read)
|
||||
? api_error::success
|
||||
: api_error::os_error;
|
||||
auto ret = nf.read(data, offset, &bytes_read) ? api_error::success
|
||||
: api_error::os_error;
|
||||
EXPECT_EQ(bytes_read, data.size());
|
||||
return ret;
|
||||
});
|
||||
@@ -543,11 +548,12 @@ TEST(ring_buffer_open_file, read_full_file_in_partial_chunks_in_reverse) {
|
||||
file_manager::ring_buffer_open_file rb(ring_buffer_dir, test_chunk_size,
|
||||
30U, fsi, mp, 8u);
|
||||
|
||||
native_file_ptr nf2;
|
||||
EXPECT_EQ(api_error::success, native_file::create_or_open(dest_path, nf2));
|
||||
auto ptr = utils::file::file::open_or_create_file(dest_path);
|
||||
auto &nf2 = *ptr;
|
||||
EXPECT_TRUE(nf2);
|
||||
|
||||
auto total_read = std::uint64_t(0u);
|
||||
const auto read_size = 3u;
|
||||
std::uint64_t total_read{0U};
|
||||
const auto read_size{3U};
|
||||
|
||||
while (total_read < fsi.size) {
|
||||
const auto offset = fsi.size - total_read - read_size;
|
||||
@@ -560,18 +566,23 @@ TEST(ring_buffer_open_file, read_full_file_in_partial_chunks_in_reverse) {
|
||||
(remain >= read_size) ? offset : 0u, data));
|
||||
|
||||
std::size_t bytes_written{};
|
||||
EXPECT_TRUE(nf2->write_bytes(data.data(), data.size(),
|
||||
(remain >= read_size) ? offset : 0u,
|
||||
bytes_written));
|
||||
EXPECT_TRUE(
|
||||
nf2.write(data, (remain >= read_size) ? offset : 0u, &bytes_written));
|
||||
total_read += data.size();
|
||||
}
|
||||
nf2->close();
|
||||
nf->close();
|
||||
nf2.close();
|
||||
nf.close();
|
||||
|
||||
EXPECT_STREQ(utils::file::generate_sha256(download_source_path).c_str(),
|
||||
utils::file::generate_sha256(dest_path).c_str());
|
||||
auto hash1 = utils::file::file(download_source_path).sha256();
|
||||
auto hash2 = utils::file::file(dest_path).sha256();
|
||||
|
||||
EXPECT_TRUE(hash1.has_value());
|
||||
EXPECT_TRUE(hash2.has_value());
|
||||
if (hash1.has_value() && hash2.has_value()) {
|
||||
EXPECT_STREQ(hash1.value().c_str(), hash2.value().c_str());
|
||||
}
|
||||
}
|
||||
|
||||
EXPECT_TRUE(utils::file::delete_directory_recursively(ring_buffer_dir));
|
||||
EXPECT_TRUE(utils::file::directory(ring_buffer_dir).remove_recursively());
|
||||
}
|
||||
} // namespace repertory
|
||||
|
||||
@@ -34,7 +34,6 @@
|
||||
#include "utils/encrypting_reader.hpp"
|
||||
#include "utils/event_capture.hpp"
|
||||
#include "utils/file_utils.hpp"
|
||||
#include "utils/native_file.hpp"
|
||||
#include "utils/path.hpp"
|
||||
#include "utils/polling.hpp"
|
||||
#include "utils/string.hpp"
|
||||
@@ -43,7 +42,7 @@
|
||||
|
||||
namespace repertory {
|
||||
static std::string file_manager_dir =
|
||||
utils::path::combine("./test_config", {"file_manager_test"});
|
||||
utils::path::combine(test::get_test_output_dir(), {"file_manager_test"});
|
||||
|
||||
auto file_manager::open(std::shared_ptr<i_closeable_open_file> of,
|
||||
const open_file_data &ofd, std::uint64_t &handle,
|
||||
@@ -85,7 +84,7 @@ TEST(file_manager, can_start_and_stop) {
|
||||
}
|
||||
|
||||
event_system::instance().stop();
|
||||
// EXPECT_TRUE(utils::file::delete_directory_recursively(file_manager_dir));
|
||||
// EXPECT_TRUE(utils::file::remove_directory(file_manager_dir, true));
|
||||
}
|
||||
|
||||
TEST(file_manager, can_create_and_close_file) {
|
||||
@@ -118,7 +117,7 @@ TEST(file_manager, can_create_and_close_file) {
|
||||
{
|
||||
std::shared_ptr<i_open_file> f;
|
||||
|
||||
const auto now = utils::time::get_file_time_now();
|
||||
const auto now = utils::time::get_time_now();
|
||||
auto meta = create_meta_attributes(
|
||||
now, FILE_ATTRIBUTE_NORMAL | FILE_ATTRIBUTE_ARCHIVE, now + 1u,
|
||||
now + 2u, false, 1, "key", 2, now + 3u, 3u, 4u, 0u, source_path, 10,
|
||||
@@ -202,7 +201,7 @@ TEST(file_manager, can_create_and_close_file) {
|
||||
|
||||
polling::instance().stop();
|
||||
event_system::instance().stop();
|
||||
EXPECT_TRUE(utils::file::delete_directory_recursively(file_manager_dir));
|
||||
EXPECT_TRUE(utils::file::directory(file_manager_dir).remove_recursively());
|
||||
}
|
||||
|
||||
TEST(file_manager, can_open_and_close_file) {
|
||||
@@ -233,7 +232,7 @@ TEST(file_manager, can_open_and_close_file) {
|
||||
std::uint64_t handle{};
|
||||
{
|
||||
|
||||
const auto now = utils::time::get_file_time_now();
|
||||
const auto now = utils::time::get_time_now();
|
||||
auto meta = create_meta_attributes(
|
||||
now, FILE_ATTRIBUTE_NORMAL | FILE_ATTRIBUTE_ARCHIVE, now + 1u,
|
||||
now + 2u, false, 1, "key", 2, now + 3u, 3u, 4u, 0u, source_path, 10,
|
||||
@@ -318,7 +317,7 @@ TEST(file_manager, can_open_and_close_file) {
|
||||
|
||||
polling::instance().stop();
|
||||
event_system::instance().stop();
|
||||
EXPECT_TRUE(utils::file::delete_directory_recursively(file_manager_dir));
|
||||
EXPECT_TRUE(utils::file::directory(file_manager_dir).remove_recursively());
|
||||
}
|
||||
|
||||
TEST(file_manager, can_open_and_close_multiple_handles_for_same_file) {
|
||||
@@ -340,7 +339,7 @@ TEST(file_manager, can_open_and_close_multiple_handles_for_same_file) {
|
||||
const auto source_path = utils::path::combine(
|
||||
cfg.get_cache_directory(), {utils::create_uuid_string()});
|
||||
|
||||
const auto now = utils::time::get_file_time_now();
|
||||
const auto now = utils::time::get_time_now();
|
||||
auto meta = create_meta_attributes(
|
||||
now, FILE_ATTRIBUTE_NORMAL | FILE_ATTRIBUTE_ARCHIVE, now + 1u,
|
||||
now + 2u, false, 1, "key", 2, now + 3u, 3u, 4u, 0u, source_path, 10,
|
||||
@@ -391,7 +390,7 @@ TEST(file_manager, can_open_and_close_multiple_handles_for_same_file) {
|
||||
|
||||
polling::instance().stop();
|
||||
event_system::instance().stop();
|
||||
EXPECT_TRUE(utils::file::delete_directory_recursively(file_manager_dir));
|
||||
EXPECT_TRUE(utils::file::directory(file_manager_dir).remove_recursively());
|
||||
}
|
||||
|
||||
TEST(file_manager, download_is_stored_after_write_if_partially_downloaded) {
|
||||
@@ -420,15 +419,14 @@ TEST(file_manager, download_is_stored_after_write_if_partially_downloaded) {
|
||||
event_capture ec({"download_stored"},
|
||||
{"file_upload_completed", "file_upload_queued"});
|
||||
|
||||
const auto now = utils::time::get_file_time_now();
|
||||
const auto now = utils::time::get_time_now();
|
||||
auto meta = create_meta_attributes(
|
||||
now, FILE_ATTRIBUTE_NORMAL | FILE_ATTRIBUTE_ARCHIVE, now + 1u, now + 2u,
|
||||
false, 1, "key", 2, now + 3u, 3u, 4u,
|
||||
utils::encryption::encrypting_reader::get_data_chunk_size() * 4u,
|
||||
source_path, 10, now + 4u);
|
||||
auto nf = create_random_file(
|
||||
generate_test_file_name("./test_config", "file_manage_test"),
|
||||
utils::string::to_uint64(meta[META_SIZE]));
|
||||
auto &nf =
|
||||
test::create_random_file(utils::string::to_uint64(meta[META_SIZE]));
|
||||
|
||||
EXPECT_CALL(mp, get_filesystem_item)
|
||||
.WillRepeatedly([&meta](const std::string &api_path, bool directory,
|
||||
@@ -465,9 +463,8 @@ TEST(file_manager, download_is_stored_after_write_if_partially_downloaded) {
|
||||
if (offset == 0u) {
|
||||
std::size_t bytes_read{};
|
||||
data.resize(size);
|
||||
auto ret = nf->read_bytes(&data[0u], size, offset, bytes_read)
|
||||
? api_error::success
|
||||
: api_error::os_error;
|
||||
auto ret = nf.read(data, offset, &bytes_read) ? api_error::success
|
||||
: api_error::os_error;
|
||||
EXPECT_EQ(bytes_read, data.size());
|
||||
return ret;
|
||||
}
|
||||
@@ -542,11 +539,11 @@ TEST(file_manager, download_is_stored_after_write_if_partially_downloaded) {
|
||||
EXPECT_EQ(std::size_t(0u), fm.get_open_file_count());
|
||||
EXPECT_EQ(std::size_t(0u), fm.get_open_handle_count());
|
||||
|
||||
nf->close();
|
||||
nf.close();
|
||||
}
|
||||
|
||||
event_system::instance().stop();
|
||||
EXPECT_TRUE(utils::file::delete_directory_recursively(file_manager_dir));
|
||||
EXPECT_TRUE(utils::file::directory(file_manager_dir).remove_recursively());
|
||||
}
|
||||
|
||||
TEST(file_manager, upload_occurs_after_write_if_fully_downloaded) {
|
||||
@@ -583,15 +580,14 @@ TEST(file_manager, upload_occurs_after_write_if_fully_downloaded) {
|
||||
});
|
||||
event_capture ec({"download_end"});
|
||||
|
||||
const auto now = utils::time::get_file_time_now();
|
||||
const auto now = utils::time::get_time_now();
|
||||
auto meta = create_meta_attributes(
|
||||
now, FILE_ATTRIBUTE_NORMAL | FILE_ATTRIBUTE_ARCHIVE, now + 1u, now + 2u,
|
||||
false, 1, "key", 2, now + 3u, 3u, 4u,
|
||||
utils::encryption::encrypting_reader::get_data_chunk_size() * 4u,
|
||||
source_path, 10, now + 4u);
|
||||
auto nf = create_random_file(
|
||||
generate_test_file_name("./test_config", "file_manage_test"),
|
||||
utils::string::to_uint64(meta[META_SIZE]));
|
||||
auto &nf =
|
||||
test::create_random_file(utils::string::to_uint64(meta[META_SIZE]));
|
||||
|
||||
EXPECT_CALL(mp, get_filesystem_item)
|
||||
.WillRepeatedly([&meta](const std::string &api_path, bool directory,
|
||||
@@ -623,9 +619,8 @@ TEST(file_manager, upload_occurs_after_write_if_fully_downloaded) {
|
||||
stop_type & /* stop_requested */) -> api_error {
|
||||
std::size_t bytes_read{};
|
||||
data.resize(size);
|
||||
auto ret = nf->read_bytes(&data[0u], size, offset, bytes_read)
|
||||
? api_error::success
|
||||
: api_error::os_error;
|
||||
auto ret = nf.read(data, offset, &bytes_read) ? api_error::success
|
||||
: api_error::os_error;
|
||||
EXPECT_EQ(bytes_read, data.size());
|
||||
return ret;
|
||||
});
|
||||
@@ -660,16 +655,16 @@ TEST(file_manager, upload_occurs_after_write_if_fully_downloaded) {
|
||||
|
||||
fm.stop();
|
||||
|
||||
nf->close();
|
||||
nf.close();
|
||||
}
|
||||
|
||||
polling::instance().stop();
|
||||
event_system::instance().stop();
|
||||
EXPECT_TRUE(utils::file::delete_directory_recursively(file_manager_dir));
|
||||
EXPECT_TRUE(utils::file::directory(file_manager_dir).remove_recursively());
|
||||
}
|
||||
|
||||
TEST(file_manager, can_evict_file) {
|
||||
EXPECT_TRUE(utils::file::delete_directory_recursively(file_manager_dir));
|
||||
EXPECT_TRUE(utils::file::directory(file_manager_dir).remove_recursively());
|
||||
{
|
||||
console_consumer c;
|
||||
event_system::instance().start();
|
||||
@@ -694,7 +689,7 @@ TEST(file_manager, can_evict_file) {
|
||||
const auto source_path = utils::path::combine(
|
||||
cfg.get_cache_directory(), {utils::create_uuid_string()});
|
||||
|
||||
const auto now = utils::time::get_file_time_now();
|
||||
const auto now = utils::time::get_time_now();
|
||||
|
||||
auto meta = create_meta_attributes(
|
||||
now, FILE_ATTRIBUTE_NORMAL | FILE_ATTRIBUTE_ARCHIVE, now + 1u, now + 2u,
|
||||
@@ -735,15 +730,15 @@ TEST(file_manager, can_evict_file) {
|
||||
std::size_t bytes_written{};
|
||||
EXPECT_EQ(api_error::success, f->write(0U, data, bytes_written));
|
||||
|
||||
std::uint64_t file_size{};
|
||||
EXPECT_TRUE(utils::file::get_file_size(source_path, file_size));
|
||||
EXPECT_EQ(static_cast<std::uint64_t>(data.size()), file_size);
|
||||
auto opt_size = utils::file::file{source_path}.size();
|
||||
EXPECT_TRUE(opt_size.has_value());
|
||||
EXPECT_EQ(static_cast<std::uint64_t>(data.size()), opt_size.value());
|
||||
}
|
||||
|
||||
fm.close(handle);
|
||||
capture.wait_for_empty();
|
||||
|
||||
EXPECT_TRUE(utils::retryable_action(
|
||||
EXPECT_TRUE(utils::retry_action(
|
||||
[&fm]() -> bool { return not fm.is_processing("/test_evict.txt"); }));
|
||||
|
||||
EXPECT_CALL(mp, get_item_meta(_, META_SOURCE, _))
|
||||
@@ -764,17 +759,17 @@ TEST(file_manager, can_evict_file) {
|
||||
return api_error::success;
|
||||
});
|
||||
EXPECT_TRUE(fm.evict_file("/test_evict.txt"));
|
||||
EXPECT_FALSE(utils::file::is_file(source_path));
|
||||
EXPECT_FALSE(utils::file::file(source_path).exists());
|
||||
|
||||
fm.stop();
|
||||
}
|
||||
|
||||
event_system::instance().stop();
|
||||
EXPECT_TRUE(utils::file::delete_directory_recursively(file_manager_dir));
|
||||
EXPECT_TRUE(utils::file::directory(file_manager_dir).remove_recursively());
|
||||
}
|
||||
|
||||
TEST(file_manager, evict_file_fails_if_file_is_pinned) {
|
||||
EXPECT_TRUE(utils::file::delete_directory_recursively(file_manager_dir));
|
||||
EXPECT_TRUE(utils::file::directory(file_manager_dir).remove_recursively());
|
||||
{
|
||||
app_config cfg(provider_type::sia, file_manager_dir);
|
||||
cfg.set_enable_chunk_downloader_timeout(false);
|
||||
@@ -796,11 +791,11 @@ TEST(file_manager, evict_file_fails_if_file_is_pinned) {
|
||||
}
|
||||
|
||||
event_system::instance().stop();
|
||||
EXPECT_TRUE(utils::file::delete_directory_recursively(file_manager_dir));
|
||||
EXPECT_TRUE(utils::file::directory(file_manager_dir).remove_recursively());
|
||||
}
|
||||
|
||||
TEST(file_manager, evict_file_fails_if_provider_is_direct_only) {
|
||||
EXPECT_TRUE(utils::file::delete_directory_recursively(file_manager_dir));
|
||||
EXPECT_TRUE(utils::file::directory(file_manager_dir).remove_recursively());
|
||||
|
||||
{
|
||||
app_config cfg(provider_type::sia, file_manager_dir);
|
||||
@@ -812,11 +807,11 @@ TEST(file_manager, evict_file_fails_if_provider_is_direct_only) {
|
||||
EXPECT_FALSE(fm.evict_file("/test.txt"));
|
||||
}
|
||||
|
||||
EXPECT_TRUE(utils::file::delete_directory_recursively(file_manager_dir));
|
||||
EXPECT_TRUE(utils::file::directory(file_manager_dir).remove_recursively());
|
||||
}
|
||||
|
||||
TEST(file_manager, evict_file_fails_if_file_is_open) {
|
||||
EXPECT_TRUE(utils::file::delete_directory_recursively(file_manager_dir));
|
||||
EXPECT_TRUE(utils::file::directory(file_manager_dir).remove_recursively());
|
||||
|
||||
{
|
||||
app_config cfg(provider_type::sia, file_manager_dir);
|
||||
@@ -862,12 +857,12 @@ TEST(file_manager, evict_file_fails_if_file_is_open) {
|
||||
fm.close(handle);
|
||||
}
|
||||
|
||||
EXPECT_TRUE(utils::file::delete_directory_recursively(file_manager_dir));
|
||||
EXPECT_TRUE(utils::file::directory(file_manager_dir).remove_recursively());
|
||||
}
|
||||
|
||||
TEST(file_manager,
|
||||
evict_file_fails_if_unable_to_get_source_path_from_item_meta) {
|
||||
EXPECT_TRUE(utils::file::delete_directory_recursively(file_manager_dir));
|
||||
EXPECT_TRUE(utils::file::directory(file_manager_dir).remove_recursively());
|
||||
|
||||
{
|
||||
app_config cfg(provider_type::sia, file_manager_dir);
|
||||
@@ -897,11 +892,11 @@ TEST(file_manager,
|
||||
EXPECT_FALSE(fm.evict_file("/test_open.txt"));
|
||||
}
|
||||
|
||||
EXPECT_TRUE(utils::file::delete_directory_recursively(file_manager_dir));
|
||||
EXPECT_TRUE(utils::file::directory(file_manager_dir).remove_recursively());
|
||||
}
|
||||
|
||||
TEST(file_manager, evict_file_fails_if_source_path_is_empty) {
|
||||
EXPECT_TRUE(utils::file::delete_directory_recursively(file_manager_dir));
|
||||
EXPECT_TRUE(utils::file::directory(file_manager_dir).remove_recursively());
|
||||
|
||||
{
|
||||
app_config cfg(provider_type::sia, file_manager_dir);
|
||||
@@ -931,11 +926,11 @@ TEST(file_manager, evict_file_fails_if_source_path_is_empty) {
|
||||
EXPECT_FALSE(fm.evict_file("/test_open.txt"));
|
||||
}
|
||||
|
||||
EXPECT_TRUE(utils::file::delete_directory_recursively(file_manager_dir));
|
||||
EXPECT_TRUE(utils::file::directory(file_manager_dir).remove_recursively());
|
||||
}
|
||||
|
||||
TEST(file_manager, evict_file_fails_if_file_is_uploading) {
|
||||
EXPECT_TRUE(utils::file::delete_directory_recursively(file_manager_dir));
|
||||
EXPECT_TRUE(utils::file::directory(file_manager_dir).remove_recursively());
|
||||
{
|
||||
console_consumer c;
|
||||
event_system::instance().start();
|
||||
@@ -960,7 +955,7 @@ TEST(file_manager, evict_file_fails_if_file_is_uploading) {
|
||||
const auto source_path = utils::path::combine(
|
||||
cfg.get_cache_directory(), {utils::create_uuid_string()});
|
||||
|
||||
const auto now = utils::time::get_file_time_now();
|
||||
const auto now = utils::time::get_time_now();
|
||||
|
||||
auto meta = create_meta_attributes(
|
||||
now, FILE_ATTRIBUTE_NORMAL | FILE_ATTRIBUTE_ARCHIVE, now + 1u, now + 2u,
|
||||
@@ -1008,29 +1003,30 @@ TEST(file_manager, evict_file_fails_if_file_is_uploading) {
|
||||
std::size_t bytes_written{};
|
||||
EXPECT_EQ(api_error::success, f->write(0U, data, bytes_written));
|
||||
|
||||
std::uint64_t file_size{};
|
||||
EXPECT_TRUE(utils::file::get_file_size(source_path, file_size));
|
||||
EXPECT_EQ(static_cast<std::uint64_t>(data.size()), file_size);
|
||||
auto opt_size = utils::file::file{source_path}.size();
|
||||
EXPECT_TRUE(opt_size.has_value());
|
||||
EXPECT_EQ(static_cast<std::uint64_t>(data.size()), opt_size.value());
|
||||
|
||||
fm.close(handle);
|
||||
|
||||
EXPECT_TRUE(utils::retryable_action(
|
||||
EXPECT_TRUE(utils::retry_action(
|
||||
[&fm]() -> bool { return fm.is_processing("/test_evict.txt"); }));
|
||||
EXPECT_FALSE(fm.evict_file("/test_evict.txt"));
|
||||
}
|
||||
|
||||
capture.wait_for_empty();
|
||||
|
||||
EXPECT_TRUE(utils::file::is_file(source_path));
|
||||
EXPECT_TRUE(utils::file::file(source_path).exists());
|
||||
|
||||
fm.stop();
|
||||
}
|
||||
|
||||
event_system::instance().stop();
|
||||
EXPECT_TRUE(utils::file::delete_directory_recursively(file_manager_dir));
|
||||
EXPECT_TRUE(utils::file::directory(file_manager_dir).remove_recursively());
|
||||
}
|
||||
|
||||
TEST(file_manager, evict_file_fails_if_file_is_in_upload_queue) {
|
||||
EXPECT_TRUE(utils::file::delete_directory_recursively(file_manager_dir));
|
||||
EXPECT_TRUE(utils::file::directory(file_manager_dir).remove_recursively());
|
||||
|
||||
{
|
||||
app_config cfg(provider_type::sia, file_manager_dir);
|
||||
@@ -1051,11 +1047,11 @@ TEST(file_manager, evict_file_fails_if_file_is_in_upload_queue) {
|
||||
EXPECT_FALSE(fm.evict_file("/test_evict.txt"));
|
||||
}
|
||||
|
||||
EXPECT_TRUE(utils::file::delete_directory_recursively(file_manager_dir));
|
||||
EXPECT_TRUE(utils::file::directory(file_manager_dir).remove_recursively());
|
||||
}
|
||||
|
||||
TEST(file_manager, evict_file_fails_if_file_is_modified) {
|
||||
EXPECT_TRUE(utils::file::delete_directory_recursively(file_manager_dir));
|
||||
EXPECT_TRUE(utils::file::directory(file_manager_dir).remove_recursively());
|
||||
|
||||
{
|
||||
app_config cfg(provider_type::sia, file_manager_dir);
|
||||
@@ -1097,11 +1093,11 @@ TEST(file_manager, evict_file_fails_if_file_is_modified) {
|
||||
EXPECT_FALSE(fm.evict_file("/test_evict.txt"));
|
||||
}
|
||||
|
||||
EXPECT_TRUE(utils::file::delete_directory_recursively(file_manager_dir));
|
||||
EXPECT_TRUE(utils::file::directory(file_manager_dir).remove_recursively());
|
||||
}
|
||||
|
||||
TEST(file_manager, evict_file_fails_if_file_is_not_complete) {
|
||||
EXPECT_TRUE(utils::file::delete_directory_recursively(file_manager_dir));
|
||||
EXPECT_TRUE(utils::file::directory(file_manager_dir).remove_recursively());
|
||||
|
||||
{
|
||||
app_config cfg(provider_type::sia, file_manager_dir);
|
||||
@@ -1145,11 +1141,11 @@ TEST(file_manager, evict_file_fails_if_file_is_not_complete) {
|
||||
EXPECT_FALSE(fm.evict_file("/test_evict.txt"));
|
||||
}
|
||||
|
||||
EXPECT_TRUE(utils::file::delete_directory_recursively(file_manager_dir));
|
||||
EXPECT_TRUE(utils::file::directory(file_manager_dir).remove_recursively());
|
||||
}
|
||||
|
||||
TEST(file_manager, can_get_directory_items) {
|
||||
EXPECT_TRUE(utils::file::delete_directory_recursively(file_manager_dir));
|
||||
EXPECT_TRUE(utils::file::directory(file_manager_dir).remove_recursively());
|
||||
|
||||
{
|
||||
app_config cfg(provider_type::sia, file_manager_dir);
|
||||
@@ -1179,11 +1175,11 @@ TEST(file_manager, can_get_directory_items) {
|
||||
EXPECT_EQ(std::size_t(2U), list.size());
|
||||
}
|
||||
|
||||
EXPECT_TRUE(utils::file::delete_directory_recursively(file_manager_dir));
|
||||
EXPECT_TRUE(utils::file::directory(file_manager_dir).remove_recursively());
|
||||
}
|
||||
|
||||
TEST(file_manager, file_is_not_opened_if_provider_create_file_fails) {
|
||||
EXPECT_TRUE(utils::file::delete_directory_recursively(file_manager_dir));
|
||||
EXPECT_TRUE(utils::file::directory(file_manager_dir).remove_recursively());
|
||||
|
||||
{
|
||||
app_config cfg(provider_type::sia, file_manager_dir);
|
||||
@@ -1192,7 +1188,7 @@ TEST(file_manager, file_is_not_opened_if_provider_create_file_fails) {
|
||||
|
||||
EXPECT_CALL(mp, is_direct_only()).WillRepeatedly(Return(false));
|
||||
|
||||
const auto now = utils::time::get_file_time_now();
|
||||
const auto now = utils::time::get_time_now();
|
||||
auto meta = create_meta_attributes(
|
||||
now, FILE_ATTRIBUTE_NORMAL | FILE_ATTRIBUTE_ARCHIVE, now + 1u, now + 2u,
|
||||
false, 1, "", 2, now + 3u, 3u, 4u, 0u, "/test_create.src", 10,
|
||||
@@ -1215,11 +1211,11 @@ TEST(file_manager, file_is_not_opened_if_provider_create_file_fails) {
|
||||
EXPECT_EQ(std::size_t(0U), fm.get_open_file_count());
|
||||
}
|
||||
|
||||
EXPECT_TRUE(utils::file::delete_directory_recursively(file_manager_dir));
|
||||
EXPECT_TRUE(utils::file::directory(file_manager_dir).remove_recursively());
|
||||
}
|
||||
|
||||
TEST(file_manager, create_fails_if_provider_create_is_unsuccessful) {
|
||||
EXPECT_TRUE(utils::file::delete_directory_recursively(file_manager_dir));
|
||||
EXPECT_TRUE(utils::file::directory(file_manager_dir).remove_recursively());
|
||||
|
||||
{
|
||||
app_config cfg(provider_type::sia, file_manager_dir);
|
||||
@@ -1246,12 +1242,12 @@ TEST(file_manager, create_fails_if_provider_create_is_unsuccessful) {
|
||||
EXPECT_EQ(std::size_t(0U), fm.get_open_file_count());
|
||||
}
|
||||
|
||||
EXPECT_TRUE(utils::file::delete_directory_recursively(file_manager_dir));
|
||||
EXPECT_TRUE(utils::file::directory(file_manager_dir).remove_recursively());
|
||||
}
|
||||
|
||||
TEST(file_manager, get_open_file_fails_if_file_is_not_open) {
|
||||
|
||||
EXPECT_TRUE(utils::file::delete_directory_recursively(file_manager_dir));
|
||||
EXPECT_TRUE(utils::file::directory(file_manager_dir).remove_recursively());
|
||||
|
||||
{
|
||||
app_config cfg(provider_type::sia, file_manager_dir);
|
||||
@@ -1270,12 +1266,12 @@ TEST(file_manager, get_open_file_fails_if_file_is_not_open) {
|
||||
EXPECT_FALSE(f);
|
||||
}
|
||||
|
||||
EXPECT_TRUE(utils::file::delete_directory_recursively(file_manager_dir));
|
||||
EXPECT_TRUE(utils::file::directory(file_manager_dir).remove_recursively());
|
||||
}
|
||||
|
||||
TEST(file_manager,
|
||||
get_open_file_promotes_non_writeable_file_if_writeable_is_specified) {
|
||||
EXPECT_TRUE(utils::file::delete_directory_recursively(file_manager_dir));
|
||||
EXPECT_TRUE(utils::file::directory(file_manager_dir).remove_recursively());
|
||||
|
||||
{
|
||||
app_config cfg(provider_type::sia, file_manager_dir);
|
||||
@@ -1355,11 +1351,11 @@ TEST(file_manager,
|
||||
EXPECT_EQ(std::size_t(1U), fm.get_open_file_count());
|
||||
}
|
||||
|
||||
EXPECT_TRUE(utils::file::delete_directory_recursively(file_manager_dir));
|
||||
EXPECT_TRUE(utils::file::directory(file_manager_dir).remove_recursively());
|
||||
}
|
||||
|
||||
TEST(file_manager, open_file_fails_if_file_is_not_found) {
|
||||
EXPECT_TRUE(utils::file::delete_directory_recursively(file_manager_dir));
|
||||
EXPECT_TRUE(utils::file::directory(file_manager_dir).remove_recursively());
|
||||
|
||||
{
|
||||
app_config cfg(provider_type::sia, file_manager_dir);
|
||||
@@ -1380,11 +1376,11 @@ TEST(file_manager, open_file_fails_if_file_is_not_found) {
|
||||
EXPECT_EQ(std::size_t(0U), fm.get_open_file_count());
|
||||
}
|
||||
|
||||
EXPECT_TRUE(utils::file::delete_directory_recursively(file_manager_dir));
|
||||
EXPECT_TRUE(utils::file::directory(file_manager_dir).remove_recursively());
|
||||
}
|
||||
|
||||
TEST(file_manager, open_file_fails_if_provider_get_filesystem_item_fails) {
|
||||
EXPECT_TRUE(utils::file::delete_directory_recursively(file_manager_dir));
|
||||
EXPECT_TRUE(utils::file::directory(file_manager_dir).remove_recursively());
|
||||
|
||||
{
|
||||
app_config cfg(provider_type::sia, file_manager_dir);
|
||||
@@ -1424,11 +1420,11 @@ TEST(file_manager, open_file_fails_if_provider_get_filesystem_item_fails) {
|
||||
EXPECT_EQ(std::size_t(0U), fm.get_open_file_count());
|
||||
}
|
||||
|
||||
EXPECT_TRUE(utils::file::delete_directory_recursively(file_manager_dir));
|
||||
EXPECT_TRUE(utils::file::directory(file_manager_dir).remove_recursively());
|
||||
}
|
||||
|
||||
TEST(file_manager, open_file_fails_if_provider_set_item_meta_fails) {
|
||||
EXPECT_TRUE(utils::file::delete_directory_recursively(file_manager_dir));
|
||||
EXPECT_TRUE(utils::file::directory(file_manager_dir).remove_recursively());
|
||||
|
||||
{
|
||||
app_config cfg(provider_type::sia, file_manager_dir);
|
||||
@@ -1475,11 +1471,11 @@ TEST(file_manager, open_file_fails_if_provider_set_item_meta_fails) {
|
||||
EXPECT_EQ(std::size_t(0U), fm.get_open_file_count());
|
||||
}
|
||||
|
||||
EXPECT_TRUE(utils::file::delete_directory_recursively(file_manager_dir));
|
||||
EXPECT_TRUE(utils::file::directory(file_manager_dir).remove_recursively());
|
||||
}
|
||||
|
||||
TEST(file_manager, open_file_creates_source_path_if_empty) {
|
||||
EXPECT_TRUE(utils::file::delete_directory_recursively(file_manager_dir));
|
||||
EXPECT_TRUE(utils::file::directory(file_manager_dir).remove_recursively());
|
||||
|
||||
{
|
||||
app_config cfg(provider_type::sia, file_manager_dir);
|
||||
@@ -1538,11 +1534,11 @@ TEST(file_manager, open_file_creates_source_path_if_empty) {
|
||||
EXPECT_EQ(std::size_t(1U), fm.get_open_file_count());
|
||||
}
|
||||
|
||||
EXPECT_TRUE(utils::file::delete_directory_recursively(file_manager_dir));
|
||||
EXPECT_TRUE(utils::file::directory(file_manager_dir).remove_recursively());
|
||||
}
|
||||
|
||||
TEST(file_manager, open_file_first_file_handle_is_not_zero) {
|
||||
EXPECT_TRUE(utils::file::delete_directory_recursively(file_manager_dir));
|
||||
EXPECT_TRUE(utils::file::directory(file_manager_dir).remove_recursively());
|
||||
|
||||
{
|
||||
app_config cfg(provider_type::sia, file_manager_dir);
|
||||
@@ -1586,11 +1582,11 @@ TEST(file_manager, open_file_first_file_handle_is_not_zero) {
|
||||
EXPECT_GT(handle, std::uint64_t(0U));
|
||||
}
|
||||
|
||||
EXPECT_TRUE(utils::file::delete_directory_recursively(file_manager_dir));
|
||||
EXPECT_TRUE(utils::file::directory(file_manager_dir).remove_recursively());
|
||||
}
|
||||
|
||||
TEST(file_manager, can_remove_file) {
|
||||
EXPECT_TRUE(utils::file::delete_directory_recursively(file_manager_dir));
|
||||
EXPECT_TRUE(utils::file::directory(file_manager_dir).remove_recursively());
|
||||
|
||||
{
|
||||
app_config cfg(provider_type::sia, file_manager_dir);
|
||||
@@ -1601,11 +1597,11 @@ TEST(file_manager, can_remove_file) {
|
||||
|
||||
file_manager fm(cfg, mp);
|
||||
|
||||
native_file::native_file_ptr f{};
|
||||
EXPECT_EQ(api_error::success,
|
||||
native_file::create_or_open("./test_remove.txt", f));
|
||||
f->close();
|
||||
EXPECT_TRUE(utils::file::is_file("./test_remove.txt"));
|
||||
{
|
||||
auto file = utils::file::file::open_or_create_file("./test_remove.txt");
|
||||
EXPECT_TRUE(*file);
|
||||
}
|
||||
EXPECT_TRUE(utils::file::file("./test_remove.txt").exists());
|
||||
|
||||
EXPECT_CALL(mp, get_filesystem_item)
|
||||
.WillOnce([](const std::string &api_path, bool directory,
|
||||
@@ -1624,14 +1620,14 @@ TEST(file_manager, can_remove_file) {
|
||||
|
||||
EXPECT_EQ(api_error::success, fm.remove_file("/test_remove.txt"));
|
||||
|
||||
EXPECT_FALSE(utils::file::is_file("./test_remove.txt"));
|
||||
EXPECT_FALSE(utils::file::file("./test_remove.txt").exists());
|
||||
}
|
||||
|
||||
EXPECT_TRUE(utils::file::delete_directory_recursively(file_manager_dir));
|
||||
EXPECT_TRUE(utils::file::directory(file_manager_dir).remove_recursively());
|
||||
}
|
||||
|
||||
TEST(file_manager, can_queue_and_remove_upload) {
|
||||
EXPECT_TRUE(utils::file::delete_directory_recursively(file_manager_dir));
|
||||
EXPECT_TRUE(utils::file::directory(file_manager_dir).remove_recursively());
|
||||
|
||||
console_consumer c;
|
||||
event_system::instance().start();
|
||||
@@ -1662,11 +1658,11 @@ TEST(file_manager, can_queue_and_remove_upload) {
|
||||
}
|
||||
|
||||
event_system::instance().stop();
|
||||
EXPECT_TRUE(utils::file::delete_directory_recursively(file_manager_dir));
|
||||
EXPECT_TRUE(utils::file::directory(file_manager_dir).remove_recursively());
|
||||
}
|
||||
|
||||
TEST(file_manager, remove_file_fails_if_open_file_is_modified) {
|
||||
EXPECT_TRUE(utils::file::delete_directory_recursively(file_manager_dir));
|
||||
EXPECT_TRUE(utils::file::directory(file_manager_dir).remove_recursively());
|
||||
|
||||
{
|
||||
app_config cfg(provider_type::sia, file_manager_dir);
|
||||
@@ -1716,7 +1712,7 @@ TEST(file_manager, remove_file_fails_if_open_file_is_modified) {
|
||||
EXPECT_EQ(api_error::file_in_use, fm.remove_file("/test_remove.txt"));
|
||||
}
|
||||
|
||||
EXPECT_TRUE(utils::file::delete_directory_recursively(file_manager_dir));
|
||||
EXPECT_TRUE(utils::file::directory(file_manager_dir).remove_recursively());
|
||||
}
|
||||
|
||||
TEST(file_manager, file_is_closed_after_download_timeout) {
|
||||
@@ -1744,7 +1740,7 @@ TEST(file_manager, file_is_closed_after_download_timeout) {
|
||||
ee.get_api_path().get<std::string>().c_str());
|
||||
});
|
||||
|
||||
const auto now = utils::time::get_file_time_now();
|
||||
const auto now = utils::time::get_time_now();
|
||||
auto meta = create_meta_attributes(
|
||||
now, FILE_ATTRIBUTE_NORMAL | FILE_ATTRIBUTE_ARCHIVE, now + 1u, now + 2u,
|
||||
false, 1, "key", 2, now + 3u, 3u, 4u,
|
||||
@@ -1814,11 +1810,11 @@ TEST(file_manager, file_is_closed_after_download_timeout) {
|
||||
}
|
||||
|
||||
event_system::instance().stop();
|
||||
EXPECT_TRUE(utils::file::delete_directory_recursively(file_manager_dir));
|
||||
EXPECT_TRUE(utils::file::directory(file_manager_dir).remove_recursively());
|
||||
}
|
||||
|
||||
TEST(file_manager, remove_file_fails_if_file_does_not_exist) {
|
||||
EXPECT_TRUE(utils::file::delete_directory_recursively(file_manager_dir));
|
||||
EXPECT_TRUE(utils::file::directory(file_manager_dir).remove_recursively());
|
||||
{
|
||||
app_config cfg(provider_type::sia, file_manager_dir);
|
||||
cfg.set_enable_chunk_downloader_timeout(false);
|
||||
@@ -1839,11 +1835,11 @@ TEST(file_manager, remove_file_fails_if_file_does_not_exist) {
|
||||
EXPECT_EQ(api_error::item_not_found, fm.remove_file("/test_remove.txt"));
|
||||
}
|
||||
|
||||
EXPECT_TRUE(utils::file::delete_directory_recursively(file_manager_dir));
|
||||
EXPECT_TRUE(utils::file::directory(file_manager_dir).remove_recursively());
|
||||
}
|
||||
|
||||
TEST(file_manager, remove_file_fails_if_provider_remove_file_fails) {
|
||||
EXPECT_TRUE(utils::file::delete_directory_recursively(file_manager_dir));
|
||||
EXPECT_TRUE(utils::file::directory(file_manager_dir).remove_recursively());
|
||||
|
||||
{
|
||||
app_config cfg(provider_type::sia, file_manager_dir);
|
||||
@@ -1871,6 +1867,6 @@ TEST(file_manager, remove_file_fails_if_provider_remove_file_fails) {
|
||||
EXPECT_EQ(api_error::item_not_found, fm.remove_file("/test_remove.txt"));
|
||||
}
|
||||
|
||||
EXPECT_TRUE(utils::file::delete_directory_recursively(file_manager_dir));
|
||||
EXPECT_TRUE(utils::file::directory(file_manager_dir).remove_recursively());
|
||||
}
|
||||
} // namespace repertory
|
||||
|
||||
@@ -35,8 +35,7 @@ TEST(upload, can_upload_a_valid_file) {
|
||||
|
||||
event_system::instance().start();
|
||||
|
||||
const auto source_path =
|
||||
generate_test_file_name("./test_config", "upload_test");
|
||||
const auto source_path = test::generate_test_file_name("upload_test");
|
||||
|
||||
mock_provider mp;
|
||||
|
||||
@@ -79,8 +78,7 @@ TEST(upload, can_cancel_upload) {
|
||||
|
||||
event_system::instance().start();
|
||||
|
||||
const auto source_path =
|
||||
generate_test_file_name("./test_config", "upload_test");
|
||||
const auto source_path = test::generate_test_file_name("upload_test");
|
||||
|
||||
mock_provider mp;
|
||||
|
||||
@@ -145,8 +143,7 @@ TEST(upload, can_stop_upload) {
|
||||
|
||||
event_system::instance().start();
|
||||
|
||||
const auto source_path =
|
||||
generate_test_file_name("./test_config", "upload_test");
|
||||
const auto source_path = test::generate_test_file_name("upload_test");
|
||||
|
||||
mock_provider mp;
|
||||
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -57,7 +57,7 @@ const auto check_forced_dirs = [](const repertory::directory_item_list &list) {
|
||||
|
||||
const auto create_directory = [](repertory::i_provider &provider,
|
||||
const std::string &api_path) {
|
||||
auto date = repertory::utils::time::get_file_time_now();
|
||||
auto date = repertory::utils::time::get_time_now();
|
||||
auto meta = repertory::create_meta_attributes(
|
||||
date, 1U, date + 1U, date + 2U, true, getgid(), "", 0700, date + 3U, 2U,
|
||||
3U, 0U, api_path + "_src", getuid(), date + 4U);
|
||||
@@ -107,10 +107,9 @@ const auto create_directory = [](repertory::i_provider &provider,
|
||||
|
||||
const auto create_file = [](repertory::i_provider &provider,
|
||||
const std::string &api_path) {
|
||||
auto source_path =
|
||||
repertory::generate_test_file_name("./test_config", "providers_test");
|
||||
auto source_path = repertory::test::generate_test_file_name("providers_test");
|
||||
|
||||
auto date = repertory::utils::time::get_file_time_now();
|
||||
auto date = repertory::utils::time::get_time_now();
|
||||
auto meta = repertory::create_meta_attributes(
|
||||
date, 1U, date + 1U, date + 2U, false, getgid(), "", 0700, date + 3U, 2U,
|
||||
3U, 0U, source_path, getuid(), date + 4U);
|
||||
@@ -121,7 +120,7 @@ const auto create_file = [](repertory::i_provider &provider,
|
||||
EXPECT_EQ(repertory::api_error::success, provider.is_file(api_path, exists));
|
||||
EXPECT_TRUE(exists);
|
||||
|
||||
EXPECT_TRUE(repertory::utils::file::delete_file(source_path));
|
||||
EXPECT_TRUE(repertory::utils::file::file{source_path}.remove());
|
||||
|
||||
repertory::api_meta_map meta2{};
|
||||
EXPECT_EQ(repertory::api_error::success,
|
||||
@@ -167,9 +166,8 @@ const auto decrypt_parts = [](const repertory::app_config &cfg,
|
||||
continue;
|
||||
}
|
||||
|
||||
EXPECT_EQ(repertory::api_error::success,
|
||||
repertory::utils::encryption::decrypt_file_name(
|
||||
cfg.get_encrypt_config().encryption_token, part));
|
||||
EXPECT_EQ(true, repertory::utils::encryption::decrypt_file_name(
|
||||
cfg.get_encrypt_config().encryption_token, part));
|
||||
}
|
||||
path = repertory::utils::string::join(parts, '/');
|
||||
}
|
||||
@@ -398,7 +396,7 @@ static void get_directory_item_count(const app_config &cfg,
|
||||
EXPECT_EQ(std::size_t(0U), provider.get_directory_item_count("/not_found"));
|
||||
|
||||
const auto source_path =
|
||||
utils::path::combine("./test_data/encrypt", {"sub10"});
|
||||
utils::path::combine(test::get_test_input_dir(), {"encrypt", "sub10"});
|
||||
|
||||
std::string api_path{};
|
||||
EXPECT_EQ(api_error::success,
|
||||
@@ -630,8 +628,8 @@ static void run_tests(const app_config &cfg, i_provider &provider) {
|
||||
|
||||
TEST(providers, encrypt_provider) {
|
||||
const auto config_path =
|
||||
utils::path::combine("./test_config", {"encrypt_provider"});
|
||||
ASSERT_TRUE(utils::file::delete_directory_recursively(config_path));
|
||||
utils::path::combine(test::get_test_output_dir(), {"encrypt_provider"});
|
||||
ASSERT_TRUE(utils::file::directory(config_path).remove_recursively());
|
||||
|
||||
console_consumer consumer{};
|
||||
event_system::instance().start();
|
||||
@@ -639,7 +637,7 @@ TEST(providers, encrypt_provider) {
|
||||
app_config cfg(provider_type::encrypt, config_path);
|
||||
|
||||
const auto encrypt_path =
|
||||
utils::path::combine("./test_data/encrypt", {"encrypt"});
|
||||
utils::path::combine(test::get_test_input_dir(), {"encrypt"});
|
||||
|
||||
EXPECT_STREQ(
|
||||
encrypt_path.c_str(),
|
||||
@@ -673,16 +671,17 @@ TEST(providers, encrypt_provider) {
|
||||
|
||||
TEST(providers, s3_provider) {
|
||||
const auto config_path =
|
||||
utils::path::combine("./test_config", {"s3_provider"});
|
||||
ASSERT_TRUE(utils::file::delete_directory_recursively(config_path));
|
||||
utils::path::combine(test::get_test_output_dir(), {"s3_provider"});
|
||||
ASSERT_TRUE(utils::file::directory(config_path).remove_recursively());
|
||||
|
||||
console_consumer consumer{};
|
||||
event_system::instance().start();
|
||||
{
|
||||
app_config cfg(provider_type::s3, config_path);
|
||||
{
|
||||
app_config src_cfg(provider_type::s3,
|
||||
utils::path::combine(get_test_dir(), {"storj"}));
|
||||
app_config src_cfg(
|
||||
provider_type::s3,
|
||||
utils::path::combine(test::get_test_input_dir(), {"storj"}));
|
||||
cfg.set_s3_config(src_cfg.get_s3_config());
|
||||
}
|
||||
|
||||
@@ -711,16 +710,17 @@ TEST(providers, s3_provider) {
|
||||
|
||||
TEST(providers, sia_provider) {
|
||||
const auto config_path =
|
||||
utils::path::combine("./test_config", {"sia_provider"});
|
||||
ASSERT_TRUE(utils::file::delete_directory_recursively(config_path));
|
||||
utils::path::combine(test::get_test_output_dir(), {"sia_provider"});
|
||||
ASSERT_TRUE(utils::file::directory(config_path).remove_recursively());
|
||||
|
||||
console_consumer consumer{};
|
||||
event_system::instance().start();
|
||||
{
|
||||
app_config cfg(provider_type::sia, config_path);
|
||||
{
|
||||
app_config src_cfg(provider_type::sia,
|
||||
utils::path::combine(get_test_dir(), {"sia"}));
|
||||
app_config src_cfg(
|
||||
provider_type::sia,
|
||||
utils::path::combine(test::get_test_input_dir(), {"sia"}));
|
||||
cfg.set_host_config(src_cfg.get_host_config());
|
||||
}
|
||||
|
||||
|
||||
@@ -47,12 +47,12 @@ using namespace repertory::remote_fuse;
|
||||
namespace fuse_test {
|
||||
static std::string mount_location_;
|
||||
static std::string fuse_remote_dir =
|
||||
utils::path::combine("./test_config", {"fuse_remote_test"});
|
||||
utils::path::combine(test::get_test_output_dir(), {"fuse_remote_test"});
|
||||
|
||||
static void access_test(repertory::remote_fuse::remote_client &client) {
|
||||
const auto test_file = utils::path::combine(fuse_remote_dir, {"access.txt"});
|
||||
const auto api_path = test_file.substr(mount_location_.size());
|
||||
EXPECT_TRUE(utils::file::retry_delete_file(test_file));
|
||||
EXPECT_TRUE(utils::file::file(test_file).remove());
|
||||
|
||||
remote::file_handle handle;
|
||||
const auto ret = client.fuse_create(
|
||||
@@ -64,13 +64,13 @@ static void access_test(repertory::remote_fuse::remote_client &client) {
|
||||
EXPECT_EQ(0, client.fuse_access(api_path.c_str(), 0));
|
||||
}
|
||||
|
||||
EXPECT_TRUE(utils::file::retry_delete_file(test_file));
|
||||
EXPECT_TRUE(utils::file::file(test_file).remove());
|
||||
}
|
||||
|
||||
static void chflags_test(repertory::remote_fuse::remote_client &client) {
|
||||
const auto test_file = utils::path::combine(fuse_remote_dir, {"chflags.txt"});
|
||||
const auto api_path = test_file.substr(mount_location_.size());
|
||||
EXPECT_TRUE(utils::file::retry_delete_file(test_file));
|
||||
EXPECT_TRUE(utils::file::file(test_file).remove());
|
||||
|
||||
remote::file_handle handle;
|
||||
const auto ret = client.fuse_create(
|
||||
@@ -86,13 +86,13 @@ static void chflags_test(repertory::remote_fuse::remote_client &client) {
|
||||
#endif
|
||||
}
|
||||
|
||||
EXPECT_TRUE(utils::file::retry_delete_file(test_file));
|
||||
EXPECT_TRUE(utils::file::file(test_file).remove());
|
||||
}
|
||||
|
||||
static void chmod_test(repertory::remote_fuse::remote_client &client) {
|
||||
const auto test_file = utils::path::combine(fuse_remote_dir, {"chmod.txt"});
|
||||
const auto api_path = test_file.substr(mount_location_.size());
|
||||
EXPECT_TRUE(utils::file::retry_delete_file(test_file));
|
||||
EXPECT_TRUE(utils::file::file(test_file).remove());
|
||||
|
||||
remote::file_handle handle;
|
||||
const auto ret = client.fuse_create(
|
||||
@@ -108,13 +108,13 @@ static void chmod_test(repertory::remote_fuse::remote_client &client) {
|
||||
#endif
|
||||
}
|
||||
|
||||
EXPECT_TRUE(utils::file::retry_delete_file(test_file));
|
||||
EXPECT_TRUE(utils::file::file(test_file).remove());
|
||||
}
|
||||
|
||||
static void chown_test(repertory::remote_fuse::remote_client &client) {
|
||||
const auto test_file = utils::path::combine(fuse_remote_dir, {"chown.txt"});
|
||||
const auto api_path = test_file.substr(mount_location_.size());
|
||||
EXPECT_TRUE(utils::file::retry_delete_file(test_file));
|
||||
EXPECT_TRUE(utils::file::file(test_file).remove());
|
||||
|
||||
remote::file_handle handle;
|
||||
const auto ret = client.fuse_create(
|
||||
@@ -134,7 +134,7 @@ static void chown_test(repertory::remote_fuse::remote_client &client) {
|
||||
#endif
|
||||
}
|
||||
|
||||
EXPECT_TRUE(utils::file::retry_delete_file(test_file));
|
||||
EXPECT_TRUE(utils::file::file(test_file).remove());
|
||||
}
|
||||
|
||||
static void
|
||||
@@ -143,7 +143,7 @@ create_and_release_test(repertory::remote_fuse::remote_client &client,
|
||||
const auto test_file =
|
||||
utils::path::combine(fuse_remote_dir, {"create_and_release.txt"});
|
||||
const auto api_path = test_file.substr(mount_location_.size());
|
||||
EXPECT_TRUE(utils::file::retry_delete_file(test_file));
|
||||
EXPECT_TRUE(utils::file::file(test_file).remove());
|
||||
|
||||
remote::file_handle handle;
|
||||
const auto ret = client.fuse_create(
|
||||
@@ -156,7 +156,7 @@ create_and_release_test(repertory::remote_fuse::remote_client &client,
|
||||
EXPECT_EQ(0u, server.get_open_file_count(test_file));
|
||||
}
|
||||
|
||||
EXPECT_TRUE(utils::file::retry_delete_file(test_file));
|
||||
EXPECT_TRUE(utils::file::file(test_file).remove());
|
||||
}
|
||||
|
||||
static void destroy_test(repertory::remote_fuse::remote_client &client) {
|
||||
@@ -167,7 +167,7 @@ static void destroy_test(repertory::remote_fuse::remote_client &client) {
|
||||
const auto test_file = utils::path::combine(fuse_remote_dir,
|
||||
{"fallocate.txt"}); const auto api_path =
|
||||
test_file.substr(mount_location_.size());
|
||||
utils::file::retry_delete_file(test_file);
|
||||
utils::file::file(test_file).remove();
|
||||
|
||||
remote::file_handle handle;
|
||||
const auto ret = client.fuse_create(
|
||||
@@ -181,14 +181,14 @@ remote::open_flags::ReadWrite, handle); EXPECT_EQ(0, ret); if (ret == 0) {
|
||||
EXPECT_EQ(100, file_size);
|
||||
}
|
||||
|
||||
utils::file::retry_delete_file(test_file);
|
||||
utils::file::file(test_file).remove();
|
||||
}*/
|
||||
|
||||
static void fgetattr_test(repertory::remote_fuse::remote_client &client) {
|
||||
const auto test_file =
|
||||
utils::path::combine(fuse_remote_dir, {"fgetattr.txt"});
|
||||
const auto api_path = test_file.substr(mount_location_.size());
|
||||
EXPECT_TRUE(utils::file::retry_delete_file(test_file));
|
||||
EXPECT_TRUE(utils::file::file(test_file).remove());
|
||||
|
||||
remote::file_handle handle;
|
||||
const auto ret = client.fuse_create(
|
||||
@@ -219,23 +219,23 @@ static void fgetattr_test(repertory::remote_fuse::remote_client &client) {
|
||||
EXPECT_EQ(st1.st_nlink, st.st_nlink);
|
||||
EXPECT_EQ(st1.st_mode, st.st_mode);
|
||||
EXPECT_LE(static_cast<remote::file_time>(st1.st_atime),
|
||||
st.st_atimespec / NANOS_PER_SECOND);
|
||||
st.st_atimespec / utils::time::NANOS_PER_SECOND);
|
||||
EXPECT_EQ(static_cast<remote::file_time>(st1.st_mtime),
|
||||
st.st_mtimespec / NANOS_PER_SECOND);
|
||||
st.st_mtimespec / utils::time::NANOS_PER_SECOND);
|
||||
EXPECT_EQ(static_cast<remote::file_time>(st1.st_ctime),
|
||||
st.st_ctimespec / NANOS_PER_SECOND);
|
||||
st.st_ctimespec / utils::time::NANOS_PER_SECOND);
|
||||
EXPECT_EQ(static_cast<remote::file_time>(st1.st_ctime),
|
||||
st.st_birthtimespec / NANOS_PER_SECOND);
|
||||
st.st_birthtimespec / utils::time::NANOS_PER_SECOND);
|
||||
}
|
||||
|
||||
EXPECT_TRUE(utils::file::retry_delete_file(test_file));
|
||||
EXPECT_TRUE(utils::file::file(test_file).remove());
|
||||
}
|
||||
|
||||
static void fsetattr_x_test(repertory::remote_fuse::remote_client &client) {
|
||||
const auto test_file =
|
||||
utils::path::combine(fuse_remote_dir, {"fsetattr_x.txt"});
|
||||
const auto api_path = test_file.substr(mount_location_.size());
|
||||
EXPECT_TRUE(utils::file::retry_delete_file(test_file));
|
||||
EXPECT_TRUE(utils::file::file(test_file).remove());
|
||||
|
||||
remote::file_handle handle;
|
||||
const auto ret = client.fuse_create(
|
||||
@@ -253,13 +253,13 @@ static void fsetattr_x_test(repertory::remote_fuse::remote_client &client) {
|
||||
EXPECT_EQ(0, client.fuse_release(api_path.c_str(), handle));
|
||||
}
|
||||
|
||||
EXPECT_TRUE(utils::file::retry_delete_file(test_file));
|
||||
EXPECT_TRUE(utils::file::file(test_file).remove());
|
||||
}
|
||||
|
||||
static void fsync_test(repertory::remote_fuse::remote_client &client) {
|
||||
const auto test_file = utils::path::combine(fuse_remote_dir, {"fsync.txt"});
|
||||
const auto api_path = test_file.substr(mount_location_.size());
|
||||
EXPECT_TRUE(utils::file::retry_delete_file(test_file));
|
||||
EXPECT_TRUE(utils::file::file(test_file).remove());
|
||||
|
||||
remote::file_handle handle;
|
||||
const auto ret = client.fuse_create(
|
||||
@@ -271,14 +271,14 @@ static void fsync_test(repertory::remote_fuse::remote_client &client) {
|
||||
EXPECT_EQ(0, client.fuse_release(api_path.c_str(), handle));
|
||||
}
|
||||
|
||||
EXPECT_TRUE(utils::file::retry_delete_file(test_file));
|
||||
EXPECT_TRUE(utils::file::file(test_file).remove());
|
||||
}
|
||||
|
||||
static void ftruncate_test(repertory::remote_fuse::remote_client &client) {
|
||||
const auto test_file =
|
||||
utils::path::combine(fuse_remote_dir, {"ftruncate.txt"});
|
||||
const auto api_path = test_file.substr(mount_location_.size());
|
||||
EXPECT_TRUE(utils::file::retry_delete_file(test_file));
|
||||
EXPECT_TRUE(utils::file::file(test_file).remove());
|
||||
|
||||
remote::file_handle handle;
|
||||
const auto ret = client.fuse_create(
|
||||
@@ -289,18 +289,18 @@ static void ftruncate_test(repertory::remote_fuse::remote_client &client) {
|
||||
EXPECT_EQ(0, client.fuse_ftruncate(api_path.c_str(), 100, handle));
|
||||
EXPECT_EQ(0, client.fuse_release(api_path.c_str(), handle));
|
||||
|
||||
std::uint64_t file_size;
|
||||
EXPECT_TRUE(utils::file::get_file_size(test_file, file_size));
|
||||
EXPECT_EQ(100u, file_size);
|
||||
auto opt_size = utils::file::file{test_file}.size();
|
||||
EXPECT_TRUE(opt_size.has_value());
|
||||
EXPECT_EQ(100U, opt_size.value());
|
||||
}
|
||||
|
||||
EXPECT_TRUE(utils::file::retry_delete_file(test_file));
|
||||
EXPECT_TRUE(utils::file::file(test_file).remove());
|
||||
}
|
||||
|
||||
static void getattr_test(repertory::remote_fuse::remote_client &client) {
|
||||
const auto test_file = utils::path::combine(fuse_remote_dir, {"getattr.txt"});
|
||||
const auto api_path = test_file.substr(mount_location_.size());
|
||||
EXPECT_TRUE(utils::file::retry_delete_file(test_file));
|
||||
EXPECT_TRUE(utils::file::file(test_file).remove());
|
||||
|
||||
remote::file_handle handle;
|
||||
const auto ret = client.fuse_create(
|
||||
@@ -330,23 +330,23 @@ static void getattr_test(repertory::remote_fuse::remote_client &client) {
|
||||
EXPECT_EQ(st1.st_nlink, st.st_nlink);
|
||||
EXPECT_EQ(st1.st_mode, st.st_mode);
|
||||
EXPECT_LE(static_cast<remote::file_time>(st1.st_atime),
|
||||
st.st_atimespec / NANOS_PER_SECOND);
|
||||
st.st_atimespec / utils::time::NANOS_PER_SECOND);
|
||||
EXPECT_EQ(static_cast<remote::file_time>(st1.st_mtime),
|
||||
st.st_mtimespec / NANOS_PER_SECOND);
|
||||
st.st_mtimespec / utils::time::NANOS_PER_SECOND);
|
||||
EXPECT_EQ(static_cast<remote::file_time>(st1.st_ctime),
|
||||
st.st_ctimespec / NANOS_PER_SECOND);
|
||||
st.st_ctimespec / utils::time::NANOS_PER_SECOND);
|
||||
EXPECT_EQ(static_cast<remote::file_time>(st1.st_ctime),
|
||||
st.st_birthtimespec / NANOS_PER_SECOND);
|
||||
st.st_birthtimespec / utils::time::NANOS_PER_SECOND);
|
||||
}
|
||||
|
||||
EXPECT_TRUE(utils::file::retry_delete_file(test_file));
|
||||
EXPECT_TRUE(utils::file::file(test_file).remove());
|
||||
}
|
||||
|
||||
/*static void getxattr_test(repertory::remote_fuse::remote_client &client) {
|
||||
const auto test_file = utils::path::combine(fuse_remote_dir,
|
||||
{"getxattr.txt"}); const auto api_path =
|
||||
test_file.substr(mount_location_.size());
|
||||
utils::file::retry_delete_file(test_file);
|
||||
utils::file::file(test_file).remove();
|
||||
|
||||
remote::file_handle handle;
|
||||
const auto ret = client.fuse_create(
|
||||
@@ -359,14 +359,14 @@ nullptr, 0)); #else EXPECT_EQ(-EACCES, client.fuse_getxattr(api_path.c_str(),
|
||||
"test", nullptr, 0)); #endif
|
||||
}
|
||||
|
||||
utils::file::retry_delete_file(test_file);
|
||||
utils::file::file(test_file).remove();
|
||||
}
|
||||
|
||||
static void getxattr_osx_test(repertory::remote_fuse::remote_client &client) {
|
||||
const auto test_file = utils::path::combine(fuse_remote_dir,
|
||||
{"getxattr_osx.txt"}); const auto api_path =
|
||||
test_file.substr(mount_location_.size());
|
||||
utils::file::retry_delete_file(test_file);
|
||||
utils::file::file(test_file).remove();
|
||||
|
||||
remote::file_handle handle;
|
||||
const auto ret = client.fuse_create(
|
||||
@@ -377,14 +377,14 @@ remote::open_flags::ReadWrite, handle); EXPECT_EQ(0, ret); if (ret == 0) {
|
||||
client.fuse_getxattrOSX(api_path.c_str(), "test", nullptr, 0, 0));
|
||||
}
|
||||
|
||||
utils::file::retry_delete_file(test_file);
|
||||
utils::file::file(test_file).remove();
|
||||
}*/
|
||||
|
||||
static void getxtimes_test(repertory::remote_fuse::remote_client &client) {
|
||||
const auto test_file =
|
||||
utils::path::combine(fuse_remote_dir, {"getxtimes.txt"});
|
||||
const auto api_path = test_file.substr(mount_location_.size());
|
||||
EXPECT_TRUE(utils::file::retry_delete_file(test_file));
|
||||
EXPECT_TRUE(utils::file::file(test_file).remove());
|
||||
|
||||
remote::file_handle handle;
|
||||
const auto ret = client.fuse_create(
|
||||
@@ -403,7 +403,7 @@ static void getxtimes_test(repertory::remote_fuse::remote_client &client) {
|
||||
EXPECT_EQ(0, client.fuse_release(api_path.c_str(), handle));
|
||||
}
|
||||
|
||||
EXPECT_TRUE(utils::file::retry_delete_file(test_file));
|
||||
EXPECT_TRUE(utils::file::file(test_file).remove());
|
||||
}
|
||||
|
||||
static void init_test(repertory::remote_fuse::remote_client &client) {
|
||||
@@ -414,7 +414,7 @@ static void init_test(repertory::remote_fuse::remote_client &client) {
|
||||
const auto test_file = utils::path::combine(fuse_remote_dir,
|
||||
{"listxattr.txt"}); const auto api_path =
|
||||
test_file.substr(mount_location_.size());
|
||||
utils::file::retry_delete_file(test_file);
|
||||
utils::file::file(test_file).remove();
|
||||
|
||||
remote::file_handle handle;
|
||||
const auto ret = client.fuse_create(
|
||||
@@ -427,29 +427,29 @@ remote::open_flags::ReadWrite, handle); EXPECT_EQ(0, ret); if (ret == 0) {
|
||||
#endif
|
||||
}
|
||||
|
||||
utils::file::retry_delete_file(test_file);
|
||||
utils::file::file(test_file).remove();
|
||||
}*/
|
||||
|
||||
static void mkdir_test(repertory::remote_fuse::remote_client &client) {
|
||||
const auto test_directory =
|
||||
utils::path::combine(fuse_remote_dir, {"mkdir_test"});
|
||||
const auto api_path = test_directory.substr(mount_location_.size());
|
||||
EXPECT_TRUE(utils::file::delete_directory(test_directory));
|
||||
EXPECT_TRUE(utils::file::directory(test_directory).remove());
|
||||
|
||||
#if defined(_WIN32)
|
||||
EXPECT_EQ(0, client.fuse_mkdir(api_path.c_str(), 0));
|
||||
#else
|
||||
EXPECT_EQ(0, client.fuse_mkdir(api_path.c_str(), S_IRWXU));
|
||||
#endif
|
||||
EXPECT_TRUE(utils::file::is_directory(test_directory));
|
||||
EXPECT_TRUE(utils::file::directory(test_directory).exists());
|
||||
|
||||
EXPECT_TRUE(utils::file::delete_directory(test_directory));
|
||||
EXPECT_TRUE(utils::file::directory(test_directory).remove());
|
||||
}
|
||||
|
||||
static void open_test(repertory::remote_fuse::remote_client &client) {
|
||||
const auto test_file = utils::path::combine(fuse_remote_dir, {"open.txt"});
|
||||
const auto api_path = test_file.substr(mount_location_.size());
|
||||
EXPECT_TRUE(utils::file::retry_delete_file(test_file));
|
||||
EXPECT_TRUE(utils::file::file(test_file).remove());
|
||||
|
||||
remote::file_handle handle;
|
||||
#if defined(_WIN32)
|
||||
@@ -471,7 +471,7 @@ static void open_test(repertory::remote_fuse::remote_client &client) {
|
||||
EXPECT_EQ(0, client.fuse_release(api_path.c_str(), handle2));
|
||||
}
|
||||
|
||||
EXPECT_TRUE(utils::file::retry_delete_file(test_file));
|
||||
EXPECT_TRUE(utils::file::file(test_file).remove());
|
||||
}
|
||||
|
||||
static void
|
||||
@@ -479,27 +479,27 @@ opendir_and_releasedir_test(repertory::remote_fuse::remote_client &client) {
|
||||
const auto test_directory =
|
||||
utils::path::combine(fuse_remote_dir, {"opendir_and_release_dir"});
|
||||
const auto api_path = test_directory.substr(mount_location_.size());
|
||||
EXPECT_TRUE(utils::file::delete_directory(test_directory));
|
||||
EXPECT_TRUE(utils::file::directory(test_directory).remove());
|
||||
|
||||
#if defined(_WIN32)
|
||||
EXPECT_EQ(0, client.fuse_mkdir(api_path.c_str(), 0));
|
||||
#else
|
||||
EXPECT_EQ(0, client.fuse_mkdir(api_path.c_str(), S_IRWXU));
|
||||
#endif
|
||||
EXPECT_TRUE(utils::file::is_directory(test_directory));
|
||||
EXPECT_TRUE(utils::file::directory(test_directory).exists());
|
||||
|
||||
remote::file_handle handle = 0;
|
||||
EXPECT_EQ(0, client.fuse_opendir(api_path.c_str(), handle));
|
||||
EXPECT_EQ(0, client.fuse_releasedir(api_path.c_str(), handle));
|
||||
|
||||
EXPECT_TRUE(utils::file::delete_directory(test_directory));
|
||||
EXPECT_TRUE(utils::file::directory(test_directory).remove());
|
||||
}
|
||||
|
||||
static void read_and_write_test(repertory::remote_fuse::remote_client &client) {
|
||||
const auto test_file =
|
||||
utils::path::combine(fuse_remote_dir, {"read_and_write.txt"});
|
||||
const auto api_path = test_file.substr(mount_location_.size());
|
||||
EXPECT_TRUE(utils::file::retry_delete_file(test_file));
|
||||
EXPECT_TRUE(utils::file::file(test_file).remove());
|
||||
|
||||
remote::file_handle handle;
|
||||
const auto ret = client.fuse_create(
|
||||
@@ -517,7 +517,7 @@ static void read_and_write_test(repertory::remote_fuse::remote_client &client) {
|
||||
EXPECT_EQ(0, client.fuse_release(api_path.c_str(), handle));
|
||||
}
|
||||
|
||||
EXPECT_TRUE(utils::file::retry_delete_file(test_file));
|
||||
EXPECT_TRUE(utils::file::file(test_file).remove());
|
||||
}
|
||||
|
||||
static void
|
||||
@@ -525,7 +525,7 @@ read_and_write_base64_test(repertory::remote_fuse::remote_client &client) {
|
||||
const auto test_file =
|
||||
utils::path::combine(fuse_remote_dir, {"read_and_write_base64.txt"});
|
||||
const auto api_path = test_file.substr(mount_location_.size());
|
||||
EXPECT_TRUE(utils::file::retry_delete_file(test_file));
|
||||
EXPECT_TRUE(utils::file::file(test_file).remove());
|
||||
|
||||
remote::file_handle handle;
|
||||
const auto ret = client.fuse_create(
|
||||
@@ -534,7 +534,7 @@ read_and_write_base64_test(repertory::remote_fuse::remote_client &client) {
|
||||
EXPECT_EQ(0, ret);
|
||||
if (ret == 0) {
|
||||
const auto data = macaron::Base64::Encode("1234567890");
|
||||
EXPECT_EQ(10, client.fuse_write_base64(api_path.c_str(), &data[0],
|
||||
EXPECT_EQ(10, client.fuse_write_base64(api_path.c_str(), data.data(),
|
||||
data.size(), 0, handle));
|
||||
data_buffer buffer(10);
|
||||
EXPECT_EQ(10, client.fuse_read(api_path.c_str(),
|
||||
@@ -544,21 +544,21 @@ read_and_write_base64_test(repertory::remote_fuse::remote_client &client) {
|
||||
EXPECT_EQ(0, client.fuse_release(api_path.c_str(), handle));
|
||||
}
|
||||
|
||||
EXPECT_TRUE(utils::file::retry_delete_file(test_file));
|
||||
EXPECT_TRUE(utils::file::file(test_file).remove());
|
||||
}
|
||||
|
||||
static void readdir_test(repertory::remote_fuse::remote_client &client) {
|
||||
const auto test_directory =
|
||||
utils::path::combine(fuse_remote_dir, {"readdir_test"});
|
||||
const auto api_path = test_directory.substr(mount_location_.size());
|
||||
EXPECT_TRUE(utils::file::delete_directory(test_directory));
|
||||
EXPECT_TRUE(utils::file::directory(test_directory).remove());
|
||||
|
||||
#if defined(_WIN32)
|
||||
EXPECT_EQ(0, client.fuse_mkdir(api_path.c_str(), 0));
|
||||
#else
|
||||
EXPECT_EQ(0, client.fuse_mkdir(api_path.c_str(), S_IRWXU));
|
||||
#endif
|
||||
EXPECT_TRUE(utils::file::is_directory(test_directory));
|
||||
EXPECT_TRUE(utils::file::directory(test_directory).exists());
|
||||
|
||||
remote::file_handle handle = 0;
|
||||
EXPECT_EQ(0, client.fuse_opendir(api_path.c_str(), handle));
|
||||
@@ -572,14 +572,14 @@ static void readdir_test(repertory::remote_fuse::remote_client &client) {
|
||||
|
||||
EXPECT_EQ(0, client.fuse_releasedir(api_path.c_str(), handle));
|
||||
|
||||
EXPECT_TRUE(utils::file::delete_directory(test_directory));
|
||||
EXPECT_TRUE(utils::file::directory(test_directory).remove());
|
||||
}
|
||||
|
||||
/*static void removexattr_test(repertory::remote_fuse::remote_client &client) {
|
||||
const auto test_file = utils::path::combine(fuse_remote_dir,
|
||||
{"removexattr.txt"}); const auto api_path =
|
||||
test_file.substr(mount_location_.size());
|
||||
utils::file::retry_delete_file(test_file);
|
||||
utils::file::file(test_file).remove();
|
||||
|
||||
remote::file_handle handle;
|
||||
const auto ret = client.fuse_create(
|
||||
@@ -592,7 +592,7 @@ remote::open_flags::ReadWrite, handle); EXPECT_EQ(0, ret); if (ret == 0) {
|
||||
"test")); #endif
|
||||
}
|
||||
|
||||
utils::file::retry_delete_file(test_file);
|
||||
utils::file::file(test_file).remove();
|
||||
}*/
|
||||
|
||||
static void rename_test(repertory::remote_fuse::remote_client &client) {
|
||||
@@ -602,8 +602,8 @@ static void rename_test(repertory::remote_fuse::remote_client &client) {
|
||||
const auto api_path = test_file.substr(mount_location_.size());
|
||||
const auto renamed_api_path =
|
||||
renamed_test_file.substr(mount_location_.size());
|
||||
EXPECT_TRUE(utils::file::retry_delete_file(test_file));
|
||||
EXPECT_TRUE(utils::file::retry_delete_file(renamed_test_file));
|
||||
EXPECT_TRUE(utils::file::file(test_file).remove());
|
||||
EXPECT_TRUE(utils::file::file(renamed_test_file).remove());
|
||||
|
||||
remote::file_handle handle;
|
||||
#if defined(_WIN32)
|
||||
@@ -621,38 +621,38 @@ static void rename_test(repertory::remote_fuse::remote_client &client) {
|
||||
EXPECT_EQ(0, client.fuse_release(api_path.c_str(), handle));
|
||||
EXPECT_EQ(0,
|
||||
client.fuse_rename(api_path.c_str(), renamed_api_path.c_str()));
|
||||
EXPECT_FALSE(utils::file::is_file(test_file));
|
||||
EXPECT_TRUE(utils::file::is_file(renamed_test_file));
|
||||
EXPECT_FALSE(utils::file::file(test_file).exists());
|
||||
EXPECT_TRUE(utils::file::file(renamed_test_file).exists());
|
||||
}
|
||||
|
||||
EXPECT_TRUE(utils::file::retry_delete_file(test_file));
|
||||
EXPECT_TRUE(utils::file::retry_delete_file(renamed_test_file));
|
||||
EXPECT_TRUE(utils::file::file(test_file).remove());
|
||||
EXPECT_TRUE(utils::file::file(renamed_test_file).remove());
|
||||
}
|
||||
|
||||
static void rmdir_test(repertory::remote_fuse::remote_client &client) {
|
||||
const auto test_directory =
|
||||
utils::path::combine(fuse_remote_dir, {"rmdir_test"});
|
||||
const auto api_path = test_directory.substr(mount_location_.size());
|
||||
EXPECT_TRUE(utils::file::delete_directory(test_directory));
|
||||
EXPECT_TRUE(utils::file::directory(test_directory).remove());
|
||||
|
||||
#if defined(_WIN32)
|
||||
EXPECT_EQ(0, client.fuse_mkdir(api_path.c_str(), 0));
|
||||
#else
|
||||
EXPECT_EQ(0, client.fuse_mkdir(api_path.c_str(), S_IRWXU));
|
||||
#endif
|
||||
EXPECT_TRUE(utils::file::is_directory(test_directory));
|
||||
EXPECT_TRUE(utils::file::directory(test_directory).exists());
|
||||
|
||||
EXPECT_EQ(0, client.fuse_rmdir(api_path.c_str()));
|
||||
EXPECT_FALSE(utils::file::is_directory(test_directory));
|
||||
EXPECT_FALSE(utils::file::directory(test_directory).exists());
|
||||
|
||||
EXPECT_TRUE(utils::file::delete_directory(test_directory));
|
||||
EXPECT_TRUE(utils::file::directory(test_directory).remove());
|
||||
}
|
||||
|
||||
static void setattr_x_test(repertory::remote_fuse::remote_client &client) {
|
||||
const auto test_file =
|
||||
utils::path::combine(fuse_remote_dir, {"setattr_x.txt"});
|
||||
const auto api_path = test_file.substr(mount_location_.size());
|
||||
EXPECT_TRUE(utils::file::retry_delete_file(test_file));
|
||||
EXPECT_TRUE(utils::file::file(test_file).remove());
|
||||
|
||||
remote::file_handle handle;
|
||||
const auto ret = client.fuse_create(
|
||||
@@ -670,14 +670,14 @@ static void setattr_x_test(repertory::remote_fuse::remote_client &client) {
|
||||
#endif
|
||||
}
|
||||
|
||||
EXPECT_TRUE(utils::file::retry_delete_file(test_file));
|
||||
EXPECT_TRUE(utils::file::file(test_file).remove());
|
||||
}
|
||||
|
||||
static void setbkuptime_test(repertory::remote_fuse::remote_client &client) {
|
||||
const auto test_file =
|
||||
utils::path::combine(fuse_remote_dir, {"setbkuptime.txt"});
|
||||
const auto api_path = test_file.substr(mount_location_.size());
|
||||
EXPECT_TRUE(utils::file::retry_delete_file(test_file));
|
||||
EXPECT_TRUE(utils::file::file(test_file).remove());
|
||||
|
||||
remote::file_handle handle;
|
||||
const auto ret = client.fuse_create(
|
||||
@@ -687,7 +687,7 @@ static void setbkuptime_test(repertory::remote_fuse::remote_client &client) {
|
||||
if (ret == 0) {
|
||||
EXPECT_EQ(0, client.fuse_release(api_path.c_str(), handle));
|
||||
|
||||
remote::file_time ts = utils::time::get_file_time_now();
|
||||
remote::file_time ts = utils::time::get_time_now();
|
||||
#if defined(_WIN32)
|
||||
EXPECT_EQ(NOT_IMPLEMENTED, client.fuse_setbkuptime(api_path.c_str(), ts));
|
||||
#else
|
||||
@@ -695,14 +695,14 @@ static void setbkuptime_test(repertory::remote_fuse::remote_client &client) {
|
||||
#endif
|
||||
}
|
||||
|
||||
EXPECT_TRUE(utils::file::retry_delete_file(test_file));
|
||||
EXPECT_TRUE(utils::file::file(test_file).remove());
|
||||
}
|
||||
|
||||
static void setchgtime_test(repertory::remote_fuse::remote_client &client) {
|
||||
const auto test_file =
|
||||
utils::path::combine(fuse_remote_dir, {"setchgtime.txt"});
|
||||
const auto api_path = test_file.substr(mount_location_.size());
|
||||
EXPECT_TRUE(utils::file::retry_delete_file(test_file));
|
||||
EXPECT_TRUE(utils::file::file(test_file).remove());
|
||||
|
||||
remote::file_handle handle;
|
||||
const auto ret = client.fuse_create(
|
||||
@@ -712,7 +712,7 @@ static void setchgtime_test(repertory::remote_fuse::remote_client &client) {
|
||||
if (ret == 0) {
|
||||
EXPECT_EQ(0, client.fuse_release(api_path.c_str(), handle));
|
||||
|
||||
remote::file_time ts = utils::time::get_file_time_now();
|
||||
remote::file_time ts = utils::time::get_time_now();
|
||||
#if defined(_WIN32)
|
||||
EXPECT_EQ(NOT_IMPLEMENTED, client.fuse_setchgtime(api_path.c_str(), ts));
|
||||
#else
|
||||
@@ -720,14 +720,14 @@ static void setchgtime_test(repertory::remote_fuse::remote_client &client) {
|
||||
#endif
|
||||
}
|
||||
|
||||
EXPECT_TRUE(utils::file::retry_delete_file(test_file));
|
||||
EXPECT_TRUE(utils::file::file(test_file).remove());
|
||||
}
|
||||
|
||||
static void setcrtime_test(repertory::remote_fuse::remote_client &client) {
|
||||
const auto test_file =
|
||||
utils::path::combine(fuse_remote_dir, {"setcrtime.txt"});
|
||||
const auto api_path = test_file.substr(mount_location_.size());
|
||||
EXPECT_TRUE(utils::file::retry_delete_file(test_file));
|
||||
EXPECT_TRUE(utils::file::file(test_file).remove());
|
||||
|
||||
remote::file_handle handle;
|
||||
const auto ret = client.fuse_create(
|
||||
@@ -737,7 +737,7 @@ static void setcrtime_test(repertory::remote_fuse::remote_client &client) {
|
||||
if (ret == 0) {
|
||||
EXPECT_EQ(0, client.fuse_release(api_path.c_str(), handle));
|
||||
|
||||
remote::file_time ts = utils::time::get_file_time_now();
|
||||
remote::file_time ts = utils::time::get_time_now();
|
||||
#if defined(_WIN32)
|
||||
EXPECT_EQ(NOT_IMPLEMENTED, client.fuse_setcrtime(api_path.c_str(), ts));
|
||||
#else
|
||||
@@ -745,7 +745,7 @@ static void setcrtime_test(repertory::remote_fuse::remote_client &client) {
|
||||
#endif
|
||||
}
|
||||
|
||||
EXPECT_TRUE(utils::file::retry_delete_file(test_file));
|
||||
EXPECT_TRUE(utils::file::file(test_file).remove());
|
||||
}
|
||||
|
||||
static void setvolname_test(repertory::remote_fuse::remote_client &client) {
|
||||
@@ -756,7 +756,7 @@ static void setvolname_test(repertory::remote_fuse::remote_client &client) {
|
||||
const auto test_file = utils::path::combine(fuse_remote_dir,
|
||||
{"setxattr.txt"}); const auto api_path =
|
||||
test_file.substr(mount_location_.size());
|
||||
utils::file::retry_delete_file(test_file);
|
||||
utils::file::file(test_file).remove();
|
||||
|
||||
remote::file_handle handle;
|
||||
const auto ret = client.fuse_create(
|
||||
@@ -771,14 +771,14 @@ remote::open_flags::ReadWrite, handle); EXPECT_EQ(0, ret); if (ret == 0) {
|
||||
5, 0)); #endif
|
||||
}
|
||||
|
||||
utils::file::retry_delete_file(test_file);
|
||||
utils::file::file(test_file).remove();
|
||||
}
|
||||
|
||||
static void setxattr_osx_test(repertory::remote_fuse::remote_client &client) {
|
||||
const auto test_file = utils::path::combine(fuse_remote_dir,
|
||||
{"setxattr_osx.txt"}); const auto api_path =
|
||||
test_file.substr(mount_location_.size());
|
||||
utils::file::retry_delete_file(test_file);
|
||||
utils::file::file(test_file).remove();
|
||||
|
||||
remote::file_handle handle;
|
||||
const auto ret = client.fuse_create(
|
||||
@@ -791,7 +791,7 @@ remote::open_flags::ReadWrite, handle); EXPECT_EQ(0, ret); if (ret == 0) {
|
||||
0));
|
||||
}
|
||||
|
||||
utils::file::retry_delete_file(test_file);
|
||||
utils::file::file(test_file).remove();
|
||||
}*/
|
||||
|
||||
#if defined(_WIN32)
|
||||
@@ -832,7 +832,7 @@ static void statfs_x_test(repertory::remote_fuse::remote_client &client,
|
||||
|
||||
remote::statfs_x st{};
|
||||
EXPECT_EQ(0, client.fuse_statfs_x(api_path.c_str(), 4096, st));
|
||||
EXPECT_STREQ(&st.f_mntfromname[0],
|
||||
EXPECT_STREQ(st.f_mntfromname.data(),
|
||||
utils::create_volume_label(provider_type::remote).c_str());
|
||||
|
||||
const auto total_bytes = drive.get_total_drive_space();
|
||||
@@ -853,7 +853,7 @@ static void truncate_test(repertory::remote_fuse::remote_client &client) {
|
||||
const auto test_file =
|
||||
utils::path::combine(fuse_remote_dir, {"truncate.txt"});
|
||||
const auto api_path = test_file.substr(mount_location_.size());
|
||||
EXPECT_TRUE(utils::file::retry_delete_file(test_file));
|
||||
EXPECT_TRUE(utils::file::file(test_file).remove());
|
||||
|
||||
remote::file_handle handle;
|
||||
#if defined(_WIN32)
|
||||
@@ -871,18 +871,18 @@ static void truncate_test(repertory::remote_fuse::remote_client &client) {
|
||||
|
||||
EXPECT_EQ(0, client.fuse_truncate(api_path.c_str(), 100));
|
||||
|
||||
std::uint64_t file_size;
|
||||
EXPECT_TRUE(utils::file::get_file_size(test_file, file_size));
|
||||
EXPECT_EQ(100u, file_size);
|
||||
auto opt_size = utils::file::file{test_file}.size();
|
||||
EXPECT_TRUE(opt_size.has_value());
|
||||
EXPECT_EQ(100U, opt_size.value());
|
||||
}
|
||||
|
||||
EXPECT_TRUE(utils::file::retry_delete_file(test_file));
|
||||
EXPECT_TRUE(utils::file::file(test_file).remove());
|
||||
}
|
||||
|
||||
static void unlink_test(repertory::remote_fuse::remote_client &client) {
|
||||
const auto test_file = utils::path::combine(fuse_remote_dir, {"unlink.txt"});
|
||||
const auto api_path = test_file.substr(mount_location_.size());
|
||||
EXPECT_TRUE(utils::file::retry_delete_file(test_file));
|
||||
EXPECT_TRUE(utils::file::file(test_file).remove());
|
||||
|
||||
remote::file_handle handle;
|
||||
const auto ret = client.fuse_create(
|
||||
@@ -892,16 +892,16 @@ static void unlink_test(repertory::remote_fuse::remote_client &client) {
|
||||
if (ret == 0) {
|
||||
EXPECT_EQ(0, client.fuse_release(api_path.c_str(), handle));
|
||||
EXPECT_EQ(0, client.fuse_unlink(api_path.c_str()));
|
||||
EXPECT_FALSE(utils::file::is_file(test_file));
|
||||
EXPECT_FALSE(utils::file::file(test_file).exists());
|
||||
}
|
||||
|
||||
EXPECT_TRUE(utils::file::retry_delete_file(test_file));
|
||||
EXPECT_TRUE(utils::file::file(test_file).remove());
|
||||
}
|
||||
|
||||
static void utimens_test(repertory::remote_fuse::remote_client &client) {
|
||||
const auto test_file = utils::path::combine(fuse_remote_dir, {"utimens.txt"});
|
||||
const auto api_path = test_file.substr(mount_location_.size());
|
||||
EXPECT_TRUE(utils::file::retry_delete_file(test_file));
|
||||
EXPECT_TRUE(utils::file::file(test_file).remove());
|
||||
|
||||
remote::file_handle handle;
|
||||
const auto ret = client.fuse_create(
|
||||
@@ -915,7 +915,7 @@ static void utimens_test(repertory::remote_fuse::remote_client &client) {
|
||||
EXPECT_EQ(0, client.fuse_utimens(api_path.c_str(), tv, 0, 0));
|
||||
}
|
||||
|
||||
EXPECT_TRUE(utils::file::retry_delete_file(test_file));
|
||||
EXPECT_TRUE(utils::file::file(test_file).remove());
|
||||
}
|
||||
|
||||
TEST(remote_fuse, all_tests) {
|
||||
@@ -934,11 +934,11 @@ TEST(remote_fuse, all_tests) {
|
||||
|
||||
event_system::instance().start();
|
||||
#if defined(_WIN32)
|
||||
mount_location_ = std::string("./test_config").substr(0, 2);
|
||||
mount_location_ = fuse_remote_dir.substr(0, 2);
|
||||
mock_winfsp_drive drive(mount_location_);
|
||||
remote_server server(config, drive, mount_location_);
|
||||
#else
|
||||
mount_location_ = utils::path::absolute(".");
|
||||
mount_location_ = fuse_remote_dir;
|
||||
mock_fuse_drive drive(mount_location_);
|
||||
remote_server server(config, drive, mount_location_);
|
||||
#endif
|
||||
@@ -990,6 +990,6 @@ TEST(remote_fuse, all_tests) {
|
||||
}
|
||||
|
||||
event_system::instance().stop();
|
||||
EXPECT_TRUE(utils::file::delete_directory_recursively(fuse_remote_dir));
|
||||
EXPECT_TRUE(utils::file::directory(fuse_remote_dir).remove_recursively());
|
||||
}
|
||||
} // namespace fuse_test
|
||||
|
||||
@@ -33,6 +33,7 @@
|
||||
#include "platform/platform.hpp"
|
||||
#include "types/repertory.hpp"
|
||||
#include "utils/common.hpp"
|
||||
#include "utils/time.hpp"
|
||||
|
||||
using namespace repertory;
|
||||
using namespace repertory::remote_winfsp;
|
||||
@@ -40,32 +41,32 @@ using namespace repertory::remote_winfsp;
|
||||
namespace winfsp_test {
|
||||
static std::string mount_location_;
|
||||
static std::string win_remote_dir =
|
||||
utils::path::combine("./test_config", {"win_remote_test"});
|
||||
utils::path::combine(test::get_test_output_dir(), {"win_remote_test"});
|
||||
|
||||
static void can_delete_test(remote_client &client) {
|
||||
const auto test_file =
|
||||
utils::path::combine(win_remote_dir, {"candelete.txt"});
|
||||
EXPECT_TRUE(utils::file::retry_delete_file(test_file));
|
||||
EXPECT_TRUE(utils::file::file(test_file).remove());
|
||||
auto api_path =
|
||||
utils::string::from_utf8(test_file).substr(mount_location_.size());
|
||||
|
||||
native_file::native_file_ptr nf;
|
||||
EXPECT_EQ(api_error::success, native_file::create_or_open(test_file, nf));
|
||||
auto ptr = utils::file::file::open_or_create_file(test_file);
|
||||
auto &nf = *ptr;
|
||||
EXPECT_TRUE(nf);
|
||||
if (nf) {
|
||||
EXPECT_EQ(STATUS_INVALID_HANDLE,
|
||||
client.winfsp_can_delete(
|
||||
reinterpret_cast<PVOID>(nf->get_handle()), &api_path[0]));
|
||||
client.winfsp_can_delete(reinterpret_cast<PVOID>(nf.get_handle()),
|
||||
api_path.data()));
|
||||
|
||||
nf->close();
|
||||
EXPECT_TRUE(utils::file::retry_delete_file(test_file));
|
||||
nf.close();
|
||||
EXPECT_TRUE(utils::file::file(test_file).remove());
|
||||
}
|
||||
}
|
||||
|
||||
template <typename t>
|
||||
static void create_and_close_test(remote_client &client, t &server) {
|
||||
const auto test_file = utils::path::combine(win_remote_dir, {"create.txt"});
|
||||
EXPECT_TRUE(utils::file::retry_delete_file(test_file));
|
||||
EXPECT_TRUE(utils::file::file(test_file).remove());
|
||||
auto api_path =
|
||||
utils::string::from_utf8(test_file).substr(mount_location_.size());
|
||||
|
||||
@@ -83,12 +84,12 @@ static void create_and_close_test(remote_client &client, t &server) {
|
||||
EXPECT_EQ(0u, client.get_open_file_count(utils::string::to_utf8(api_path)));
|
||||
EXPECT_EQ(0u, server.get_open_file_count(test_file));
|
||||
|
||||
EXPECT_TRUE(utils::file::retry_delete_file(test_file));
|
||||
EXPECT_TRUE(utils::file::file(test_file).remove());
|
||||
}
|
||||
|
||||
static void cleanup_test(remote_client &client) {
|
||||
const auto test_file = utils::path::combine(win_remote_dir, {"cleanup.txt"});
|
||||
EXPECT_TRUE(utils::file::retry_delete_file(test_file));
|
||||
EXPECT_TRUE(utils::file::file(test_file).remove());
|
||||
auto api_path =
|
||||
utils::string::from_utf8(test_file).substr(mount_location_.size());
|
||||
|
||||
@@ -107,12 +108,12 @@ static void cleanup_test(remote_client &client) {
|
||||
EXPECT_FALSE(was_closed);
|
||||
EXPECT_EQ(STATUS_SUCCESS, client.winfsp_close(file_desc));
|
||||
|
||||
EXPECT_TRUE(utils::file::retry_delete_file(test_file));
|
||||
EXPECT_TRUE(utils::file::file(test_file).remove());
|
||||
}
|
||||
|
||||
static void flush_test(remote_client &client) {
|
||||
const auto test_file = utils::path::combine(win_remote_dir, {"flush.txt"});
|
||||
EXPECT_TRUE(utils::file::retry_delete_file(test_file));
|
||||
EXPECT_TRUE(utils::file::file(test_file).remove());
|
||||
auto api_path =
|
||||
utils::string::from_utf8(test_file).substr(mount_location_.size());
|
||||
|
||||
@@ -129,13 +130,13 @@ static void flush_test(remote_client &client) {
|
||||
|
||||
EXPECT_EQ(STATUS_SUCCESS, client.winfsp_close(file_desc));
|
||||
|
||||
EXPECT_TRUE(utils::file::retry_delete_file(test_file));
|
||||
EXPECT_TRUE(utils::file::file(test_file).remove());
|
||||
}
|
||||
|
||||
static void get_file_info_test(remote_client &client) {
|
||||
const auto test_file =
|
||||
utils::path::combine(win_remote_dir, {"get_file_info.txt"});
|
||||
EXPECT_TRUE(utils::file::retry_delete_file(test_file));
|
||||
EXPECT_TRUE(utils::file::file(test_file).remove());
|
||||
auto api_path =
|
||||
utils::string::from_utf8(test_file).substr(mount_location_.size());
|
||||
|
||||
@@ -152,13 +153,13 @@ static void get_file_info_test(remote_client &client) {
|
||||
|
||||
EXPECT_EQ(STATUS_SUCCESS, client.winfsp_close(file_desc));
|
||||
|
||||
EXPECT_TRUE(utils::file::retry_delete_file(test_file));
|
||||
EXPECT_TRUE(utils::file::file(test_file).remove());
|
||||
}
|
||||
|
||||
static void get_security_by_name_test(remote_client &client) {
|
||||
const auto test_file =
|
||||
utils::path::combine(win_remote_dir, {"get_security_by_name.txt"});
|
||||
EXPECT_TRUE(utils::file::retry_delete_file(test_file));
|
||||
EXPECT_TRUE(utils::file::file(test_file).remove());
|
||||
auto api_path =
|
||||
utils::string::from_utf8(test_file).substr(mount_location_.size());
|
||||
|
||||
@@ -181,7 +182,7 @@ static void get_security_by_name_test(remote_client &client) {
|
||||
EXPECT_EQ(static_cast<UINT32>(FILE_ATTRIBUTE_NORMAL), attributes);
|
||||
EXPECT_FALSE(str_descriptor.empty());
|
||||
|
||||
EXPECT_TRUE(utils::file::retry_delete_file(test_file));
|
||||
EXPECT_TRUE(utils::file::file(test_file).remove());
|
||||
}
|
||||
|
||||
static void get_volume_info_test(remote_client &client) {
|
||||
@@ -202,7 +203,7 @@ static void mounted_test(remote_client &client) {
|
||||
|
||||
static void open_test(remote_client &client) {
|
||||
const auto test_file = utils::path::combine(win_remote_dir, {"open.txt"});
|
||||
EXPECT_TRUE(utils::file::retry_delete_file(test_file));
|
||||
EXPECT_TRUE(utils::file::file(test_file).remove());
|
||||
auto api_path =
|
||||
utils::string::from_utf8(test_file).substr(mount_location_.size());
|
||||
|
||||
@@ -229,13 +230,13 @@ static void open_test(remote_client &client) {
|
||||
EXPECT_EQ(STATUS_SUCCESS, client.winfsp_close(file_desc));
|
||||
EXPECT_EQ(STATUS_SUCCESS, client.winfsp_close(file_desc2));
|
||||
|
||||
EXPECT_TRUE(utils::file::retry_delete_file(test_file));
|
||||
EXPECT_TRUE(utils::file::file(test_file).remove());
|
||||
}
|
||||
|
||||
static void overwrite_test(remote_client &client) {
|
||||
const auto test_file =
|
||||
utils::path::combine(win_remote_dir, {"overwrite.txt"});
|
||||
EXPECT_TRUE(utils::file::retry_delete_file(test_file));
|
||||
EXPECT_TRUE(utils::file::file(test_file).remove());
|
||||
auto api_path =
|
||||
utils::string::from_utf8(test_file).substr(mount_location_.size());
|
||||
|
||||
@@ -259,13 +260,13 @@ static void overwrite_test(remote_client &client) {
|
||||
|
||||
EXPECT_EQ(STATUS_SUCCESS, client.winfsp_close(file_desc));
|
||||
|
||||
EXPECT_TRUE(utils::file::retry_delete_file(test_file));
|
||||
EXPECT_TRUE(utils::file::file(test_file).remove());
|
||||
}
|
||||
|
||||
static void create_and_read_directory_test(remote_client &client) {
|
||||
const auto test_directory =
|
||||
utils::path::combine(win_remote_dir, {"read_directory"});
|
||||
EXPECT_TRUE(utils::file::delete_directory(test_directory));
|
||||
EXPECT_TRUE(utils::file::directory(test_directory).remove());
|
||||
auto api_path =
|
||||
utils::string::from_utf8(test_directory).substr(mount_location_.size());
|
||||
|
||||
@@ -278,7 +279,7 @@ static void create_and_read_directory_test(remote_client &client) {
|
||||
FILE_ATTRIBUTE_DIRECTORY, 0, &file_desc, &fi, normalized_name, exists);
|
||||
EXPECT_EQ(STATUS_SUCCESS, ret);
|
||||
|
||||
EXPECT_TRUE(utils::file::is_directory(test_directory));
|
||||
EXPECT_TRUE(utils::file::directory(test_directory).exists());
|
||||
|
||||
json list;
|
||||
ret = client.winfsp_read_directory(file_desc, nullptr, nullptr, list);
|
||||
@@ -287,13 +288,13 @@ static void create_and_read_directory_test(remote_client &client) {
|
||||
|
||||
EXPECT_EQ(STATUS_SUCCESS, client.winfsp_close(file_desc));
|
||||
|
||||
EXPECT_TRUE(utils::file::delete_directory(test_directory));
|
||||
EXPECT_TRUE(utils::file::directory(test_directory).remove());
|
||||
}
|
||||
|
||||
static void open_and_read_directory_test(remote_client &client) {
|
||||
const auto test_directory =
|
||||
utils::path::combine(win_remote_dir, {"open_and_read_directory"});
|
||||
EXPECT_TRUE(utils::file::delete_directory(test_directory));
|
||||
EXPECT_TRUE(utils::file::directory(test_directory).remove());
|
||||
auto api_path =
|
||||
utils::string::from_utf8(test_directory).substr(mount_location_.size());
|
||||
|
||||
@@ -308,7 +309,7 @@ static void open_and_read_directory_test(remote_client &client) {
|
||||
|
||||
EXPECT_EQ(STATUS_SUCCESS, client.winfsp_close(file_desc));
|
||||
|
||||
EXPECT_TRUE(utils::file::is_directory(test_directory));
|
||||
EXPECT_TRUE(utils::file::directory(test_directory).exists());
|
||||
|
||||
file_desc = reinterpret_cast<PVOID>(REPERTORY_INVALID_HANDLE);
|
||||
ret = client.winfsp_open(&api_path[0], FILE_DIRECTORY_FILE,
|
||||
@@ -323,13 +324,13 @@ static void open_and_read_directory_test(remote_client &client) {
|
||||
|
||||
EXPECT_EQ(STATUS_SUCCESS, client.winfsp_close(file_desc));
|
||||
|
||||
EXPECT_TRUE(utils::file::delete_directory(test_directory));
|
||||
EXPECT_TRUE(utils::file::directory(test_directory).remove());
|
||||
}
|
||||
|
||||
static void read_and_write_test(remote_client &client) {
|
||||
const auto test_file =
|
||||
utils::path::combine(win_remote_dir, {"read_and_write.txt"});
|
||||
EXPECT_TRUE(utils::file::retry_delete_file(test_file));
|
||||
EXPECT_TRUE(utils::file::file(test_file).remove());
|
||||
auto api_path =
|
||||
utils::string::from_utf8(test_file).substr(mount_location_.size());
|
||||
|
||||
@@ -365,14 +366,14 @@ static void read_and_write_test(remote_client &client) {
|
||||
|
||||
EXPECT_EQ(STATUS_SUCCESS, client.winfsp_close(file_desc));
|
||||
|
||||
EXPECT_TRUE(utils::file::retry_delete_file(test_file));
|
||||
EXPECT_TRUE(utils::file::file(test_file).remove());
|
||||
}
|
||||
|
||||
static void rename_test(remote_client &client) {
|
||||
const auto test_file = utils::path::combine(win_remote_dir, {"rename.txt"});
|
||||
const auto test_file2 = utils::path::combine(win_remote_dir, {"rename2.txt"});
|
||||
EXPECT_TRUE(utils::file::retry_delete_file(test_file));
|
||||
EXPECT_TRUE(utils::file::retry_delete_file(test_file2));
|
||||
EXPECT_TRUE(utils::file::file(test_file).remove());
|
||||
EXPECT_TRUE(utils::file::file(test_file2).remove());
|
||||
auto api_path =
|
||||
utils::string::from_utf8(test_file).substr(mount_location_.size());
|
||||
auto api_path2 =
|
||||
@@ -389,20 +390,20 @@ static void rename_test(remote_client &client) {
|
||||
|
||||
ret = client.winfsp_rename(file_desc, &api_path[0], &api_path2[0], 0);
|
||||
EXPECT_EQ(STATUS_SUCCESS, ret);
|
||||
EXPECT_TRUE(utils::file::is_file(test_file2));
|
||||
EXPECT_FALSE(utils::file::is_file(test_file));
|
||||
EXPECT_TRUE(utils::file::file(test_file2).exists());
|
||||
EXPECT_FALSE(utils::file::file(test_file).exists());
|
||||
|
||||
EXPECT_EQ(STATUS_SUCCESS, client.winfsp_close(file_desc));
|
||||
|
||||
EXPECT_TRUE(utils::file::retry_delete_file(test_file));
|
||||
EXPECT_TRUE(utils::file::retry_delete_file(test_file2));
|
||||
EXPECT_TRUE(utils::file::file(test_file).remove());
|
||||
EXPECT_TRUE(utils::file::file(test_file2).remove());
|
||||
}
|
||||
|
||||
static void set_basic_info_test(remote_client &client) {
|
||||
const auto test_file =
|
||||
utils::path::combine(win_remote_dir, {"set_basic_info.txt"});
|
||||
EXPECT_TRUE(utils::file::retry_delete_file(test_file));
|
||||
EXPECT_TRUE(utils::file::retry_delete_file(test_file));
|
||||
EXPECT_TRUE(utils::file::file(test_file).remove());
|
||||
EXPECT_TRUE(utils::file::file(test_file).remove());
|
||||
auto api_path =
|
||||
utils::string::from_utf8(test_file).substr(mount_location_.size());
|
||||
|
||||
@@ -429,7 +430,7 @@ static void set_basic_info_test(remote_client &client) {
|
||||
const auto change_time = last_write_time;
|
||||
#else
|
||||
const auto creation_time =
|
||||
utils::unix_time_to_windows_time(utils::time::get_time_now());
|
||||
utils::time::unix_time_to_windows_time(utils::time::get_time_now());
|
||||
const auto last_access_time = creation_time + 1;
|
||||
const auto last_write_time = creation_time + 2;
|
||||
const auto change_time = last_write_time;
|
||||
@@ -447,13 +448,13 @@ static void set_basic_info_test(remote_client &client) {
|
||||
|
||||
EXPECT_EQ(STATUS_SUCCESS, client.winfsp_close(file_desc));
|
||||
|
||||
EXPECT_TRUE(utils::file::retry_delete_file(test_file));
|
||||
EXPECT_TRUE(utils::file::file(test_file).remove());
|
||||
}
|
||||
|
||||
static void set_file_size_test(remote_client &client) {
|
||||
const auto test_file =
|
||||
utils::path::combine(win_remote_dir, {"set_file_size.txt"});
|
||||
EXPECT_TRUE(utils::file::retry_delete_file(test_file));
|
||||
EXPECT_TRUE(utils::file::file(test_file).remove());
|
||||
auto api_path =
|
||||
utils::string::from_utf8(test_file).substr(mount_location_.size());
|
||||
|
||||
@@ -472,13 +473,13 @@ static void set_file_size_test(remote_client &client) {
|
||||
client.winfsp_set_file_size(file_desc, new_file_size,
|
||||
set_allocation_size, &fi));
|
||||
|
||||
std::uint64_t file_size = 0u;
|
||||
EXPECT_TRUE(utils::file::get_file_size(test_file, file_size));
|
||||
EXPECT_EQ(34u, file_size);
|
||||
auto opt_size = utils::file::file{test_file}.size();
|
||||
EXPECT_TRUE(opt_size.has_value());
|
||||
EXPECT_EQ(34U, opt_size.value());
|
||||
|
||||
EXPECT_EQ(STATUS_SUCCESS, client.winfsp_close(file_desc));
|
||||
|
||||
EXPECT_TRUE(utils::file::retry_delete_file(test_file));
|
||||
EXPECT_TRUE(utils::file::file(test_file).remove());
|
||||
}
|
||||
|
||||
static void unmounted_test(remote_client &client) {
|
||||
@@ -492,7 +493,6 @@ TEST(remote_winfsp, all_tests) {
|
||||
EXPECT_TRUE(found_port);
|
||||
if (found_port) {
|
||||
console_consumer c;
|
||||
|
||||
app_config config(provider_type::remote, win_remote_dir);
|
||||
config.set_remote_host_name_or_ip("localhost");
|
||||
config.set_remote_port(port);
|
||||
@@ -502,11 +502,11 @@ TEST(remote_winfsp, all_tests) {
|
||||
|
||||
event_system::instance().start();
|
||||
#if defined(_WIN32)
|
||||
mount_location_ = std::string("./test_config").substr(0, 2);
|
||||
mount_location_ = win_remote_dir.substr(0, 2);
|
||||
mock_winfsp_drive drive(mount_location_);
|
||||
remote_server server(config, drive, mount_location_);
|
||||
#else
|
||||
mount_location_ = utils::path::absolute(".");
|
||||
mount_location_ = win_remote_dir;
|
||||
mock_fuse_drive drive(mount_location_);
|
||||
remote_fuse::remote_server server(config, drive, mount_location_);
|
||||
#endif
|
||||
@@ -536,6 +536,6 @@ TEST(remote_winfsp, all_tests) {
|
||||
}
|
||||
|
||||
event_system::instance().stop();
|
||||
EXPECT_TRUE(utils::file::delete_directory_recursively(win_remote_dir));
|
||||
EXPECT_TRUE(utils::file::directory(win_remote_dir).remove_recursively());
|
||||
}
|
||||
} // namespace winfsp_test
|
||||
|
||||
@@ -1,73 +0,0 @@
|
||||
/*
|
||||
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 "test_common.hpp"
|
||||
|
||||
#include "types/repertory.hpp"
|
||||
#include "utils/common.hpp"
|
||||
#include "utils/path.hpp"
|
||||
|
||||
namespace repertory {
|
||||
std::vector<std::string> generated_files;
|
||||
|
||||
void delete_generated_files() {
|
||||
for (const auto &file : generated_files) {
|
||||
EXPECT_TRUE(utils::file::retry_delete_file(file));
|
||||
}
|
||||
}
|
||||
|
||||
auto create_random_file(std::string path, std::size_t size) -> native_file_ptr {
|
||||
native_file_ptr file;
|
||||
if (native_file::create_or_open(path, file) == api_error::success) {
|
||||
generated_files.emplace_back(utils::path::absolute(path));
|
||||
|
||||
EXPECT_TRUE(file->truncate(0U));
|
||||
|
||||
data_buffer buf(size);
|
||||
randombytes_buf(buf.data(), buf.size());
|
||||
|
||||
std::size_t bytes_written{};
|
||||
EXPECT_TRUE(file->write_bytes(buf.data(), buf.size(), 0U, bytes_written));
|
||||
file->flush();
|
||||
|
||||
std::uint64_t current_size{};
|
||||
EXPECT_TRUE(utils::file::get_file_size(path, current_size));
|
||||
EXPECT_EQ(size, current_size);
|
||||
}
|
||||
|
||||
return file;
|
||||
}
|
||||
|
||||
auto generate_test_file_name(const std::string &directory,
|
||||
const std::string &file_name_no_extension)
|
||||
-> std::string {
|
||||
static std::atomic<std::uint32_t> idx{0U};
|
||||
auto path = utils::path::combine(
|
||||
directory, {file_name_no_extension + std::to_string(idx++) + ".dat"});
|
||||
generated_files.emplace_back(path);
|
||||
return path;
|
||||
}
|
||||
|
||||
auto get_test_dir() -> std::string {
|
||||
auto dir = utils::get_environment_variable("PROJECT_TEST_DIR");
|
||||
return utils::path::combine(dir.empty() ? "." : dir, {"test_config"});
|
||||
}
|
||||
} // namespace repertory
|
||||
@@ -21,17 +21,14 @@
|
||||
*/
|
||||
#include "test_common.hpp"
|
||||
|
||||
#include "platform/platform.hpp"
|
||||
#include "utils/common.hpp"
|
||||
#include "utils/file_utils.hpp"
|
||||
#include "utils/string.hpp"
|
||||
#include "utils/utils.hpp"
|
||||
#include "providers/s3/s3_provider.hpp"
|
||||
#include "utils/file.hpp"
|
||||
|
||||
namespace repertory {
|
||||
#if defined(_WIN32)
|
||||
TEST(utils, convert_api_date) {
|
||||
LARGE_INTEGER li{};
|
||||
li.QuadPart = utils::convert_api_date("2009-10-12T17:50:30.111Z");
|
||||
li.QuadPart = s3_provider::convert_api_date("2009-10-12T17:50:30.111Z");
|
||||
|
||||
SYSTEMTIME st{};
|
||||
FileTimeToSystemTime(reinterpret_cast<FILETIME *>(&li), &st);
|
||||
@@ -48,10 +45,13 @@ TEST(utils, convert_api_date) {
|
||||
EXPECT_EQ(20, lt.wSecond);
|
||||
EXPECT_EQ(111, lt.wMilliseconds);
|
||||
}
|
||||
#endif
|
||||
#endif // defined(_WIN32)
|
||||
|
||||
TEST(utils, generate_sha256) {
|
||||
const auto res = utils::file::generate_sha256(__FILE__);
|
||||
std::cout << res << std::endl;
|
||||
auto res = utils::file::file{__FILE__}.sha256();
|
||||
EXPECT_TRUE(res.has_value());
|
||||
if (res.has_value()) {
|
||||
std::cout << res.value() << std::endl;
|
||||
}
|
||||
}
|
||||
} // namespace repertory
|
||||
|
||||
@@ -69,19 +69,19 @@ static void execute_mount(winfsp_test *test,
|
||||
|
||||
static void unmount(winfsp_test *test, const std::string &mount_point) {
|
||||
test->drive->shutdown();
|
||||
auto mounted = utils::file::is_directory(mount_point);
|
||||
auto mounted = utils::file::directory(mount_point).exists();
|
||||
for (auto i = 0; mounted && (i < 50); i++) {
|
||||
std::this_thread::sleep_for(100ms);
|
||||
mounted = utils::file::is_directory(mount_point);
|
||||
mounted = utils::file::directory(mount_point).exists();
|
||||
}
|
||||
EXPECT_FALSE(utils::file::is_directory(mount_point));
|
||||
EXPECT_FALSE(utils::file::directory(mount_point).exists());
|
||||
}
|
||||
|
||||
static void root_creation_test(const std::string &mount_point) {
|
||||
TEST_HEADER(__FUNCTION__);
|
||||
WIN32_FILE_ATTRIBUTE_DATA ad{};
|
||||
EXPECT_TRUE(
|
||||
::GetFileAttributesEx(&mount_point[0], GetFileExInfoStandard, &ad));
|
||||
::GetFileAttributesEx(mount_point.c_str(), GetFileExInfoStandard, &ad));
|
||||
EXPECT_EQ(FILE_ATTRIBUTE_DIRECTORY, ad.dwFileAttributes);
|
||||
EXPECT_EQ(0, ad.nFileSizeHigh);
|
||||
EXPECT_EQ(0, ad.nFileSizeLow);
|
||||
@@ -96,11 +96,11 @@ static auto create_test(winfsp_test *test, const std::string &mount_point) {
|
||||
EXPECT_NE(INVALID_HANDLE_VALUE, handle);
|
||||
EXPECT_TRUE(::CloseHandle(handle));
|
||||
|
||||
EXPECT_TRUE(utils::file::is_file(file));
|
||||
EXPECT_TRUE(utils::file::file(file).exists());
|
||||
|
||||
std::uint64_t file_size;
|
||||
EXPECT_TRUE(utils::file::get_file_size(file, file_size));
|
||||
EXPECT_EQ(0, file_size);
|
||||
auto opt_size = utils::file::file(file).size();
|
||||
EXPECT_TRUE(opt_size.has_value());
|
||||
EXPECT_EQ(0, opt_size.value());
|
||||
|
||||
std::string attr;
|
||||
EXPECT_EQ(api_error::success, test->provider->get_item_meta(
|
||||
@@ -113,8 +113,8 @@ static auto create_test(winfsp_test *test, const std::string &mount_point) {
|
||||
static void delete_file_test(const std::string &file) {
|
||||
TEST_HEADER(__FUNCTION__);
|
||||
event_capture ec({"file_removed"});
|
||||
EXPECT_TRUE(utils::file::retry_delete_file(file));
|
||||
EXPECT_FALSE(utils::file::is_file(file));
|
||||
EXPECT_TRUE(utils::file::file(file).remove());
|
||||
EXPECT_FALSE(utils::file::file(file).exists());
|
||||
}
|
||||
|
||||
static void create_directory_test(const std::string &directory) {
|
||||
@@ -149,11 +149,11 @@ static void write_file_test(const std::string &mount_point) {
|
||||
EXPECT_EQ(10, bytes_written);
|
||||
EXPECT_TRUE(::CloseHandle(handle));
|
||||
|
||||
EXPECT_TRUE(utils::file::is_file(file));
|
||||
EXPECT_TRUE(utils::file::file(file).exists());
|
||||
|
||||
std::uint64_t file_size;
|
||||
EXPECT_TRUE(utils::file::get_file_size(file, file_size));
|
||||
EXPECT_EQ(10, file_size);
|
||||
auto opt_size = utils::file::file(file).size();
|
||||
EXPECT_TRUE(opt_size.has_value());
|
||||
EXPECT_EQ(10U, opt_size.value());
|
||||
}
|
||||
|
||||
static void read_file_test(const std::string &mount_point) {
|
||||
@@ -199,8 +199,8 @@ static void rename_file_test(winfsp_test *test,
|
||||
const auto file2 = utils::path::combine(mount_point, {"rename_file2.txt"});
|
||||
EXPECT_TRUE(::MoveFile(&file[0], &file2[0]));
|
||||
|
||||
EXPECT_TRUE(utils::file::is_file(file2));
|
||||
EXPECT_FALSE(utils::file::is_file(file));
|
||||
EXPECT_TRUE(utils::file::file(file2).exists());
|
||||
EXPECT_FALSE(utils::file::file(file).exists());
|
||||
|
||||
api_meta_map meta2{};
|
||||
EXPECT_EQ(api_error::success,
|
||||
|
||||
Reference in New Issue
Block a user