v2.0.3-rc (#32)
Some checks reported errors
BlockStorage/repertory/pipeline/head Something is wrong with the build of this commit

# Changelog

## v2.0.3-rc

### Issues

* \#28 \[bug\] Address slow directory responses in S3 mounts for deeply nested directories
* \#29 \[bug\] S3 error responses are not being logged
* \#30 \[bug\] Sia provider error responses are not logged
* \#31 \[bug\] S3 provider should limit max key size to 1024

### Changes from v2.0.2-rc

* Always use direct for read-only providers
* Fixed externally removed files not being processed during cleanup
* Fixed http headers not being added for requests
* Fixed incorrect `stat` values for remote mounts
* Fixed invalid directory nullptr error on remote mounts
* Fixed memory leak in event system
* Refactored application shutdown
* Refactored event system
* Updated build system to Alpine 3.21.0
* Updated build system to MinGW-w64 12.0.0
* Updated copyright to 2018-2025

Reviewed-on: #32
This commit is contained in:
2025-02-11 17:26:24 -06:00
parent 8dd46b8ad8
commit fa439c634f
380 changed files with 9644 additions and 4217 deletions

View File

@ -1 +0,0 @@
ae9a5789e23459e59606e6714723f2d3ffc31c03174191ef0d015bdf06007450 binutils-2.41.tar.xz

View File

@ -0,0 +1 @@
b53606f443ac8f01d1d5fc9c39497f2af322d99e14cea5c0b4b124d630379365 binutils-2.43.tar.xz

Binary file not shown.

View File

@ -1 +0,0 @@
fbd032683370d761ba68dba2566d3280a154f5290634172d60a79b24d366d9dc expat-2.6.2.tar.gz

View File

@ -1 +0,0 @@
925e6b4b8cf8856e0ac214f6f34e30dee63b7bb7a50460ab4603950eff48f89e icu-release-75-1.tar.gz

View File

@ -0,0 +1 @@
a2c443404f00098e9e90acf29dc318e049d2dc78d9ae5f46efb261934a730ce2 icu-release-76-1.tar.gz

View File

@ -1 +0,0 @@
3f66bce069ee8bed7439a1a13da7cb91a5e67ea6170f21317ac7f5794625ee10 mingw-w64-v11.0.1.tar.bz2

View File

@ -0,0 +1 @@
cc41898aac4b6e8dd5cffd7331b9d9515b912df4420a3a612b5ea2955bbeed2f mingw-w64-v12.0.0.tar.bz2

View File

@ -1,5 +1,5 @@
/*
Copyright <2018-2024> <scott.e.graves@protonmail.com>
Copyright <2018-2025> <scott.e.graves@protonmail.com>
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal

View File

@ -1,5 +1,5 @@
/*
Copyright <2018-2024> <scott.e.graves@protonmail.com>
Copyright <2018-2025> <scott.e.graves@protonmail.com>
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal

View File

@ -1,5 +1,5 @@
/*
Copyright <2018-2024> <scott.e.graves@protonmail.com>
Copyright <2018-2025> <scott.e.graves@protonmail.com>
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal

View File

@ -1,5 +1,5 @@
/*
Copyright <2018-2024> <scott.e.graves@protonmail.com>
Copyright <2018-2025> <scott.e.graves@protonmail.com>
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal

View File

@ -1,5 +1,5 @@
/*
Copyright <2018-2024> <scott.e.graves@protonmail.com>
Copyright <2018-2025> <scott.e.graves@protonmail.com>
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
@ -416,6 +416,7 @@ using data_buffer = std::vector<unsigned char>;
using mutex_lock = std::lock_guard<std::mutex>;
using recur_mutex_lock = std::lock_guard<std::recursive_mutex>;
using stop_type = std::atomic_bool;
using stop_type_callback = std::function<std::atomic_bool()>;
using unique_mutex_lock = std::unique_lock<std::mutex>;
using unique_recur_mutex_lock = std::unique_lock<std::recursive_mutex>;
@ -462,16 +463,14 @@ struct file_deleter final {
};
using file_t = std::unique_ptr<FILE, file_deleter>;
#if defined(PROJECT_ENABLE_CURL)
struct http_range final {
std::uint64_t begin{};
std::uint64_t end{};
};
using http_headers = std::unordered_map<std::string, std::string>;
using http_headers = std::map<std::string, std::string>;
using http_query_parameters = std::map<std::string, std::string>;
using http_ranges = std::vector<http_range>;
#endif // defined(PROJECT_ENABLE_CURL)
} // namespace repertory
#endif // defined(__cplusplus)

View File

@ -1,5 +1,5 @@
/*
Copyright <2018-2024> <scott.e.graves@protonmail.com>
Copyright <2018-2025> <scott.e.graves@protonmail.com>
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal

View File

@ -1,5 +1,5 @@
/*
Copyright <2018-2024> <scott.e.graves@protonmail.com>
Copyright <2018-2025> <scott.e.graves@protonmail.com>
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal

View File

@ -1,5 +1,5 @@
/*
Copyright <2018-2024> <scott.e.graves@protonmail.com>
Copyright <2018-2025> <scott.e.graves@protonmail.com>
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal

View File

@ -1,5 +1,5 @@
/*
Copyright <2018-2024> <scott.e.graves@protonmail.com>
Copyright <2018-2025> <scott.e.graves@protonmail.com>
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal

View File

@ -1,5 +1,5 @@
/*
Copyright <2018-2024> <scott.e.graves@protonmail.com>
Copyright <2018-2025> <scott.e.graves@protonmail.com>
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal

View File

@ -1,5 +1,5 @@
/*
Copyright <2018-2024> <scott.e.graves@protonmail.com>
Copyright <2018-2025> <scott.e.graves@protonmail.com>
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal

View File

@ -1,5 +1,5 @@
/*
Copyright <2018-2024> <scott.e.graves@protonmail.com>
Copyright <2018-2025> <scott.e.graves@protonmail.com>
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
@ -32,17 +32,19 @@ 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,
stop_type_callback stop_requested_cb,
std::string_view token,
std::optional<std::string> 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 source_path,
stop_type_callback stop_requested_cb,
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,
stop_type_callback stop_requested_cb, std::string_view token,
std::vector<std::array<unsigned char,
crypto_aead_xchacha20poly1305_IETF_NPUBBYTES>>
iv_list,
@ -62,7 +64,7 @@ public:
private:
utils::encryption::hash_256_t key_;
stop_type &stop_requested_;
stop_type_callback stop_requested_cb_;
size_t error_return_;
std::unique_ptr<utils::file::i_file> source_file_;
@ -87,16 +89,16 @@ 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_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 {
[[nodiscard]] static constexpr auto get_encrypted_chunk_size()
-> std::size_t {
return encrypted_chunk_size_;
}
@ -116,14 +118,17 @@ public:
return error_return_;
}
[[nodiscard]] auto get_iv_list()
-> std::vector<std::array<unsigned char,
crypto_aead_xchacha20poly1305_IETF_NPUBBYTES>> {
[[nodiscard]] static constexpr auto get_header_size() -> std::size_t {
return header_size_;
}
[[nodiscard]] auto get_iv_list() -> std::vector<
std::array<unsigned char, crypto_aead_xchacha20poly1305_IETF_NPUBBYTES>> {
return iv_list_;
}
[[nodiscard]] auto get_stop_requested() const -> bool {
return stop_requested_;
return stop_requested_cb_();
}
[[nodiscard]] auto get_total_size() const -> std::uint64_t {
@ -131,8 +136,8 @@ public:
}
[[nodiscard]] static auto reader_function(char *buffer, size_t size,
size_t nitems,
void *instream) -> size_t {
size_t nitems, void *instream)
-> size_t {
return reinterpret_cast<encrypting_reader *>(instream)->reader_function(
buffer, size, nitems);
}

View File

@ -1,5 +1,5 @@
/*
Copyright <2018-2024> <scott.e.graves@protonmail.com>
Copyright <2018-2025> <scott.e.graves@protonmail.com>
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
@ -185,7 +185,6 @@ encrypt_data(const std::array<unsigned char,
buf.size(), res);
}
#if defined(PROJECT_ENABLE_CURL)
using reader_func_t =
std::function<bool(data_buffer &cypher_text, std::uint64_t start_offset,
std::uint64_t end_offset)>;
@ -195,7 +194,11 @@ read_encrypted_range(const http_range &range,
const utils::encryption::hash_256_t &key,
reader_func_t reader_func, std::uint64_t total_size,
data_buffer &data) -> bool;
#endif // defined(PROJECT_ENABLE_CURL)
[[nodiscard]] auto read_encrypted_range(
const http_range &range, const utils::encryption::hash_256_t &key,
reader_func_t reader_func, std::uint64_t total_size, unsigned char *data,
std::size_t size, std::size_t &bytes_read) -> bool;
#endif // defined(PROJECT_ENABLE_BOOST)
template <typename hash_t>

View File

@ -1,5 +1,5 @@
/*
Copyright <2018-2024> <scott.e.graves@protonmail.com>
Copyright <2018-2025> <scott.e.graves@protonmail.com>
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal

View File

@ -1,5 +1,5 @@
/*
Copyright <2018-2024> <scott.e.graves@protonmail.com>
Copyright <2018-2025> <scott.e.graves@protonmail.com>
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal

View File

@ -1,5 +1,5 @@
/*
Copyright <2018-2024> <scott.e.graves@protonmail.com>
Copyright <2018-2025> <scott.e.graves@protonmail.com>
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal

View File

@ -1,5 +1,5 @@
/*
Copyright <2018-2024> <scott.e.graves@protonmail.com>
Copyright <2018-2025> <scott.e.graves@protonmail.com>
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
@ -45,12 +45,13 @@ public:
private:
fs_file_t file_;
std::string encryption_token_;
public:
void close() override;
[[nodiscard]] auto copy_to(std::string_view new_path,
bool overwrite) const -> bool override;
[[nodiscard]] auto copy_to(std::string_view new_path, bool overwrite) const
-> bool override;
[[nodiscard]] auto exists() const -> bool override { return file_->exists(); }
@ -68,8 +69,8 @@ public:
return file_->get_read_buffer_size();
}
[[nodiscard]] auto
get_time(time_type type) const -> std::optional<std::uint64_t> override {
[[nodiscard]] auto get_time(time_type type) const
-> std::optional<std::uint64_t> override {
return file_->get_time(type);
}
@ -97,9 +98,10 @@ public:
[[nodiscard]] auto truncate(std::size_t size) -> bool override;
[[nodiscard]] auto
write(const unsigned char *data, std::size_t to_write, std::size_t offset,
std::size_t *total_written = nullptr) -> bool override;
[[nodiscard]] auto write(const unsigned char *data, std::size_t to_write,
std::size_t offset,
std::size_t *total_written = nullptr)
-> bool override;
public:
[[nodiscard]] operator bool() const override {

View File

@ -1,5 +1,5 @@
/*
Copyright <2018-2024> <scott.e.graves@protonmail.com>
Copyright <2018-2025> <scott.e.graves@protonmail.com>
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal

View File

@ -1,5 +1,5 @@
/*
Copyright <2018-2024> <scott.e.graves@protonmail.com>
Copyright <2018-2025> <scott.e.graves@protonmail.com>
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal

View File

@ -1,5 +1,5 @@
/*
Copyright <2018-2024> <scott.e.graves@protonmail.com>
Copyright <2018-2025> <scott.e.graves@protonmail.com>
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal

View File

@ -1,5 +1,5 @@
/*
Copyright <2018-2024> <scott.e.graves@protonmail.com>
Copyright <2018-2025> <scott.e.graves@protonmail.com>
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
@ -67,11 +67,44 @@ public:
thread_file(thread_file &&move_file) noexcept
: file_(std::move(move_file.file_)) {}
~thread_file() override { close(); }
~thread_file() override;
private:
using action_t = std::function<bool()>;
struct io_item final {
action_t action;
bool complete{false};
std::unique_ptr<std::mutex> mtx{
std::make_unique<std::mutex>(),
};
mutable std::unique_ptr<std::condition_variable> notify{
std::make_unique<std::condition_variable>(),
};
bool success{false};
void done(bool result);
void wait() const;
};
private:
fs_file_t file_;
private:
mutable std::vector<std::shared_ptr<io_item>> actions_;
mutable std::unique_ptr<std::thread> io_thread_;
mutable std::unique_ptr<std::mutex> mtx_{std::make_unique<std::mutex>()};
mutable std::unique_ptr<std::condition_variable> notify_{
std::make_unique<std::condition_variable>(),
};
stop_type stop_requested_{false};
private:
auto do_io(action_t action) const -> bool;
void thread_func() const;
public:
void close() override;

View File

@ -1,5 +1,5 @@
/*
Copyright <2018-2024> <scott.e.graves@protonmail.com>
Copyright <2018-2025> <scott.e.graves@protonmail.com>
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal

View File

@ -1,5 +1,5 @@
/*
Copyright <2018-2024> <scott.e.graves@protonmail.com>
Copyright <2018-2025> <scott.e.graves@protonmail.com>
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal

View File

@ -1,5 +1,5 @@
/*
Copyright <2018-2024> <scott.e.graves@protonmail.com>
Copyright <2018-2025> <scott.e.graves@protonmail.com>
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal

View File

@ -1,5 +1,5 @@
/*
Copyright <2018-2024> <scott.e.graves@protonmail.com>
Copyright <2018-2025> <scott.e.graves@protonmail.com>
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal

View File

@ -1,5 +1,5 @@
/*
Copyright <2018-2024> <scott.e.graves@protonmail.com>
Copyright <2018-2025> <scott.e.graves@protonmail.com>
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal

View File

@ -1,5 +1,5 @@
/*
Copyright <2018-2024> <scott.e.graves@protonmail.com>
Copyright <2018-2025> <scott.e.graves@protonmail.com>
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal

View File

@ -1,5 +1,5 @@
/*
Copyright <2018-2024> <scott.e.graves@protonmail.com>
Copyright <2018-2025> <scott.e.graves@protonmail.com>
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal

View File

@ -1,5 +1,5 @@
/*
Copyright <2018-2024> <scott.e.graves@protonmail.com>
Copyright <2018-2025> <scott.e.graves@protonmail.com>
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal

View File

@ -1,5 +1,5 @@
/*
Copyright <2018-2024> <scott.e.graves@protonmail.com>
Copyright <2018-2025> <scott.e.graves@protonmail.com>
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal

View File

@ -1,5 +1,5 @@
/*
Copyright <2018-2024> <scott.e.graves@protonmail.com>
Copyright <2018-2025> <scott.e.graves@protonmail.com>
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal

View File

@ -1,5 +1,5 @@
/*
Copyright <2018-2024> <scott.e.graves@protonmail.com>
Copyright <2018-2025> <scott.e.graves@protonmail.com>
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal

View File

@ -1,5 +1,5 @@
/*
Copyright <2018-2024> <scott.e.graves@protonmail.com>
Copyright <2018-2025> <scott.e.graves@protonmail.com>
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal

View File

@ -1,5 +1,5 @@
/*
Copyright <2018-2024> <scott.e.graves@protonmail.com>
Copyright <2018-2025> <scott.e.graves@protonmail.com>
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal

View File

@ -1,5 +1,5 @@
/*
Copyright <2018-2024> <scott.e.graves@protonmail.com>
Copyright <2018-2025> <scott.e.graves@protonmail.com>
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal

View File

@ -1,5 +1,5 @@
/*
Copyright <2018-2024> <scott.e.graves@protonmail.com>
Copyright <2018-2025> <scott.e.graves@protonmail.com>
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal

View File

@ -1,5 +1,5 @@
/*
Copyright <2018-2024> <scott.e.graves@protonmail.com>
Copyright <2018-2025> <scott.e.graves@protonmail.com>
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
@ -40,8 +40,8 @@ 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=(const encrypting_streambuf &)
-> encrypting_streambuf & = delete;
auto operator=(encrypting_streambuf &&) -> encrypting_streambuf & = delete;
explicit encrypting_streambuf(const encrypting_reader &reader)
@ -93,9 +93,10 @@ protected:
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 {
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);
}
@ -177,16 +178,16 @@ const std::size_t encrypting_reader::encrypted_chunk_size_ =
encrypting_reader::encrypting_reader(
std::string_view file_name, std::string_view source_path,
stop_type &stop_requested, std::string_view token,
stop_type_callback stop_requested_cb, std::string_view token,
std::optional<std::string> relative_parent_path, std::size_t error_return)
: key_(utils::encryption::generate_key<utils::encryption::hash_256_t>(
token)),
stop_requested_(stop_requested),
stop_requested_cb_(std::move(stop_requested_cb)),
error_return_(error_return),
source_file_(utils::file::file::open_or_create_file(source_path, true)) {
REPERTORY_USES_FUNCTION_NAME();
if (not *source_file_) {
if (not*source_file_) {
throw utils::error::create_exception(function_name, {
"file open failed",
source_path,
@ -237,17 +238,17 @@ encrypting_reader::encrypting_reader(
encrypting_reader::encrypting_reader(std::string_view encrypted_file_path,
std::string_view source_path,
stop_type &stop_requested,
stop_type_callback stop_requested_cb,
std::string_view token,
std::size_t error_return)
: key_(utils::encryption::generate_key<utils::encryption::hash_256_t>(
token)),
stop_requested_(stop_requested),
stop_requested_cb_(std::move(stop_requested_cb)),
error_return_(error_return),
source_file_(utils::file::file::open_or_create_file(source_path, true)) {
REPERTORY_USES_FUNCTION_NAME();
if (not *source_file_) {
if (not*source_file_) {
throw utils::error::create_exception(function_name, {
"file open failed",
source_path,
@ -283,19 +284,19 @@ encrypting_reader::encrypting_reader(std::string_view encrypted_file_path,
encrypting_reader::encrypting_reader(
std::string_view encrypted_file_path, std::string_view source_path,
stop_type &stop_requested, std::string_view token,
stop_type_callback stop_requested_cb, 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),
stop_requested_cb_(std::move(stop_requested_cb)),
error_return_(error_return),
source_file_(utils::file::file::open_or_create_file(source_path, true)) {
REPERTORY_USES_FUNCTION_NAME();
if (not *source_file_) {
if (not*source_file_) {
throw utils::error::create_exception(function_name, {
"file open failed",
source_path,
@ -329,7 +330,7 @@ encrypting_reader::encrypting_reader(
encrypting_reader::encrypting_reader(const encrypting_reader &reader)
: key_(reader.key_),
stop_requested_(reader.stop_requested_),
stop_requested_cb_(reader.stop_requested_cb_),
error_return_(reader.error_return_),
source_file_(
utils::file::file::open_file(reader.source_file_->get_path(), true)),
@ -343,7 +344,7 @@ encrypting_reader::encrypting_reader(const encrypting_reader &reader)
total_size_(reader.total_size_) {
REPERTORY_USES_FUNCTION_NAME();
if (not *source_file_) {
if (not*source_file_) {
throw utils::error::create_exception(
function_name, {
"file open failed",
@ -403,7 +404,7 @@ auto encrypting_reader::reader_function(char *buffer, size_t size,
try {
ret = true;
auto remain = read_size;
while (not stop_requested_ && ret && (remain != 0U)) {
while (not get_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_
@ -441,9 +442,9 @@ auto encrypting_reader::reader_function(char *buffer, size_t size,
}
}
return stop_requested_ ? static_cast<std::size_t>(CURL_READFUNC_ABORT)
: ret ? total_read
: error_return_;
return get_stop_requested() ? static_cast<std::size_t>(CURL_READFUNC_ABORT)
: ret ? total_read
: error_return_;
}
} // namespace repertory::utils::encryption

View File

@ -1,5 +1,5 @@
/*
Copyright <2018-2024> <scott.e.graves@protonmail.com>
Copyright <2018-2025> <scott.e.graves@protonmail.com>
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
@ -25,26 +25,27 @@
#include "utils/collection.hpp"
#include "utils/encrypting_reader.hpp"
#include "utils/path.hpp"
namespace repertory::utils::encryption {
auto decrypt_file_path(std::string_view encryption_token,
std::string &file_path) -> bool {
std::string decrypted_file_path{};
std::vector<std::string> decrypted_parts;
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 (not res) {
return res;
if (not decrypt_file_name(encryption_token, file_name)) {
return false;
}
decrypted_file_path += '/' + file_name;
decrypted_parts.push_back(file_name);
}
file_path = decrypted_file_path;
file_path =
utils::path::create_api_path(utils::string::join(decrypted_parts, '/'));
return true;
}
@ -56,34 +57,27 @@ auto decrypt_file_name(std::string_view encryption_token,
}
file_name.clear();
if (not utils::encryption::decrypt_data(encryption_token, buffer,
file_name)) {
return false;
}
return true;
return utils::encryption::decrypt_data(encryption_token, buffer, file_name);
}
#if defined(PROJECT_ENABLE_CURL)
auto read_encrypted_range(const http_range &range,
const utils::encryption::hash_256_t &key,
reader_func_t reader_func, std::uint64_t total_size,
data_buffer &data) -> bool {
const auto encrypted_chunk_size =
auto encrypted_chunk_size =
utils::encryption::encrypting_reader::get_encrypted_chunk_size();
const auto data_chunk_size =
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 start_chunk = static_cast<std::size_t>(range.begin / data_chunk_size);
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(
auto start_offset = chunk * encrypted_chunk_size;
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));
@ -98,7 +92,7 @@ auto read_encrypted_range(const http_range &range,
}
cypher.clear();
const auto data_size = static_cast<std::size_t>(std::min(
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)),
@ -111,7 +105,58 @@ auto read_encrypted_range(const http_range &range,
return true;
}
#endif // defined(PROJECT_ENABLE_CURL)
auto read_encrypted_range(const http_range &range,
const utils::encryption::hash_256_t &key,
reader_func_t reader_func, std::uint64_t total_size,
unsigned char *data, std::size_t size,
std::size_t &bytes_read) -> bool {
bytes_read = 0U;
auto encrypted_chunk_size =
utils::encryption::encrypting_reader::get_encrypted_chunk_size();
auto data_chunk_size =
utils::encryption::encrypting_reader::get_data_chunk_size();
auto start_chunk = static_cast<std::size_t>(range.begin / data_chunk_size);
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);
std::span dest_buffer(data, size);
for (std::size_t chunk = start_chunk; chunk <= end_chunk; chunk++) {
data_buffer cypher;
auto start_offset = chunk * encrypted_chunk_size;
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));
if (not reader_func(cypher, start_offset, end_offset)) {
return false;
}
data_buffer source_buffer;
if (not utils::encryption::decrypt_data(key, cypher, source_buffer)) {
return false;
}
cypher.clear();
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::next(dest_buffer.begin(), static_cast<std::int64_t>(bytes_read)));
remain -= data_size;
bytes_read += data_size;
source_offset = 0U;
}
return true;
}
} // namespace repertory::utils::encryption
#endif // defined(PROJECT_ENABLE_LIBSODIUM) && defined (PROJECT_ENABLE_BOOST)

View File

@ -1,5 +1,5 @@
/*
Copyright <2018-2024> <scott.e.graves@protonmail.com>
Copyright <2018-2025> <scott.e.graves@protonmail.com>
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal

View File

@ -1,5 +1,5 @@
/*
Copyright <2018-2024> <scott.e.graves@protonmail.com>
Copyright <2018-2025> <scott.e.graves@protonmail.com>
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal

View File

@ -1,5 +1,5 @@
/*
Copyright <2018-2024> <scott.e.graves@protonmail.com>
Copyright <2018-2025> <scott.e.graves@protonmail.com>
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal

View File

@ -1,5 +1,5 @@
/*
Copyright <2018-2024> <scott.e.graves@protonmail.com>
Copyright <2018-2025> <scott.e.graves@protonmail.com>
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
@ -23,31 +23,166 @@
#include "utils/file_enc_file.hpp"
#include "utils/common.hpp"
#include "utils/encrypting_reader.hpp"
#include "utils/encryption.hpp"
namespace repertory::utils::file {
auto enc_file::attach_file(fs_file_t file) -> fs_file_t {}
auto enc_file::attach_file(fs_file_t file) -> fs_file_t {
return fs_file_t{
new enc_file(std::move(file)),
};
}
enc_file::enc_file(fs_file_t file) : file_(std::move(file)) {}
void enc_file::close() {}
void enc_file::close() { file_->close(); }
auto enc_file::copy_to(std::string_view new_path,
bool overwrite) const -> bool {}
auto enc_file::copy_to(std::string_view new_path, bool overwrite) const
-> bool {
return file_->copy_to(new_path, overwrite);
}
void enc_file::flush() const {}
void enc_file::flush() const { return file_->flush(); }
auto enc_file::move_to(std::string_view path) -> bool {}
auto enc_file::move_to(std::string_view path) -> bool {
return file_->move_to(path);
}
auto enc_file::read(unsigned char *data, std::size_t to_read,
std::uint64_t offset, std::size_t *total_read) -> bool {}
std::uint64_t offset, std::size_t *total_read) -> bool {
if (total_read != nullptr) {
*total_read = 0U;
}
auto enc_file::remove() -> bool {}
auto file_size{size()};
if (not file_size.has_value()) {
return false;
}
auto enc_file::truncate(std::size_t size) -> bool {}
to_read = utils::calculate_read_size(file_size.value(), to_read, offset);
if (to_read == 0U) {
return true;
}
std::size_t bytes_read{};
auto ret{
utils::encryption::read_encrypted_range(
{offset, offset + to_read - 1U},
utils::encryption::generate_key<utils::encryption::hash_256_t>(
encryption_token_),
[&](auto &&ct_buffer, auto &&start_offset,
auto &&end_offset) -> bool {
ct_buffer.resize(end_offset - start_offset + 1U);
return file_->read(ct_buffer, start_offset);
},
file_size.value(), data, to_read, bytes_read),
};
if (ret && total_read != nullptr) {
*total_read = bytes_read;
}
return ret;
}
auto enc_file::remove() -> bool { return file_->remove(); }
auto enc_file::truncate(std::size_t size) -> bool {
if (size == 0U) {
return file_->truncate(size);
}
auto file_size{this->size()};
if (not file_size.has_value()) {
return false;
}
if (size == file_size.value()) {
return true;
}
auto chunks{
size / utils::encryption::encrypting_reader::get_data_chunk_size(),
};
auto real_size{
(chunks * utils::encryption::encrypting_reader::get_data_chunk_size()) +
(chunks * utils::encryption::encrypting_reader::get_header_size()),
};
auto remain{
size % utils::encryption::encrypting_reader::get_data_chunk_size(),
};
if (remain > 0U) {
real_size +=
(remain + utils::encryption::encrypting_reader::get_header_size());
}
if (size < file_size.value()) {
if (remain == 0U) {
return file_->truncate(real_size);
}
auto begin_chunk{
size / utils::encryption::encrypting_reader::get_data_chunk_size(),
};
auto offset{
begin_chunk *
utils::encryption::encrypting_reader::get_data_chunk_size(),
};
std::size_t total_read{};
data_buffer data(
utils::encryption::encrypting_reader::get_data_chunk_size());
if (not i_file::read(data, offset, &total_read)) {
return false;
}
data.resize(remain);
if (not file_->truncate(real_size)) {
return false;
}
return i_file::write(data, offset);
}
auto begin_chunk{
file_size.value() /
utils::encryption::encrypting_reader::get_data_chunk_size(),
};
auto end_chunk{
utils::divide_with_ceiling(
file_size.value(),
utils::encryption::encrypting_reader::get_data_chunk_size()),
};
return false;
}
auto enc_file::write(const unsigned char *data, std::size_t to_write,
std::size_t offset, std::size_t *total_written) -> bool {}
std::size_t offset, std::size_t *total_written) -> bool {
auto file_size{size()};
if (not file_size.has_value()) {
return false;
}
auto enc_file::size() const -> std::optional<std::uint64_t> {}
if ((offset + to_write) > file_size.value()) {
if (not truncate((offset + to_write) - file_size.value())) {
return false;
}
}
return false;
}
auto enc_file::size() const -> std::optional<std::uint64_t> {
auto file_size = file_->size();
if (not file_size.has_value()) {
return std::nullopt;
}
return utils::encryption::encrypting_reader::calculate_decrypted_size(
file_size.value());
}
} // namespace repertory::utils::file
#endif // defined(PROJECT_ENABLE_LIBSODIUM) && defined(PROJECT_ENABLE_BOOST)

View File

@ -1,5 +1,5 @@
/*
Copyright <2018-2024> <scott.e.graves@protonmail.com>
Copyright <2018-2025> <scott.e.graves@protonmail.com>
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal

View File

@ -1,5 +1,5 @@
/*
Copyright <2018-2024> <scott.e.graves@protonmail.com>
Copyright <2018-2025> <scott.e.graves@protonmail.com>
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
@ -127,7 +127,7 @@ auto smb_directory::open(std::wstring_view host, std::wstring_view user,
}
auto smb_directory::copy_to(std::string_view new_path,
bool overwrite) const -> bool {
bool /* overwrite */) const -> bool {
REPERTORY_USES_FUNCTION_NAME();
try {

View File

@ -1,5 +1,5 @@
/*
Copyright <2018-2024> <scott.e.graves@protonmail.com>
Copyright <2018-2025> <scott.e.graves@protonmail.com>
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal

View File

@ -1,5 +1,5 @@
/*
Copyright <2018-2024> <scott.e.graves@protonmail.com>
Copyright <2018-2025> <scott.e.graves@protonmail.com>
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
@ -25,41 +25,174 @@ namespace repertory::utils::file {
// auto thread_file::attach_file(native_handle handle,
// bool read_only) -> fs_file_t {}
thread_file::thread_file(std::string_view path)
: file_(new repertory::utils::file::file(path)) {}
thread_file::thread_file(std::wstring_view path)
: file_(new repertory::utils::file::file(utils::string::to_utf8(path))) {}
auto thread_file::attach_file(fs_file_t file) -> fs_file_t {}
auto thread_file::attach_file(fs_file_t file) -> fs_file_t {
return fs_file_t{
new thread_file(std::move(file)),
};
}
auto thread_file::open_file(std::string_view path,
bool read_only) -> fs_file_t {}
bool read_only) -> fs_file_t {
return fs_file_t{
new thread_file(file::open_file(path, read_only)),
};
}
auto thread_file::open_or_create_file(std::string_view path,
bool read_only) -> fs_file_t {}
bool read_only) -> fs_file_t {
return fs_file_t{
new thread_file(file::open_or_create_file(path, read_only)),
};
}
void thread_file::io_item::done(bool result) {
unique_mutex_lock lock(*mtx);
complete = true;
success = result;
notify->notify_all();
}
void thread_file::io_item::wait() const {
if (complete) {
return;
}
unique_mutex_lock lock(*mtx);
while (not complete) {
notify->wait(lock);
}
notify->notify_all();
}
thread_file::thread_file(std::string_view path) : file_(new file(path)) {}
thread_file::thread_file(std::wstring_view path)
: file_(new file(utils::string::to_utf8(path))) {}
thread_file::thread_file(fs_file_t file) : file_(std::move(file)) {}
void thread_file::close() {}
thread_file::~thread_file() {
close();
if (io_thread_) {
io_thread_->join();
}
}
void thread_file::close() {
do_io([this]() -> bool {
file_->close();
stop_requested_ = true;
return true;
});
}
auto thread_file::copy_to(std::string_view new_path,
bool overwrite) const -> bool {}
bool overwrite) const -> bool {
return do_io([this, &new_path, &overwrite]() -> bool {
return file_->copy_to(new_path, overwrite);
});
}
void thread_file::flush() const {}
auto thread_file::do_io(action_t action) const -> bool {
unique_mutex_lock lock(*mtx_);
if (stop_requested_) {
return false;
}
auto thread_file::move_to(std::string_view path) -> bool {}
if (not io_thread_) {
io_thread_ = std::make_unique<std::thread>([this]() { thread_func(); });
}
auto item = std::make_shared<io_item>(action);
actions_.emplace_back(item);
notify_->notify_all();
lock.unlock();
item->wait();
return item->success;
}
void thread_file::flush() const {
do_io([this]() -> bool {
file_->flush();
return true;
});
}
auto thread_file::move_to(std::string_view path) -> bool {
return do_io([this, &path]() -> bool { return file_->move_to(path); });
}
auto thread_file::read(unsigned char *data, std::size_t to_read,
std::uint64_t offset, std::size_t *total_read) -> bool {}
std::uint64_t offset, std::size_t *total_read) -> bool {
return do_io([this, &data, &to_read, &offset, &total_read]() -> bool {
return file_->read(data, to_read, offset, total_read);
});
}
auto thread_file::remove() -> bool {}
auto thread_file::remove() -> bool {
return do_io([this]() -> bool { return file_->remove(); });
}
auto thread_file::truncate(std::size_t size) -> bool {}
void thread_file::thread_func() const {
unique_mutex_lock lock(*mtx_);
notify_->notify_all();
lock.unlock();
const auto run_actions = [this, &lock]() {
auto actions = actions_;
actions_.clear();
notify_->notify_all();
lock.unlock();
for (auto &&action : actions) {
action->done(action->action());
}
};
while (not stop_requested_) {
lock.lock();
if (stop_requested_) {
lock.unlock();
break;
}
while (not stop_requested_ && actions_.empty()) {
notify_->wait(lock);
}
if (stop_requested_) {
lock.unlock();
break;
}
run_actions();
}
lock.lock();
run_actions();
}
auto thread_file::truncate(std::size_t size) -> bool {
return do_io([this, &size]() -> bool { return file_->truncate(size); });
}
auto thread_file::write(const unsigned char *data, std::size_t to_write,
std::size_t offset,
std::size_t *total_written) -> bool {}
std::size_t *total_written) -> bool {
return do_io([this, &data, &to_write, &offset, &total_written]() -> bool {
return file_->write(data, to_write, offset, total_written);
});
}
auto thread_file::size() const -> std::optional<std::uint64_t> {}
auto thread_file::size() const -> std::optional<std::uint64_t> {
std::optional<std::uint64_t> size;
do_io([this, &size]() -> bool {
size = file_->size();
return size.has_value();
});
return size;
}
} // namespace repertory::utils::file

View File

@ -1,5 +1,5 @@
/*
Copyright <2018-2024> <scott.e.graves@protonmail.com>
Copyright <2018-2025> <scott.e.graves@protonmail.com>
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal

View File

@ -1,5 +1,5 @@
/*
Copyright <2018-2024> <scott.e.graves@protonmail.com>
Copyright <2018-2025> <scott.e.graves@protonmail.com>
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal

View File

@ -1,5 +1,5 @@
/*
Copyright <2018-2024> <scott.e.graves@protonmail.com>
Copyright <2018-2025> <scott.e.graves@protonmail.com>
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal

View File

@ -1,5 +1,5 @@
/*
Copyright <2018-2024> <scott.e.graves@protonmail.com>
Copyright <2018-2025> <scott.e.graves@protonmail.com>
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal

View File

@ -1,5 +1,5 @@
/*
Copyright <2018-2024> <scott.e.graves@protonmail.com>
Copyright <2018-2025> <scott.e.graves@protonmail.com>
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal

View File

@ -1,5 +1,5 @@
/*
Copyright <2018-2024> <scott.e.graves@protonmail.com>
Copyright <2018-2025> <scott.e.graves@protonmail.com>
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal

View File

@ -1,5 +1,5 @@
/*
Copyright <2018-2024> <scott.e.graves@protonmail.com>
Copyright <2018-2025> <scott.e.graves@protonmail.com>
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal

View File

@ -1,5 +1,5 @@
/*
Copyright <2018-2024> <scott.e.graves@protonmail.com>
Copyright <2018-2025> <scott.e.graves@protonmail.com>
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
@ -57,8 +57,10 @@ auto create_random_file(std::size_t size) -> utils::file::i_file & {
#if defined(PROJECT_ENABLE_LIBSODIUM)
randombytes_buf(buf.data(), buf.size());
#else // !defined(PROJECT_ENABLE_LIBSODIUM)
thread_local std::mt19937 gen(static_cast<unsigned long>(
std::time(nullptr) ^ std::random_device{}()));
thread_local std::mt19937 gen{
static_cast<std::uint_fast32_t>(std::time(nullptr)) ^
static_cast<std::uint_fast32_t>(std::random_device{}()),
};
std::uniform_int_distribution<std::uint8_t> dis(0U, 255U);
std::generate(buf.begin(), buf.end(), [&]() -> auto { return dis(gen); });
#endif // defined(PROJECT_ENABLE_LIBSODIUM)

View File

@ -1,5 +1,5 @@
/*
Copyright <2018-2024> <scott.e.graves@protonmail.com>
Copyright <2018-2025> <scott.e.graves@protonmail.com>
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal

View File

@ -1,5 +1,5 @@
/*
Copyright <2018-2024> <scott.e.graves@protonmail.com>
Copyright <2018-2025> <scott.e.graves@protonmail.com>
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal

View File

@ -1,5 +1,5 @@
/*
Copyright <2018-2024> <scott.e.graves@protonmail.com>
Copyright <2018-2025> <scott.e.graves@protonmail.com>
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal

View File

@ -1,5 +1,5 @@
/*
Copyright <2018-2024> <scott.e.graves@protonmail.com>
Copyright <2018-2025> <scott.e.graves@protonmail.com>
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
@ -23,6 +23,10 @@
#if defined(PROJECT_ENABLE_LIBSODIUM) && defined(PROJECT_ENABLE_BOOST)
namespace {
const auto get_stop_requested = []() -> bool { return false; };
} // namespace
namespace repertory {
TEST(utils_encrypting_reader, read_file_data) {
const auto token = std::string("moose");
@ -30,9 +34,8 @@ TEST(utils_encrypting_reader, read_file_data) {
8U * utils::encryption::encrypting_reader::get_data_chunk_size());
EXPECT_TRUE(source_file);
if (source_file) {
stop_type stop_requested{false};
utils::encryption::encrypting_reader reader(
"test.dat", source_file.get_path(), stop_requested, token);
"test.dat", source_file.get_path(), get_stop_requested, token);
for (std::uint8_t i = 0U; i < 8U; i++) {
data_buffer buffer(
@ -70,9 +73,8 @@ TEST(utils_encrypting_reader, read_file_data_in_multiple_chunks) {
8U * utils::encryption::encrypting_reader::get_data_chunk_size());
EXPECT_TRUE(source_file);
if (source_file) {
stop_type stop_requested{false};
utils::encryption::encrypting_reader reader(
"test.dat", source_file.get_path(), stop_requested, token);
"test.dat", source_file.get_path(), get_stop_requested, token);
for (std::uint8_t i = 0U; i < 8U; i += 2U) {
data_buffer buffer(
@ -118,9 +120,8 @@ TEST(utils_encrypting_reader, read_file_data_as_stream) {
8U * utils::encryption::encrypting_reader::get_data_chunk_size());
EXPECT_TRUE(source_file);
if (source_file) {
stop_type stop_requested{false};
utils::encryption::encrypting_reader reader(
"test.dat", source_file.get_path(), stop_requested, token);
"test.dat", source_file.get_path(), get_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());
@ -171,9 +172,8 @@ TEST(utils_encrypting_reader, read_file_data_in_multiple_chunks_as_stream) {
8u * utils::encryption::encrypting_reader::get_data_chunk_size());
EXPECT_TRUE(source_file);
if (source_file) {
stop_type stop_requested{false};
utils::encryption::encrypting_reader reader(
"test.dat", source_file.get_path(), stop_requested, token);
"test.dat", source_file.get_path(), get_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());

View File

@ -1,5 +1,5 @@
/*
Copyright <2018-2024> <scott.e.graves@protonmail.com>
Copyright <2018-2025> <scott.e.graves@protonmail.com>
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
@ -23,6 +23,10 @@
#if defined(PROJECT_ENABLE_LIBSODIUM)
namespace {
const auto get_stop_requested = []() -> bool { return false; };
} // namespace
namespace repertory {
static constexpr const std::string_view token{"moose"};
static constexpr const std::wstring_view token_w{L"moose"};
@ -250,9 +254,8 @@ TEST(utils_encryption, decrypt_file_name) {
8U * utils::encryption::encrypting_reader::get_data_chunk_size());
EXPECT_TRUE(source_file);
if (source_file) {
stop_type stop_requested{false};
utils::encryption::encrypting_reader reader(
"test.dat", source_file.get_path(), stop_requested, token,
"test.dat", source_file.get_path(), get_stop_requested, token,
std::nullopt);
auto file_name = reader.get_encrypted_file_name();
@ -267,9 +270,9 @@ TEST(utils_encryption, decrypt_file_path) {
8U * utils::encryption::encrypting_reader::get_data_chunk_size());
EXPECT_TRUE(source_file);
if (source_file) {
stop_type stop_requested{false};
utils::encryption::encrypting_reader reader(
"test.dat", source_file.get_path(), stop_requested, token, "moose/cow");
"test.dat", source_file.get_path(), get_stop_requested, token,
"moose/cow");
auto file_path = reader.get_encrypted_file_path();

View File

@ -1,5 +1,5 @@
/*
Copyright <2018-2024> <scott.e.graves@protonmail.com>
Copyright <2018-2025> <scott.e.graves@protonmail.com>
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal

View File

@ -1,5 +1,5 @@
/*
Copyright <2018-2024> <scott.e.graves@protonmail.com>
Copyright <2018-2025> <scott.e.graves@protonmail.com>
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
@ -22,9 +22,49 @@
#include "test.hpp"
namespace {
static constexpr const auto file_type_count{1U};
#if defined(PROJECT_ENABLE_LIBSODIUM) && defined(PROJECT_ENABLE_BOOST)
#include "utils/file_enc_file.hpp"
constexpr const auto file_type_count{3U};
#else
constexpr const auto file_type_count{2U};
#endif
[[nodiscard]] auto create_file(auto idx, auto path,
bool read_only = false) -> auto {
switch (idx) {
case 0U:
return repertory::utils::file::file::open_or_create_file(path, read_only);
case 1U:
return repertory::utils::file::thread_file::open_or_create_file(path,
read_only);
#if defined(PROJECT_ENABLE_LIBSODIUM) && defined(PROJECT_ENABLE_BOOST)
case 2U:
return repertory::utils::file::enc_file::attach_file(
repertory::utils::file::file::open_or_create_file(path, read_only));
#endif
default:
throw std::runtime_error("not supported");
}
}
[[nodiscard]] auto open_file(auto idx, auto path,
bool read_only = false) -> auto {
switch (idx) {
case 0U:
return repertory::utils::file::file::open_file(path, read_only);
case 1U:
return repertory::utils::file::thread_file::open_file(path, read_only);
#if defined(PROJECT_ENABLE_LIBSODIUM) && defined(PROJECT_ENABLE_BOOST)
case 2U:
return repertory::utils::file::enc_file::attach_file(
repertory::utils::file::file::open_file(path, read_only));
#endif
default:
throw std::runtime_error("not supported");
}
}
} // namespace
namespace repertory {
TEST(utils_file, can_create_and_remove_file) {
for (auto idx = 0U; idx < file_type_count; ++idx) {
@ -32,8 +72,7 @@ TEST(utils_file, can_create_and_remove_file) {
EXPECT_FALSE(utils::file::file(path).exists() ||
utils::file::directory(path).exists());
auto file = idx == 0U ? utils::file::file::open_or_create_file(path)
: utils::file::thread_file::open_or_create_file(path);
auto file{create_file(idx, path)};
EXPECT_TRUE(*file);
EXPECT_TRUE(utils::file::file(path).exists());
@ -51,15 +90,12 @@ TEST(utils_file, can_open_file) {
auto path = test::generate_test_file_name("utils_file");
{
auto file = idx == 0U
? utils::file::file::open_or_create_file(path)
: utils::file::thread_file::open_or_create_file(path);
auto file{create_file(idx, path)};
EXPECT_TRUE(*file);
}
{
auto file = idx == 0U ? utils::file::file::open_file(path)
: utils::file::thread_file::open_file(path);
auto file{create_file(idx, path)};
EXPECT_TRUE(*file);
}
}
@ -69,8 +105,7 @@ TEST(utils_file, open_file_fails_if_not_found) {
for (auto idx = 0U; idx < file_type_count; ++idx) {
auto path = test::generate_test_file_name("utils_file");
auto file = idx == 0U ? utils::file::file::open_file(path)
: utils::file::thread_file::open_file(path);
auto file{open_file(idx, path)};
EXPECT_FALSE(*file);
}
}
@ -79,9 +114,7 @@ TEST(utils_file, write_fails_for_read_only_file) {
for (auto idx = 0U; idx < file_type_count; ++idx) {
auto path = test::generate_test_file_name("utils_file");
auto file = idx == 0U
? utils::file::file::open_or_create_file(path, true)
: utils::file::thread_file::open_or_create_file(path, true);
auto file{create_file(idx, path, true)};
EXPECT_TRUE(utils::file::file(path).exists());
EXPECT_TRUE(*file);
std::size_t bytes_written{};
@ -188,8 +221,8 @@ TEST(utils_file, read_and_write_json_file_encrypted) {
#if defined(PROJECT_ENABLE_LIBDSM)
TEST(utils_file, smb_create_smb_path) {
auto path = "//server/share";
auto rel_path = "test/test.txt";
const auto *path = "//server/share";
const auto *rel_path = "test/test.txt";
auto smb_path = utils::file::smb_create_smb_path(path, rel_path);
EXPECT_STREQ("//server/share/test/test.txt", smb_path.c_str());
@ -207,7 +240,7 @@ TEST(utils_file, smb_create_smb_path) {
}
TEST(utils_file, smb_create_relative_path) {
auto path = "//server/share/test.txt";
const auto *path = "//server/share/test.txt";
auto rel_path = utils::file::smb_create_relative_path(path);
EXPECT_STREQ("\\test.txt", rel_path.c_str());
@ -225,7 +258,7 @@ TEST(utils_file, smb_create_relative_path) {
}
TEST(utils_file, smb_create_search_path) {
auto path = "//server/share";
const auto *path = "//server/share";
auto search_path = utils::file::smb_create_search_path(path);
EXPECT_STREQ("\\*", search_path.c_str());
@ -251,8 +284,8 @@ TEST(utils_file, smb_create_search_path) {
}
TEST(utils_file, smb_parent_is_same) {
auto path1 = "//server/share";
auto path2 = "//server/share";
const auto *path1 = "//server/share";
const auto *path2 = "//server/share";
EXPECT_TRUE(utils::file::smb_parent_is_same(path1, path2));
path1 = "//server/share/";
@ -269,8 +302,8 @@ TEST(utils_file, smb_parent_is_same) {
}
TEST(utils_file, smb_parent_is_not_same) {
auto path1 = "server/share";
auto path2 = "//server/share";
const auto *path1 = "server/share";
const auto *path2 = "//server/share";
EXPECT_FALSE(utils::file::smb_parent_is_same(path1, path2));
path1 = "server/share/";

View File

@ -1,5 +1,5 @@
/*
Copyright <2018-2024> <scott.e.graves@protonmail.com>
Copyright <2018-2025> <scott.e.graves@protonmail.com>
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal

View File

@ -1,5 +1,5 @@
/*
Copyright <2018-2024> <scott.e.graves@protonmail.com>
Copyright <2018-2025> <scott.e.graves@protonmail.com>
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal

View File

@ -1,5 +1,5 @@
/*
Copyright <2018-2024> <scott.e.graves@protonmail.com>
Copyright <2018-2025> <scott.e.graves@protonmail.com>
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal