Compare commits
10 Commits
f73c706b8b
...
33fa52f5a4
Author | SHA1 | Date | |
---|---|---|---|
33fa52f5a4 | |||
eaae2fea77 | |||
b4999323da | |||
1cdc174207 | |||
8262c2db29 | |||
dfd239c30d | |||
37b1e156d4 | |||
1751847ec2 | |||
f878a7b760 | |||
f9a8751a57 |
@ -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_
|
|
@ -38,8 +38,8 @@
|
|||||||
#include "types/remote.hpp"
|
#include "types/remote.hpp"
|
||||||
#include "types/repertory.hpp"
|
#include "types/repertory.hpp"
|
||||||
#include "utils/common.hpp"
|
#include "utils/common.hpp"
|
||||||
|
#include "utils/file.hpp"
|
||||||
#include "utils/file_utils.hpp"
|
#include "utils/file_utils.hpp"
|
||||||
#include "utils/native_file.hpp"
|
|
||||||
#include "utils/path.hpp"
|
#include "utils/path.hpp"
|
||||||
#include "utils/time.hpp"
|
#include "utils/time.hpp"
|
||||||
|
|
||||||
@ -472,21 +472,20 @@ auto remote_server::fuse_read(
|
|||||||
if (os_handle != INVALID_HANDLE_VALUE) {
|
if (os_handle != INVALID_HANDLE_VALUE) {
|
||||||
errno = EFAULT;
|
errno = EFAULT;
|
||||||
|
|
||||||
auto file = native_file::attach(os_handle);
|
auto file = utils::file::file::attach_file(os_handle, true);
|
||||||
std::uint64_t file_size{};
|
if (file) {
|
||||||
if (file->get_file_size(file_size)) {
|
auto file_size = file.size();
|
||||||
data.resize(utils::calculate_read_size(
|
data.resize(utils::calculate_read_size(
|
||||||
file_size, static_cast<std::size_t>(read_size), read_offset));
|
file_size, static_cast<std::size_t>(read_size), read_offset));
|
||||||
if (!data.empty()) {
|
if (data.empty()) {
|
||||||
|
res = 0;
|
||||||
|
errno = 0;
|
||||||
|
} else {
|
||||||
std::size_t bytes_read{};
|
std::size_t bytes_read{};
|
||||||
if (file->read_bytes(data.data(), data.size(), read_offset,
|
if (file.read(data.data(), data.size(), read_offset, &bytes_read)) {
|
||||||
bytes_read)) {
|
|
||||||
res = 0;
|
res = 0;
|
||||||
errno = 0;
|
errno = 0;
|
||||||
}
|
}
|
||||||
} else {
|
|
||||||
res = 0;
|
|
||||||
errno = 0;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -539,10 +538,10 @@ auto remote_server::fuse_write(
|
|||||||
if (os_handle != INVALID_HANDLE_VALUE) {
|
if (os_handle != INVALID_HANDLE_VALUE) {
|
||||||
errno = EFAULT;
|
errno = EFAULT;
|
||||||
if ((write_size == 0) ||
|
if ((write_size == 0) ||
|
||||||
native_file::attach(os_handle)->write_bytes(
|
utils::file::file::attach_file(os_handle).write(
|
||||||
reinterpret_cast<const unsigned char *>(buffer),
|
reinterpret_cast<const unsigned char *>(buffer),
|
||||||
static_cast<std::size_t>(write_size), write_offset,
|
static_cast<std::size_t>(write_size), write_offset,
|
||||||
bytes_written)) {
|
&bytes_written)) {
|
||||||
res = 0;
|
res = 0;
|
||||||
errno = 0;
|
errno = 0;
|
||||||
}
|
}
|
||||||
|
@ -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
|
|
@ -31,6 +31,8 @@
|
|||||||
#include "platform/platform.hpp"
|
#include "platform/platform.hpp"
|
||||||
#include "providers/s3/s3_provider.hpp"
|
#include "providers/s3/s3_provider.hpp"
|
||||||
#include "providers/sia/sia_provider.hpp"
|
#include "providers/sia/sia_provider.hpp"
|
||||||
|
#include "utils/file_utils.hpp"
|
||||||
|
#include "utils/path.hpp"
|
||||||
|
|
||||||
extern std::size_t PROVIDER_INDEX;
|
extern std::size_t PROVIDER_INDEX;
|
||||||
|
|
||||||
@ -47,15 +49,19 @@ protected:
|
|||||||
void SetUp() override {
|
void SetUp() override {
|
||||||
if (PROVIDER_INDEX != 0) {
|
if (PROVIDER_INDEX != 0) {
|
||||||
if (PROVIDER_INDEX == 1) {
|
if (PROVIDER_INDEX == 1) {
|
||||||
EXPECT_TRUE(utils::file::delete_directory_recursively(
|
EXPECT_TRUE(
|
||||||
utils::path::combine(test::get_test_output_dir(), {"winfsp_test" + std::to_string(PROVIDER_INDEX)}));
|
utils::file::delete_directory_recursively(utils::path::combine(
|
||||||
|
test::get_test_output_dir(),
|
||||||
|
{"winfsp_test" + std::to_string(PROVIDER_INDEX)})));
|
||||||
|
|
||||||
app_config src_cfg(
|
app_config src_cfg(
|
||||||
provider_type::s3,
|
provider_type::s3,
|
||||||
utils::path::combine(test::get_test_input_dir(), {"storj"}));
|
utils::path::combine(test::get_test_input_dir(), {"storj"}));
|
||||||
config = std::make_unique<app_config>(
|
config = std::make_unique<app_config>(
|
||||||
provider_type::s3,
|
provider_type::s3,
|
||||||
utils::path::combine(test::get_test_output_dir(), {"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
|
EXPECT_FALSE(config
|
||||||
->set_value_by_name("S3Config.AccessKey",
|
->set_value_by_name("S3Config.AccessKey",
|
||||||
src_cfg.get_s3_config().access_key)
|
src_cfg.get_s3_config().access_key)
|
||||||
|
@ -63,8 +63,6 @@ auto main(int argc, char **argv) -> int {
|
|||||||
::testing::InitGoogleTest(&argc, argv);
|
::testing::InitGoogleTest(&argc, argv);
|
||||||
auto ret = RUN_ALL_TESTS();
|
auto ret = RUN_ALL_TESTS();
|
||||||
|
|
||||||
delete_generated_files();
|
|
||||||
|
|
||||||
repertory::project_cleanup();
|
repertory::project_cleanup();
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
|
@ -274,7 +274,7 @@ TEST(open_file, write_with_incomplete_download) {
|
|||||||
test_state();
|
test_state();
|
||||||
|
|
||||||
o.close();
|
o.close();
|
||||||
nf->close();
|
nf.close();
|
||||||
|
|
||||||
test_state();
|
test_state();
|
||||||
|
|
||||||
|
@ -401,9 +401,8 @@ TEST(ring_buffer_open_file, read_full_file_in_reverse) {
|
|||||||
EXPECT_FALSE(stop_requested);
|
EXPECT_FALSE(stop_requested);
|
||||||
std::size_t bytes_read{};
|
std::size_t bytes_read{};
|
||||||
data.resize(size);
|
data.resize(size);
|
||||||
auto ret = nf.read_bytes(data, offset, &bytes_read)
|
auto ret = nf.read(data, offset, &bytes_read) ? api_error::success
|
||||||
? api_error::success
|
: api_error::os_error;
|
||||||
: api_error::os_error;
|
|
||||||
EXPECT_EQ(bytes_read, data.size());
|
EXPECT_EQ(bytes_read, data.size());
|
||||||
return ret;
|
return ret;
|
||||||
});
|
});
|
||||||
@ -461,9 +460,8 @@ TEST(ring_buffer_open_file, read_full_file_in_partial_chunks) {
|
|||||||
EXPECT_FALSE(stop_requested);
|
EXPECT_FALSE(stop_requested);
|
||||||
std::size_t bytes_read{};
|
std::size_t bytes_read{};
|
||||||
data.resize(size);
|
data.resize(size);
|
||||||
auto ret = nf.read_bytes(data, offset, &bytes_read)
|
auto ret = nf.read(data, offset, &bytes_read) ? api_error::success
|
||||||
? api_error::success
|
: api_error::os_error;
|
||||||
: api_error::os_error;
|
|
||||||
EXPECT_EQ(bytes_read, data.size());
|
EXPECT_EQ(bytes_read, data.size());
|
||||||
return ret;
|
return ret;
|
||||||
});
|
});
|
||||||
@ -471,8 +469,8 @@ TEST(ring_buffer_open_file, read_full_file_in_partial_chunks) {
|
|||||||
file_manager::ring_buffer_open_file rb(ring_buffer_dir, test_chunk_size,
|
file_manager::ring_buffer_open_file rb(ring_buffer_dir, test_chunk_size,
|
||||||
30U, fsi, mp, 8u);
|
30U, fsi, mp, 8u);
|
||||||
|
|
||||||
auto nf2 =
|
auto nf2 = utils::file::file::open_or_create_file(dest_path);
|
||||||
utils::file::file::open_or_create_file(dest_path) : EXPECT_TRUE(nf2);
|
EXPECT_TRUE(nf2);
|
||||||
|
|
||||||
auto total_read = std::uint64_t(0u);
|
auto total_read = std::uint64_t(0u);
|
||||||
|
|
||||||
@ -481,7 +479,7 @@ TEST(ring_buffer_open_file, read_full_file_in_partial_chunks) {
|
|||||||
EXPECT_EQ(api_error::success, rb.read(3u, total_read, data));
|
EXPECT_EQ(api_error::success, rb.read(3u, total_read, data));
|
||||||
|
|
||||||
std::size_t bytes_written{};
|
std::size_t bytes_written{};
|
||||||
EXPECT_TRUE(nf2.write_bytes(data, total_read, &bytes_written));
|
EXPECT_TRUE(nf2.write(data, total_read, &bytes_written));
|
||||||
total_read += data.size();
|
total_read += data.size();
|
||||||
}
|
}
|
||||||
nf2.close();
|
nf2.close();
|
||||||
@ -495,9 +493,8 @@ TEST(ring_buffer_open_file, read_full_file_in_partial_chunks) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
TEST(ring_buffer_open_file, read_full_file_in_partial_chunks_in_reverse) {
|
TEST(ring_buffer_open_file, read_full_file_in_partial_chunks_in_reverse) {
|
||||||
const auto download_source_path =
|
auto nf = test::create_random_file(test_chunk_size * 32u);
|
||||||
test::generate_test_file_name("ring_buffer_open_file");
|
const auto download_source_path = nf.get_path().string();
|
||||||
auto nf = create_random_file(download_source_path, test_chunk_size * 32u);
|
|
||||||
|
|
||||||
const auto dest_path = test::generate_test_file_name("ring_buffer_open_file");
|
const auto dest_path = test::generate_test_file_name("ring_buffer_open_file");
|
||||||
|
|
||||||
@ -529,10 +526,10 @@ TEST(ring_buffer_open_file, read_full_file_in_partial_chunks_in_reverse) {
|
|||||||
30U, fsi, mp, 8u);
|
30U, fsi, mp, 8u);
|
||||||
|
|
||||||
auto nf2 = utils::file::file::open_or_create_file(dest_path);
|
auto nf2 = utils::file::file::open_or_create_file(dest_path);
|
||||||
EXPERT_TRUE(nf2);
|
EXPECT_TRUE(nf2);
|
||||||
|
|
||||||
auto total_read = std::uint64_t(0u);
|
std::uint64_t total_read{0U};
|
||||||
const auto read_size = 3u;
|
const auto read_size{3U};
|
||||||
|
|
||||||
while (total_read < fsi.size) {
|
while (total_read < fsi.size) {
|
||||||
const auto offset = fsi.size - total_read - read_size;
|
const auto offset = fsi.size - total_read - read_size;
|
||||||
|
@ -934,7 +934,7 @@ TEST(remote_fuse, all_tests) {
|
|||||||
|
|
||||||
event_system::instance().start();
|
event_system::instance().start();
|
||||||
#if defined(_WIN32)
|
#if defined(_WIN32)
|
||||||
mount_location_ = std::string(test::get_test_output_dir(), 2);
|
mount_location_ = test::get_test_output_dir().substr(0, 2);
|
||||||
mock_winfsp_drive drive(mount_location_);
|
mock_winfsp_drive drive(mount_location_);
|
||||||
remote_server server(config, drive, mount_location_);
|
remote_server server(config, drive, mount_location_);
|
||||||
#else
|
#else
|
||||||
|
@ -53,8 +53,8 @@ static void can_delete_test(remote_client &client) {
|
|||||||
EXPECT_TRUE(nf);
|
EXPECT_TRUE(nf);
|
||||||
if (nf) {
|
if (nf) {
|
||||||
EXPECT_EQ(STATUS_INVALID_HANDLE,
|
EXPECT_EQ(STATUS_INVALID_HANDLE,
|
||||||
client.winfsp_can_delete(
|
client.winfsp_can_delete(reinterpret_cast<PVOID>(nf.get_handle()),
|
||||||
reinterpret_cast<PVOID>(nf.get_handle()), api_path.c_str());
|
api_path.data()));
|
||||||
|
|
||||||
nf.close();
|
nf.close();
|
||||||
EXPECT_TRUE(utils::file::retry_delete_file(test_file));
|
EXPECT_TRUE(utils::file::retry_delete_file(test_file));
|
||||||
@ -491,7 +491,6 @@ TEST(remote_winfsp, all_tests) {
|
|||||||
EXPECT_TRUE(found_port);
|
EXPECT_TRUE(found_port);
|
||||||
if (found_port) {
|
if (found_port) {
|
||||||
console_consumer c;
|
console_consumer c;
|
||||||
|
|
||||||
app_config config(provider_type::remote, win_remote_dir);
|
app_config config(provider_type::remote, win_remote_dir);
|
||||||
config.set_remote_host_name_or_ip("localhost");
|
config.set_remote_host_name_or_ip("localhost");
|
||||||
config.set_remote_port(port);
|
config.set_remote_port(port);
|
||||||
@ -501,7 +500,7 @@ TEST(remote_winfsp, all_tests) {
|
|||||||
|
|
||||||
event_system::instance().start();
|
event_system::instance().start();
|
||||||
#if defined(_WIN32)
|
#if defined(_WIN32)
|
||||||
mount_location_ = std::string(test::get_test_output_dir(), 2);
|
mount_location_ = test::get_test_output_dir().substr(0, 2);
|
||||||
mock_winfsp_drive drive(mount_location_);
|
mock_winfsp_drive drive(mount_location_);
|
||||||
remote_server server(config, drive, mount_location_);
|
remote_server server(config, drive, mount_location_);
|
||||||
#else
|
#else
|
||||||
|
@ -27,12 +27,16 @@
|
|||||||
namespace repertory::utils::file {
|
namespace repertory::utils::file {
|
||||||
class file final {
|
class file final {
|
||||||
public:
|
public:
|
||||||
|
[[nodiscard]] static auto attach_file(native_handle handle,
|
||||||
|
bool read_only = false) -> file;
|
||||||
|
|
||||||
[[nodiscard]] static auto open_file(std::filesystem::path path,
|
[[nodiscard]] static auto open_file(std::filesystem::path path,
|
||||||
bool read_only = false) -> file;
|
bool read_only = false) -> file;
|
||||||
|
|
||||||
[[nodiscard]] static auto open_or_create_file(std::filesystem::path path,
|
[[nodiscard]] static auto open_or_create_file(std::filesystem::path path,
|
||||||
bool read_only = false) -> file;
|
bool read_only = false) -> file;
|
||||||
|
|
||||||
|
public:
|
||||||
file() noexcept = default;
|
file() noexcept = default;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
@ -102,31 +106,14 @@ public:
|
|||||||
[[nodiscard]] auto truncate(std::size_t size) -> bool;
|
[[nodiscard]] auto truncate(std::size_t size) -> bool;
|
||||||
|
|
||||||
[[nodiscard]] auto write(const data_buffer &data, std::uint64_t offset,
|
[[nodiscard]] auto write(const data_buffer &data, std::uint64_t offset,
|
||||||
std::size_t *total_written = nullptr) -> bool {
|
std::size_t *total_written = nullptr) -> bool;
|
||||||
return write_(reinterpret_cast<const unsigned char *>(data.data()),
|
|
||||||
data.size() * sizeof(data_buffer::value_type), offset,
|
|
||||||
total_written);
|
|
||||||
}
|
|
||||||
|
|
||||||
[[nodiscard]] auto write(std::string_view data, std::uint64_t offset,
|
[[nodiscard]] auto write(const unsigned char *data, std::size_t to_write,
|
||||||
std::size_t *total_written = nullptr) -> bool {
|
std::size_t offset,
|
||||||
return write_(reinterpret_cast<const unsigned char *>(data.data()),
|
std::size_t *total_written = nullptr) -> bool;
|
||||||
data.size(), offset, total_written);
|
|
||||||
}
|
|
||||||
|
|
||||||
[[nodiscard]] auto write(std::wstring_view data, std::uint64_t offset,
|
|
||||||
std::size_t *total_written = nullptr) -> bool {
|
|
||||||
return write_(reinterpret_cast<const unsigned char *>(data.data()),
|
|
||||||
data.size() * sizeof(wchar_t), offset, total_written);
|
|
||||||
}
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
[[nodiscard]] operator bool() const { return file_ != nullptr; }
|
[[nodiscard]] operator bool() const { return file_ != nullptr; }
|
||||||
|
|
||||||
private:
|
|
||||||
[[nodiscard]] auto write_(const unsigned char *data, std::size_t to_write,
|
|
||||||
std::size_t offset,
|
|
||||||
std::size_t *total_written) -> bool;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
[[nodiscard]] auto get_file_size(std::string_view path,
|
[[nodiscard]] auto get_file_size(std::string_view path,
|
||||||
|
@ -157,7 +157,9 @@ auto write_json_file(std::string_view path,
|
|||||||
}
|
}
|
||||||
#endif // defined(PROJECT_ENABLE_LIBSODIUM) && defined(PROJECT_ENABLE_BOOST)
|
#endif // defined(PROJECT_ENABLE_LIBSODIUM) && defined(PROJECT_ENABLE_BOOST)
|
||||||
|
|
||||||
return file.write(data.dump(), 0U);
|
auto json_str = data.dump();
|
||||||
|
return file.write(reinterpret_cast<const unsigned char *>(json_str.c_str()),
|
||||||
|
json_str.size(), 0U);
|
||||||
} catch (const std::exception &e) {
|
} catch (const std::exception &e) {
|
||||||
utils::error::handle_exception(function_name, e);
|
utils::error::handle_exception(function_name, e);
|
||||||
} catch (...) {
|
} catch (...) {
|
||||||
|
@ -27,32 +27,92 @@
|
|||||||
#include "utils/string.hpp"
|
#include "utils/string.hpp"
|
||||||
|
|
||||||
namespace repertory::utils::file {
|
namespace repertory::utils::file {
|
||||||
auto file::open_file(std::filesystem::path path, bool read_only) -> file {
|
auto file::attach_file(native_handle handle, bool read_only) -> file {
|
||||||
path = utils::path::absolute(path.string());
|
static constexpr const std::string_view function_name{
|
||||||
if (not is_file(path.string())) {
|
static_cast<const char *>(__FUNCTION__),
|
||||||
throw std::runtime_error("file not found: " + path.string());
|
|
||||||
}
|
|
||||||
|
|
||||||
if (not read_only) {
|
|
||||||
#if defined(_WIN32)
|
|
||||||
_chmod(path.string().c_str(), 0600U);
|
|
||||||
#else // !defined(_WIN32)
|
|
||||||
chmod(path.string().c_str(), 0600U);
|
|
||||||
#endif // defined(_WIN32)
|
|
||||||
}
|
|
||||||
|
|
||||||
#if defined(_WIN32)
|
|
||||||
auto *ptr =
|
|
||||||
_fsopen(path.string().c_str(), read_only ? "rb" : "rb+", _SH_DENYNO);
|
|
||||||
std::cout << errno << std::endl;
|
|
||||||
#else // !defined(_WIN32)
|
|
||||||
auto *ptr = fopen(path.string().c_str(), read_only ? "rb" : "rb+");
|
|
||||||
#endif // defined(_WIN32)
|
|
||||||
|
|
||||||
return file{
|
|
||||||
file_t{ptr},
|
|
||||||
path,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
try {
|
||||||
|
std::string path;
|
||||||
|
|
||||||
|
#if defined(_WIN32)
|
||||||
|
path.resize(MAX_PATH + 1);
|
||||||
|
|
||||||
|
::GetFinalPathNameByHandleA(handle, path.data(),
|
||||||
|
static_cast<DWORD>(path.size()),
|
||||||
|
FILE_NAME_NORMALIZED | VOLUME_NAME_DOS);
|
||||||
|
#else // !defined(_WIN32)
|
||||||
|
source_path.resize(PATH_MAX + 1);
|
||||||
|
|
||||||
|
#if defined(__APPLE__)
|
||||||
|
fcntl(handle, F_GETPATH, source_path.data());
|
||||||
|
#else // !defined(__APPLE__)
|
||||||
|
readlink(("/proc/self/fd/" + std::to_string(handle)).c_str(),
|
||||||
|
source_path.data(), source_path.size());
|
||||||
|
#endif // defined(__APPLE__)
|
||||||
|
#endif // defined(_WIN32)
|
||||||
|
|
||||||
|
path = path.c_str();
|
||||||
|
|
||||||
|
#if defined(_WIN32)
|
||||||
|
auto *ptr = _fdopen(
|
||||||
|
static_cast<int>(_open_osfhandle(reinterpret_cast<intptr_t>(handle),
|
||||||
|
read_only ? _O_RDONLY : _O_RDWR)),
|
||||||
|
read_only ? "rb" : "rb+");
|
||||||
|
#else // !defined(_WIN32)
|
||||||
|
auto *ptr = fdopen(handle, read_only ? "rb" : "rb+");
|
||||||
|
#endif // defined(_WIN32)
|
||||||
|
|
||||||
|
return file{
|
||||||
|
file_t{ptr},
|
||||||
|
utils::path::absolute(path),
|
||||||
|
};
|
||||||
|
} catch (const std::exception &e) {
|
||||||
|
utils::error::handle_exception(function_name, e);
|
||||||
|
} catch (...) {
|
||||||
|
utils::error::handle_exception(function_name);
|
||||||
|
}
|
||||||
|
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
|
auto file::open_file(std::filesystem::path path, bool read_only) -> file {
|
||||||
|
static constexpr const std::string_view function_name{
|
||||||
|
static_cast<const char *>(__FUNCTION__),
|
||||||
|
};
|
||||||
|
|
||||||
|
try {
|
||||||
|
path = utils::path::absolute(path.string());
|
||||||
|
if (not is_file(path.string())) {
|
||||||
|
throw std::runtime_error("file not found: " + path.string());
|
||||||
|
}
|
||||||
|
|
||||||
|
if (not read_only) {
|
||||||
|
#if defined(_WIN32)
|
||||||
|
_chmod(path.string().c_str(), 0600U);
|
||||||
|
#else // !defined(_WIN32)
|
||||||
|
chmod(path.string().c_str(), 0600U);
|
||||||
|
#endif // defined(_WIN32)
|
||||||
|
}
|
||||||
|
|
||||||
|
#if defined(_WIN32)
|
||||||
|
auto *ptr =
|
||||||
|
_fsopen(path.string().c_str(), read_only ? "rb" : "rb+", _SH_DENYNO);
|
||||||
|
#else // !defined(_WIN32)
|
||||||
|
auto *ptr = fopen(path.string().c_str(), read_only ? "rb" : "rb+");
|
||||||
|
#endif // defined(_WIN32)
|
||||||
|
|
||||||
|
return file{
|
||||||
|
file_t{ptr},
|
||||||
|
path,
|
||||||
|
};
|
||||||
|
} catch (const std::exception &e) {
|
||||||
|
utils::error::handle_exception(function_name, e);
|
||||||
|
} catch (...) {
|
||||||
|
utils::error::handle_exception(function_name);
|
||||||
|
}
|
||||||
|
|
||||||
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
auto file::open_or_create_file(std::filesystem::path path,
|
auto file::open_or_create_file(std::filesystem::path path,
|
||||||
@ -274,8 +334,8 @@ auto file::truncate(std::size_t size) -> bool {
|
|||||||
return ec.value() == 0;
|
return ec.value() == 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto file::write_(const unsigned char *data, std::size_t to_write,
|
auto 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 {
|
||||||
#if defined(_WIN32)
|
#if defined(_WIN32)
|
||||||
recur_mutex_lock lock{mtx_};
|
recur_mutex_lock lock{mtx_};
|
||||||
#endif // defined(_WIN32)
|
#endif // defined(_WIN32)
|
||||||
@ -350,4 +410,11 @@ auto file::size() const -> std::uint64_t {
|
|||||||
|
|
||||||
return 0U;
|
return 0U;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
auto file::write(const data_buffer &data, std::uint64_t offset,
|
||||||
|
std::size_t *total_written) -> bool {
|
||||||
|
return write(reinterpret_cast<const unsigned char *>(data.data()),
|
||||||
|
data.size() * sizeof(data_buffer::value_type), offset,
|
||||||
|
total_written);
|
||||||
|
}
|
||||||
} // namespace repertory::utils::file
|
} // namespace repertory::utils::file
|
||||||
|
@ -24,7 +24,7 @@
|
|||||||
|
|
||||||
#if defined(U)
|
#if defined(U)
|
||||||
#undef U
|
#undef U
|
||||||
#endif // defined(U)
|
#endif // defined(U)
|
||||||
|
|
||||||
#include "gmock/gmock.h"
|
#include "gmock/gmock.h"
|
||||||
#include "gtest/gtest.h"
|
#include "gtest/gtest.h"
|
||||||
@ -34,21 +34,23 @@ using namespace ::testing;
|
|||||||
|
|
||||||
#define COMMA ,
|
#define COMMA ,
|
||||||
|
|
||||||
#include "utils/config.hpp"
|
|
||||||
|
|
||||||
#include "utils/all.hpp"
|
#include "utils/all.hpp"
|
||||||
|
|
||||||
namespace repertory::test {
|
namespace repertory::test {
|
||||||
|
#if defined(PROJECT_ENABLE_LIBSODIUM)
|
||||||
[[nodiscard]] auto create_random_file(std::size_t size) -> utils::file::file;
|
[[nodiscard]] auto create_random_file(std::size_t size) -> utils::file::file;
|
||||||
|
#endif // defined(PROJECT_ENABLE_LIBSODIUM)
|
||||||
|
|
||||||
[[nodiscard]] auto
|
[[nodiscard]] auto
|
||||||
generate_test_file_name(std::string_view file_name_no_extension) -> std::string;
|
generate_test_file_name(std::string_view file_name_no_extension) -> std::string;
|
||||||
|
|
||||||
|
#if defined(PROJECT_ENABLE_LIBSODIUM) && defined(PROJECT_ENABLE_BOOST)
|
||||||
template <typename buffer_t, typename result_t>
|
template <typename buffer_t, typename result_t>
|
||||||
static void decrypt_and_verify(const buffer_t &buffer, std::string_view token,
|
static void decrypt_and_verify(const buffer_t &buffer, std::string_view token,
|
||||||
result_t &result) {
|
result_t &result) {
|
||||||
EXPECT_TRUE(utils::encryption::decrypt_data(token, buffer, result));
|
EXPECT_TRUE(utils::encryption::decrypt_data(token, buffer, result));
|
||||||
}
|
}
|
||||||
|
#endif // defined(PROJECT_ENABLE_LIBSODIUM) && defined(PROJECT_ENABLE_BOOST)
|
||||||
|
|
||||||
[[nodiscard]] auto get_test_input_dir() -> std::string;
|
[[nodiscard]] auto get_test_input_dir() -> std::string;
|
||||||
|
|
||||||
|
@ -53,6 +53,7 @@ static auto deleter{std::make_unique<file_deleter>()};
|
|||||||
} // namespace
|
} // namespace
|
||||||
|
|
||||||
namespace repertory::test {
|
namespace repertory::test {
|
||||||
|
#if defined(PROJECT_ENABLE_LIBSODIUM)
|
||||||
auto create_random_file(std::size_t size) -> utils::file::file {
|
auto create_random_file(std::size_t size) -> utils::file::file {
|
||||||
recur_mutex_lock lock{file_mtx};
|
recur_mutex_lock lock{file_mtx};
|
||||||
|
|
||||||
@ -74,6 +75,7 @@ auto create_random_file(std::size_t size) -> utils::file::file {
|
|||||||
|
|
||||||
return file;
|
return file;
|
||||||
}
|
}
|
||||||
|
#endif // defined(PROJECT_ENABLE_LIBSODIUM)
|
||||||
|
|
||||||
auto generate_test_file_name(std::string_view file_name_no_extension)
|
auto generate_test_file_name(std::string_view file_name_no_extension)
|
||||||
-> std::string {
|
-> std::string {
|
||||||
|
Reference in New Issue
Block a user