Compare commits
2 Commits
561cfd937a
...
9f45a6ab81
Author | SHA1 | Date | |
---|---|---|---|
9f45a6ab81 | |||
cf16a1532a |
@ -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>;
|
||||
|
||||
|
@ -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)
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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_);
|
||||
|
@ -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,
|
||||
|
@ -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
|
||||
|
@ -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,
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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 (...) {
|
||||
|
Reference in New Issue
Block a user