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/repertory.hpp"
|
||||
#include "utils/common.hpp"
|
||||
#include "utils/file.hpp"
|
||||
#include "utils/file_utils.hpp"
|
||||
#include "utils/native_file.hpp"
|
||||
#include "utils/path.hpp"
|
||||
#include "utils/time.hpp"
|
||||
|
||||
@ -472,21 +472,20 @@ auto remote_server::fuse_read(
|
||||
if (os_handle != INVALID_HANDLE_VALUE) {
|
||||
errno = EFAULT;
|
||||
|
||||
auto file = native_file::attach(os_handle);
|
||||
std::uint64_t file_size{};
|
||||
if (file->get_file_size(file_size)) {
|
||||
auto file = utils::file::file::attach_file(os_handle, true);
|
||||
if (file) {
|
||||
auto file_size = file.size();
|
||||
data.resize(utils::calculate_read_size(
|
||||
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{};
|
||||
if (file->read_bytes(data.data(), data.size(), read_offset,
|
||||
bytes_read)) {
|
||||
if (file.read(data.data(), data.size(), read_offset, &bytes_read)) {
|
||||
res = 0;
|
||||
errno = 0;
|
||||
}
|
||||
} else {
|
||||
res = 0;
|
||||
errno = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -539,10 +538,10 @@ auto remote_server::fuse_write(
|
||||
if (os_handle != INVALID_HANDLE_VALUE) {
|
||||
errno = EFAULT;
|
||||
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),
|
||||
static_cast<std::size_t>(write_size), write_offset,
|
||||
bytes_written)) {
|
||||
&bytes_written)) {
|
||||
res = 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 {
|
||||
class file final {
|
||||
public:
|
||||
[[nodiscard]] static auto attach_file(native_handle handle,
|
||||
bool read_only = false) -> file;
|
||||
|
||||
[[nodiscard]] static auto open_file(std::filesystem::path path,
|
||||
bool read_only = false) -> file;
|
||||
|
||||
@ -103,31 +106,14 @@ public:
|
||||
[[nodiscard]] auto truncate(std::size_t size) -> bool;
|
||||
|
||||
[[nodiscard]] auto write(const data_buffer &data, std::uint64_t offset,
|
||||
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);
|
||||
}
|
||||
std::size_t *total_written = nullptr) -> bool;
|
||||
|
||||
[[nodiscard]] auto write(std::string_view data, std::uint64_t offset,
|
||||
std::size_t *total_written = nullptr) -> bool {
|
||||
return write_(reinterpret_cast<const unsigned char *>(data.data()),
|
||||
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);
|
||||
}
|
||||
[[nodiscard]] auto write(const unsigned char *data, std::size_t to_write,
|
||||
std::size_t offset,
|
||||
std::size_t *total_written = nullptr) -> bool;
|
||||
|
||||
public:
|
||||
[[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,
|
||||
|
@ -157,7 +157,9 @@ auto write_json_file(std::string_view path,
|
||||
}
|
||||
#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) {
|
||||
utils::error::handle_exception(function_name, e);
|
||||
} catch (...) {
|
||||
|
@ -27,6 +27,55 @@
|
||||
#include "utils/string.hpp"
|
||||
|
||||
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 {
|
||||
static constexpr const std::string_view function_name{
|
||||
static_cast<const char *>(__FUNCTION__),
|
||||
@ -285,8 +334,8 @@ auto file::truncate(std::size_t size) -> bool {
|
||||
return ec.value() == 0;
|
||||
}
|
||||
|
||||
auto file::write_(const unsigned char *data, std::size_t to_write,
|
||||
std::size_t offset, std::size_t *total_written) -> bool {
|
||||
auto file::write(const unsigned char *data, std::size_t to_write,
|
||||
std::size_t offset, std::size_t *total_written) -> bool {
|
||||
#if defined(_WIN32)
|
||||
recur_mutex_lock lock{mtx_};
|
||||
#endif // defined(_WIN32)
|
||||
@ -361,4 +410,11 @@ auto file::size() const -> std::uint64_t {
|
||||
|
||||
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
|
||||
|
Reference in New Issue
Block a user