2 Commits

Author SHA1 Message Date
9f45a6ab81 refactor
Some checks failed
BlockStorage/repertory/pipeline/head There was a failure building this commit
2024-08-30 20:56:59 -05:00
cf16a1532a updated build system 2024-08-30 20:04:20 -05:00
9 changed files with 257 additions and 169 deletions

View File

@ -22,22 +22,13 @@
#ifndef INCLUDE_UTILS_FILE_UTILS_HPP_
#define INCLUDE_UTILS_FILE_UTILS_HPP_
#include "types/repertory.hpp"
#include "utils/file.hpp"
namespace repertory::utils::file {
void change_to_process_directory();
[[nodiscard]] auto
get_directory_files(std::string path, bool oldest_first,
get_directory_files(std::string_view path, bool oldest_first,
bool recursive = false) -> std::deque<std::string>;
[[nodiscard]] auto
get_free_drive_space(const std::string &path) -> std::uint64_t;
[[nodiscard]] auto
get_total_drive_space(const std::string &path) -> std::uint64_t;
[[nodiscard]] auto
read_file_lines(const std::string &path) -> std::vector<std::string>;

View File

@ -317,11 +317,12 @@ auto app_config::get_json() const -> json {
}
auto app_config::get_max_cache_size_bytes() const -> std::uint64_t {
const auto max_space =
auto max_space =
std::max(static_cast<std::uint64_t>(100ULL * 1024ULL * 1024ULL),
max_cache_size_bytes_);
return std::min(utils::file::get_free_drive_space(get_cache_directory()),
max_space);
auto free_space = utils::file::get_free_drive_space(get_cache_directory());
return free_space.has_value() ? std::min(free_space.value(), max_space)
: max_space;
}
auto app_config::get_provider_display_name(const provider_type &prov)

View File

@ -393,31 +393,34 @@ auto fuse_base::init_(struct fuse_conn_info *conn) -> void * {
#if FUSE_USE_VERSION >= 30
auto fuse_base::init_impl([[maybe_unused]] struct fuse_conn_info *conn,
struct fuse_config *cfg) -> void * {
#else
#else // FUSE_USE_VERSION < 30
auto fuse_base::init_impl(struct fuse_conn_info *conn) -> void * {
#endif
#endif // FUSE_USE_VERSION >= 30
static constexpr const std::string_view function_name{
static_cast<const char *>(__FUNCTION__),
};
utils::file::change_to_process_directory();
if (not console_enabled_) {
if (not repertory::project_initialize()) {
utils::error::raise_error(function_name,
"failed to initialize repertory");
event_system::instance().raise<unmount_requested>();
}
}
#if defined(__APPLE__)
conn->want |= FUSE_CAP_VOL_RENAME;
conn->want |= FUSE_CAP_XTIMES;
#endif // __APPLE__
#endif // defined(__APPLE__)
#if FUSE_USE_VERSION >= 30
cfg->nullpath_ok = 0;
cfg->hard_remove = 1;
#endif
#endif // FUSE_USE_VERSION >= 30
if (not utils::file::change_to_process_directory()) {
utils::error::raise_error(function_name,
"failed to change to process directory");
event_system::instance().raise<unmount_requested>();
return this;
}
if (not console_enabled_ && not repertory::project_initialize()) {
utils::error::raise_error(function_name, "failed to initialize repertory");
event_system::instance().raise<unmount_requested>();
}
return this;
}

View File

@ -623,7 +623,9 @@ auto winfsp_drive::Mounted(PVOID host) -> NTSTATUS {
};
auto ret = STATUS_SUCCESS;
utils::file::change_to_process_directory();
if (not utils::file::change_to_process_directory()) {
return utils::get_last_error_code();
}
auto *file_system_host = reinterpret_cast<FileSystemHost *>(host);
polling::instance().start(&config_);

View File

@ -628,8 +628,9 @@ auto encrypt_provider::get_item_meta(const std::string &api_path,
}
auto encrypt_provider::get_total_drive_space() const -> std::uint64_t {
const auto cfg = config_.get_encrypt_config();
return utils::file::get_total_drive_space(cfg.path);
auto total_space =
utils::file::get_total_drive_space(config_.get_encrypt_config().path);
return total_space.value_or(0U);
}
auto encrypt_provider::get_total_item_count() const -> std::uint64_t {
@ -646,8 +647,10 @@ auto encrypt_provider::get_total_item_count() const -> std::uint64_t {
}
auto encrypt_provider::get_used_drive_space() const -> std::uint64_t {
const auto cfg = config_.get_encrypt_config();
return get_total_drive_space() - utils::file::get_free_drive_space(cfg.path);
auto free_space =
utils::file::get_free_drive_space(config_.get_encrypt_config().path);
return free_space.has_value() ? get_total_drive_space() - free_space.value()
: 0U;
}
auto encrypt_provider::is_directory(const std::string &api_path,

View File

@ -31,121 +31,70 @@
#include "utils/utils.hpp"
namespace repertory::utils::file {
void change_to_process_directory() {
#if defined(_WIN32)
std::string file_name;
file_name.resize(MAX_PATH);
::GetModuleFileNameA(nullptr, &file_name[0U],
static_cast<DWORD>(file_name.size()));
std::string path = file_name.c_str();
::PathRemoveFileSpecA(&path[0U]);
::SetCurrentDirectoryA(&path[0U]);
#else
std::string path;
path.resize(PATH_MAX + 1);
#if defined(__APPLE__)
proc_pidpath(getpid(), &path[0U], path.size());
#else
readlink("/proc/self/exe", &path[0U], path.size());
#endif
path = utils::path::get_parent_path(path);
chdir(path.c_str());
#endif
}
auto get_free_drive_space(const std::string &path) -> std::uint64_t {
#if defined(_WIN32)
ULARGE_INTEGER li{};
::GetDiskFreeSpaceEx(path.c_str(), &li, nullptr, nullptr);
return li.QuadPart;
#endif
#if defined(__linux__)
std::uint64_t ret = 0;
struct statfs64 st {};
if (statfs64(path.c_str(), &st) == 0) {
ret = st.f_bfree * st.f_bsize;
}
return ret;
#endif
#if defined(__APPLE__)
struct statvfs st {};
statvfs(path.c_str(), &st);
return st.f_bfree * st.f_frsize;
#endif
}
auto get_total_drive_space(const std::string &path) -> std::uint64_t {
#if defined(_WIN32)
ULARGE_INTEGER li{};
::GetDiskFreeSpaceEx(path.c_str(), nullptr, &li, nullptr);
return li.QuadPart;
#endif
#if defined(__linux__)
std::uint64_t ret = 0;
struct statfs64 st {};
if (statfs64(path.c_str(), &st) == 0) {
ret = st.f_blocks * st.f_bsize;
}
return ret;
#endif
#if defined(__APPLE__)
struct statvfs st {};
statvfs(path.c_str(), &st);
return st.f_blocks * st.f_frsize;
#endif
}
auto get_directory_files(std::string path, bool oldest_first,
auto get_directory_files(std::string_view path, bool oldest_first,
bool recursive) -> std::deque<std::string> {
path = utils::path::absolute(path);
static constexpr const std::string_view function_name{
static_cast<const char *>(__FUNCTION__),
};
auto abs_path = utils::path::absolute(path);
std::deque<std::string> ret;
std::unordered_map<std::string, std::uint64_t> lookup;
#if defined(_WIN32)
WIN32_FIND_DATA fd{};
const auto search = utils::path::combine(path, {"*.*"});
auto search = utils::path::combine(abs_path, {"*.*"});
auto find = ::FindFirstFile(search.c_str(), &fd);
if (find != INVALID_HANDLE_VALUE) {
do {
const auto full_path = utils::path::combine(path, {fd.cFileName});
if ((fd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) ==
FILE_ATTRIBUTE_DIRECTORY) {
if (recursive) {
const auto sub_files =
get_directory_files(full_path, oldest_first, recursive);
ret.insert(ret.end(), sub_files.begin(), sub_files.end());
} else {
ULARGE_INTEGER li{};
li.HighPart = fd.ftLastWriteTime.dwHighDateTime;
li.LowPart = fd.ftLastWriteTime.dwLowDateTime;
lookup[full_path] = li.QuadPart;
ret.emplace_back(full_path);
try {
do {
auto full_path = utils::path::combine(abs_path, {fd.cFileName});
if ((fd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) ==
FILE_ATTRIBUTE_DIRECTORY) {
if (recursive) {
auto sub_files =
get_directory_files(full_path, oldest_first, recursive);
ret.insert(ret.end(), sub_files.begin(), sub_files.end());
} else {
ULARGE_INTEGER li{};
li.HighPart = fd.ftLastWriteTime.dwHighDateTime;
li.LowPart = fd.ftLastWriteTime.dwLowDateTime;
lookup[full_path] = li.QuadPart;
ret.emplace_back(full_path);
}
}
}
} while (::FindNextFile(find, &fd) != 0);
} while (::FindNextFile(find, &fd) != 0);
} catch (const std::exception &e) {
utils::error::raise_error(function_name, e,
"failed to get directory files");
}
::FindClose(find);
std::sort(ret.begin(), ret.end(),
[&](const auto &p1, const auto &p2) -> bool {
return (oldest_first != 0) == (lookup[p1] < lookup[p2]);
});
std::sort(ret.begin(), ret.end(), [&](auto &&path1, auto &&path2) -> bool {
return (oldest_first != 0) == (lookup[path1] < lookup[path2]);
});
}
#else
auto *root = opendir(path.c_str());
#else // !defined(_WIN32)
auto *root = opendir(abs_path.c_str());
if (root) {
struct dirent *de{};
while ((de = readdir(root)) != nullptr) {
if (de->d_type == DT_DIR) {
if (recursive) {
const auto sub_files =
get_directory_files(utils::path::combine(path, {de->d_name}),
oldest_first, recursive);
ret.insert(ret.end(), sub_files.begin(), sub_files.end());
try {
struct dirent *de{};
while ((de = readdir(root)) != nullptr) {
if (de->d_type == DT_DIR) {
if (recursive) {
auto sub_files = get_directory_files(
utils::path::combine(abs_path, {de->d_name}), oldest_first,
recursive);
ret.insert(ret.end(), sub_files.begin(), sub_files.end());
}
} else {
ret.emplace_back(utils::path::combine(abs_path, {de->d_name}));
}
} else {
ret.emplace_back(utils::path::combine(path, {de->d_name}));
}
} catch (const std::exception &e) {
utils::error::raise_error(function_name, e,
"failed to get directory files");
}
closedir(root);
const auto add_to_lookup = [&](const std::string &lookup_path) {
@ -153,25 +102,26 @@ auto get_directory_files(std::string path, bool oldest_first,
struct stat st {};
stat(lookup_path.c_str(), &st);
#if defined(__APPLE__)
lookup[lookup_path] = static_cast<std::uint64_t>(
(st.st_mtimespec.tv_sec * utils::time::NANOS_PER_SECOND) +
st.st_mtimespec.tv_nsec);
lookup[lookup_path] =
(static_cast<std::uint64_t>(st.st_mtimespec.tv_sec) *
utils::time::NANOS_PER_SECOND) +
static_cast<std::uint64_t>(st.st_mtimespec.tv_nsec);
#else // !defined(__APPLE__)
lookup[lookup_path] = static_cast<std::uint64_t>(
(st.st_mtim.tv_sec * utils::time::NANOS_PER_SECOND) +
st.st_mtim.tv_nsec);
lookup[lookup_path] = (static_cast<std::uint64_t>(st.st_mtim.tv_sec) *
utils::time::NANOS_PER_SECOND) +
static_cast<std::uint64_t>(st.st_mtim.tv_nsec);
#endif // defined(__APPLE__)
}
};
std::sort(ret.begin(), ret.end(),
[&](const auto &p1, const auto &p2) -> bool {
add_to_lookup(p1);
add_to_lookup(p2);
return (oldest_first != 0) == (lookup[p1] < lookup[p2]);
});
std::sort(ret.begin(), ret.end(), [&](auto &&path1, auto &&path2) -> bool {
add_to_lookup(path1);
add_to_lookup(path2);
return (oldest_first != 0) == (lookup.at(path1) < lookup.at(path2));
});
}
#endif
#endif // defined(_WIN32)
return ret;
}
@ -190,7 +140,7 @@ auto read_file_lines(const std::string &path) -> std::vector<std::string> {
}
auto reset_modified_time(const std::string &path) -> bool {
auto ret = false;
auto ret{false};
#if defined(_WIN32)
SYSTEMTIME st{};
::GetSystemTime(&st);
@ -206,13 +156,14 @@ auto reset_modified_time(const std::string &path) -> bool {
::CloseHandle(handle);
}
}
#else
#else // !defined(_WIN32)
auto fd = open(path.c_str(), O_RDWR);
if ((ret = (fd != -1))) {
ret = not futimens(fd, nullptr);
ret = futimens(fd, nullptr) == 0;
close(fd);
}
#endif
#endif // defined(_WIN32)
return ret;
}
} // namespace repertory::utils::file

View File

@ -56,6 +56,8 @@ struct file_times final {
}
};
[[nodiscard]] auto change_to_process_directory() -> bool;
[[nodiscard]] inline auto
directory_exists_in_path(std::string_view path,
std::string_view sub_directory) -> bool;
@ -71,6 +73,9 @@ file_exists_in_path(std::string_view path, std::string_view file_name) -> bool;
file_exists_in_path(std::wstring_view path,
std::wstring_view file_name) -> bool;
[[nodiscard]] auto
get_free_drive_space(std::string_view path) -> std::optional<std::uint64_t>;
[[nodiscard]] auto get_time(std::string_view path,
time_type type) -> std::optional<std::uint64_t>;
@ -83,6 +88,9 @@ get_times(std::string_view path) -> std::optional<file_times>;
[[nodiscard]] auto
get_times(std::wstring_view path) -> std::optional<file_times>;
[[nodiscard]] auto
get_total_drive_space(std::string_view path) -> std::optional<std::uint64_t>;
#if defined(PROJECT_ENABLE_LIBDSM)
[[nodiscard]] auto
smb_create_and_validate_relative_path(std::string_view smb_path,

View File

@ -26,9 +26,102 @@
#include "utils/path.hpp"
#include "utils/string.hpp"
#include "utils/time.hpp"
#include "utils/unix.hpp"
#include "utils/windows.hpp"
namespace repertory::utils::file {
auto change_to_process_directory() -> bool {
static constexpr const std::string_view function_name{
static_cast<const char *>(__FUNCTION__),
};
try {
#if defined(_WIN32)
std::string file_name;
file_name.resize(MAX_PATH + 1U);
::GetModuleFileNameA(nullptr, file_name.data(),
static_cast<DWORD>(file_name.size() - 1U));
auto path = utils::path::strip_to_file_name(file_name.c_str());
::SetCurrentDirectoryA(path.c_str());
#else // !defined(_WIN32)
std::string path;
path.resize(PATH_MAX + 1);
#if defined(__APPLE__)
proc_pidpath(getpid(), path.c_str(), path.size());
#else // !defined(__APPLE__)
auto res = readlink("/proc/self/exe", path.data(), path.size());
if (res == -1) {
throw std::runtime_error("failed to readlink|" + path + '|' +
std::to_string(errno));
}
#endif // defined(__APPLE__)
path = utils::path::get_parent_path(path);
res = chdir(path.c_str());
if (res != 0) {
throw std::runtime_error("failed to chdir|" + path + '|' +
std::to_string(errno));
}
#endif // defined(_WIN32)
return true;
} catch (const std::exception &e) {
utils::error::handle_exception(function_name, e);
} catch (...) {
utils::error::handle_exception(function_name);
}
return false;
}
auto get_free_drive_space(std::string_view path)
-> std::optional<std::uint64_t> {
static constexpr const std::string_view function_name{
static_cast<const char *>(__FUNCTION__),
};
try {
#if defined(_WIN32)
ULARGE_INTEGER li{};
if (not ::GetDiskFreeSpaceEx(path.c_str(), &li, nullptr, nullptr)) {
throw std::runtime_error("failed to get free disk space|" +
std::string{path} + '|' +
std::to_string(utils::get_last_error_code()));
}
return li.QuadPart;
#endif // defined(_WIN32)
#if defined(__linux__)
struct statfs64 st {};
if (statfs64(std::string{path}.c_str(), &st) != 0) {
throw std::runtime_error("failed to get free disk space|" +
std::string{path} + '|' +
std::to_string(utils::get_last_error_code()));
}
return st.f_bfree * static_cast<std::uint64_t>(st.f_bsize);
#endif // defined(__linux__)
#if defined(__APPLE__)
struct statvfs st {};
if (statvfs(path.c_str(), &st) != 0) {
throw std::runtime_error("failed to get free disk space|" +
std::string{path} + '|' +
std::to_string(utils::get_last_error_code()));
}
return st.f_bfree * static_cast<std::uint64_t>(st.f_frsize);
#endif // defined(__APPLE__)
} catch (const std::exception &e) {
utils::error::handle_exception(function_name, e);
} catch (...) {
utils::error::handle_exception(function_name);
}
return std::nullopt;
}
auto get_time(std::string_view path,
time_type type) -> std::optional<std::uint64_t> {
auto times = get_times(path);
@ -50,6 +143,8 @@ auto get_times(std::string_view path) -> std::optional<file_times> {
};
try {
file_times ret{};
#if defined(_WIN32)
auto file_handle = ::CreateFileA(std::string{path}.c_str(), GENERIC_READ, 0,
nullptr, OPEN_EXISTING, 0, nullptr);
@ -69,46 +164,32 @@ auto get_times(std::string_view path) -> std::optional<file_times> {
'|' +
std::to_string(utils::get_last_error_code()));
}
ret.accessed = utils::time::windows_file_time_to_unix_time(times.at(1U));
ret.created = utils::time::windows_file_time_to_unix_time(times.at(0U));
ret.modified = utils::time::windows_file_time_to_unix_time(times.at(2U));
ret.written = utils::time::windows_file_time_to_unix_time(times.at(2U));
#else // !defined(_WIN32)
struct stat64 st {};
if (stat64(std::string{path}.c_str(), &st) != 0) {
throw std::runtime_error("failed to get file times|" + std::string{path} +
'|' + std::to_string(errno));
}
#endif // defined(_WIN32)
file_times ret{};
#if defined(_WIN32)
ret.accessed = utils::time::windows_file_time_to_unix_time(times.at(1U));
#else // !defined(_WIN32)
ret.accessed = static_cast<std::uint64_t>(st.st_atim.tv_nsec) +
static_cast<std::uint64_t>(st.st_atim.tv_sec) *
utils::time::NANOS_PER_SECOND;
#endif // defined(_WIN32)
#if defined(_WIN32)
ret.created = utils::time::windows_file_time_to_unix_time(times.at(0U));
#else // !defined(_WIN32)
ret.created = static_cast<std::uint64_t>(st.st_ctim.tv_nsec) +
static_cast<std::uint64_t>(st.st_ctim.tv_sec) *
utils::time::NANOS_PER_SECOND;
#endif // defined(_WIN32)
#if defined(_WIN32)
ret.modified = utils::time::windows_file_time_to_unix_time(times.at(2U));
#else // !defined(_WIN32)
ret.modified = static_cast<std::uint64_t>(st.st_mtim.tv_nsec) +
static_cast<std::uint64_t>(st.st_mtim.tv_sec) *
utils::time::NANOS_PER_SECOND;
#endif // defined(_WIN32)
#if defined(_WIN32)
ret.written = utils::time::windows_file_time_to_unix_time(times.at(2U));
#else // !defined(_WIN32)
ret.written = static_cast<std::uint64_t>(st.st_mtim.tv_nsec) +
static_cast<std::uint64_t>(st.st_mtim.tv_sec) *
utils::time::NANOS_PER_SECOND;
#endif // defined(_WIN32)
return ret;
} catch (const std::exception &e) {
utils::error::handle_exception(function_name, e);
@ -123,6 +204,53 @@ auto get_times(std::wstring_view path) -> std::optional<file_times> {
return get_times(utils::string::to_utf8(path));
}
auto get_total_drive_space(std::string_view path)
-> std::optional<std::uint64_t> {
static constexpr const std::string_view function_name{
static_cast<const char *>(__FUNCTION__),
};
try {
#if defined(_WIN32)
ULARGE_INTEGER li{};
if (not ::GetDiskFreeSpaceEx(path.c_str(), nullptr, &li, nullptr)) {
throw std::runtime_error("failed to get total disk space|" +
std::string{path} + '|' +
std::to_string(utils::get_last_error_code()));
}
return li.QuadPart;
#endif // defined(_WIN32)
#if defined(__linux__)
struct statfs64 st {};
if (statfs64(std::string{path}.c_str(), &st) != 0) {
throw std::runtime_error("failed to get total disk space|" +
std::string{path} + '|' +
std::to_string(utils::get_last_error_code()));
}
return st.f_blocks * static_cast<std::uint64_t>(st.f_bsize);
#endif // defined(__linux__)
#if defined(__APPLE__)
struct statvfs st {};
if (statvfs(path.c_str(), &st) != 0) {
throw std::runtime_error("failed to get total disk space|" +
std::string{path} + '|' +
std::to_string(utils::get_last_error_code()));
}
return st.f_blocks * static_cast<std::uint64_t>(st.f_frsize);
#endif // defined(__APPLE__)
} catch (const std::exception &e) {
utils::error::handle_exception(function_name, e);
} catch (...) {
utils::error::handle_exception(function_name);
}
return std::nullopt;
}
auto i_fs_item::get_time(time_type type) const -> std::optional<std::uint64_t> {
return utils::file::get_time(get_path(), type);
}

View File

@ -95,7 +95,8 @@ auto directory::copy_to(std::string_view new_path,
try {
throw std::runtime_error("failed to copy directory|" + path_ + '|' +
std::string{new_path} + "|not implemented");
std::string{new_path} + '+' +
std::to_string(overwrite) + "|not implemented");
} catch (const std::exception &e) {
utils::error::handle_exception(function_name, e);
} catch (...) {