updated build system and fixes
Some checks failed
BlockStorage/repertory/pipeline/head There was a failure building this commit
Some checks failed
BlockStorage/repertory/pipeline/head There was a failure building this commit
This commit is contained in:
@ -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
|
|
@ -27,6 +27,9 @@
|
|||||||
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;
|
||||||
|
|
||||||
@ -103,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,6 +27,55 @@
|
|||||||
#include "utils/string.hpp"
|
#include "utils/string.hpp"
|
||||||
|
|
||||||
namespace repertory::utils::file {
|
namespace repertory::utils::file {
|
||||||
|
auto file::attach_file(native_handle handle, bool read_only) -> file {
|
||||||
|
static constexpr const std::string_view function_name{
|
||||||
|
static_cast<const char *>(__FUNCTION__),
|
||||||
|
};
|
||||||
|
|
||||||
|
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 {
|
auto file::open_file(std::filesystem::path path, bool read_only) -> file {
|
||||||
static constexpr const std::string_view function_name{
|
static constexpr const std::string_view function_name{
|
||||||
static_cast<const char *>(__FUNCTION__),
|
static_cast<const char *>(__FUNCTION__),
|
||||||
@ -285,7 +334,7 @@ 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_};
|
||||||
@ -361,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
|
||||||
|
Reference in New Issue
Block a user