From cf6a370eea6f2461d9559018599e1a1ef992fb1b Mon Sep 17 00:00:00 2001 From: "Scott E. Graves" Date: Sat, 19 Oct 2024 15:58:51 -0500 Subject: [PATCH] updated build system --- support/src/utils/file.cpp | 1057 ++++++++++++++++++------------------ 1 file changed, 525 insertions(+), 532 deletions(-) diff --git a/support/src/utils/file.cpp b/support/src/utils/file.cpp index 425b7779..bc941413 100644 --- a/support/src/utils/file.cpp +++ b/support/src/utils/file.cpp @@ -121,109 +121,106 @@ auto get_free_drive_space(std::string_view path) }); return li.QuadPart; + } #endif // defined(_WIN32) #if defined(__linux__) - struct statfs64 st {}; - if (statfs64(std::string{path}.c_str(), &st) != 0) { - throw utils::error::create_exception({ - function_name, - "failed to get free disk space", - std::to_string(utils::get_last_error_code()), - path, - }); - } + struct statfs64 st {}; + if (statfs64(std::string{path}.c_str(), &st) != 0) { + throw utils::error::create_exception({ + function_name, + "failed to get free disk space", + std::to_string(utils::get_last_error_code()), + path, + }); + } - return st.f_bfree * static_cast(st.f_bsize); + return st.f_bfree * static_cast(st.f_bsize); #endif // defined(__linux__) #if defined(__APPLE__) - struct statvfs st {}; - if (statvfs(path.c_str(), &st) != 0) { - throw utils::error::create_exception({ - function_name, - "failed to get free disk space", - std::to_string(utils::get_last_error_code()), - path, - }); - } + struct statvfs st {}; + if (statvfs(path.c_str(), &st) != 0) { + throw utils::error::create_exception({ + function_name, + "failed to get free disk space", + std::to_string(utils::get_last_error_code()), + path, + }); + } - return st.f_bfree * static_cast(st.f_frsize); + return st.f_bfree * static_cast(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; + } catch (const std::exception &e) { + utils::error::handle_exception(function_name, e); + } catch (...) { + utils::error::handle_exception(function_name); } - auto get_free_drive_space( - std::wstring_view path) -> std::optional { - return get_free_drive_space(utils::string::to_utf8(path)); + return std::nullopt; +} + +auto get_free_drive_space(std::wstring_view path) + -> std::optional { + return get_free_drive_space(utils::string::to_utf8(path)); +} + +auto get_time(std::string_view path, + time_type type) -> std::optional { + auto times = get_times(path); + if (times.has_value()) { + return times->get(type); } - auto get_time(std::string_view path, - time_type type) -> std::optional { - auto times = get_times(path); - if (times.has_value()) { - return times->get(type); - } + return std::nullopt; +} - return std::nullopt; - } +auto get_time(std::wstring_view path, + time_type type) -> std::optional { + return get_time(utils::string::to_utf8(path), type); +} - auto get_time(std::wstring_view path, - time_type type) -> std::optional { - return get_time(utils::string::to_utf8(path), type); - } +auto get_times(std::string_view path) -> std::optional { + REPERTORY_USES_FUNCTION_NAME(); - auto get_times(std::string_view path) -> std::optional { - REPERTORY_USES_FUNCTION_NAME(); - - try { - file_times ret{}; + try { + file_times ret{}; #if defined(_WIN32) - auto file_handle = ::CreateFileA( - std::string{path}.c_str(), GENERIC_READ, - FILE_SHARE_DELETE | FILE_SHARE_READ | FILE_SHARE_WRITE, nullptr, - OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, nullptr); - if (file_handle != INVALID_HANDLE_VALUE) { - std::array times{}; - auto res = ::GetFileTime(file_handle, ×.at(0U), ×.at(1U), - ×.at(2U)); - ::CloseHandle(file_handle); - if (res) { - 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)); - return ret; - } + auto file_handle = ::CreateFileA( + std::string{path}.c_str(), GENERIC_READ, + FILE_SHARE_DELETE | FILE_SHARE_READ | FILE_SHARE_WRITE, nullptr, + OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, nullptr); + if (file_handle != INVALID_HANDLE_VALUE) { + std::array times{}; + auto res = ::GetFileTime(file_handle, ×.at(0U), ×.at(1U), + ×.at(2U)); + ::CloseHandle(file_handle); + if (res) { + 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)); + return ret; } + } - struct _stat64 st {}; - if (_stat64(std::string{path}.c_str(), &st) != 0) { - throw utils::error::create_exception({ - function_name, - "failed to get file times", - std::to_string(utils::get_last_error_code()), - path, - }); - } + struct _stat64 st {}; + if (_stat64(std::string{path}.c_str(), &st) != 0) { + throw utils::error::create_exception({ + function_name, + "failed to get file times", + std::to_string(utils::get_last_error_code()), + path, + }); + } - ret.accessed = utils::time::windows_time_t_to_unix_time(st.st_atime); - ret.created = utils::time::windows_time_t_to_unix_time(st.st_ctime); - ret.modified = utils::time::windows_time_t_to_unix_time(st.st_mtime); - ret.written = utils::time::windows_time_t_to_unix_time(st.st_mtime); + ret.accessed = utils::time::windows_time_t_to_unix_time(st.st_atime); + ret.created = utils::time::windows_time_t_to_unix_time(st.st_ctime); + ret.modified = utils::time::windows_time_t_to_unix_time(st.st_mtime); + ret.written = utils::time::windows_time_t_to_unix_time(st.st_mtime); #else // !defined(_WIN32) struct stat64 st {}; if (stat64(std::string{path}.c_str(), &st) != 0) { @@ -250,480 +247,476 @@ auto get_free_drive_space(std::string_view path) #endif // defined(_WIN32) - return ret; - } catch (const std::exception &e) { - utils::error::handle_exception(function_name, e); - } catch (...) { - utils::error::handle_exception(function_name); - } - - return std::nullopt; + return ret; + } catch (const std::exception &e) { + utils::error::handle_exception(function_name, e); + } catch (...) { + utils::error::handle_exception(function_name); } - auto get_times(std::wstring_view path) -> std::optional { - return get_times(utils::string::to_utf8(path)); - } + return std::nullopt; +} - auto get_total_drive_space( - std::string_view path) -> std::optional { - REPERTORY_USES_FUNCTION_NAME(); +auto get_times(std::wstring_view path) -> std::optional { + return get_times(utils::string::to_utf8(path)); +} - try { +auto get_total_drive_space(std::string_view path) + -> std::optional { + REPERTORY_USES_FUNCTION_NAME(); + + try { #if defined(_WIN32) - ULARGE_INTEGER li{}; - if (not ::GetDiskFreeSpaceEx(std::string{path}.c_str(), nullptr, &li, - nullptr)) { - throw utils::error::create_exception({ - function_name, - "failed to get total disk space", - std::to_string(utils::get_last_error_code()), - path, - }); - } - - return li.QuadPart; -#endif // defined(_WIN32) - -#if defined(__linux__) - struct statfs64 st {}; - if (statfs64(std::string{path}.c_str(), &st) != 0) { - throw utils::error::create_exception({ - function_name, - "failed to get total disk space", - std::to_string(utils::get_last_error_code()), - path, - }); - } - - return st.f_blocks * static_cast(st.f_bsize); -#endif // defined(__linux__) - -#if defined(__APPLE__) - struct statvfs st {}; - if (statvfs(path.c_str(), &st) != 0) { - throw utils::error::create_exception({ - function_name, - "failed to get total disk space", - std::to_string(utils::get_last_error_code()), - path, - }); - } - - return st.f_blocks * static_cast(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_total_drive_space( - std::wstring_view path) -> std::optional { - return get_total_drive_space(utils::string::to_utf8(path)); - } - - auto i_fs_item::get_time(time_type type) - const -> std::optional { - return utils::file::get_time(get_path(), type); - } - - auto i_file::read_all(data_buffer & data, std::uint64_t offset, - std::size_t * total_read) -> bool { - data_buffer buffer; - buffer.resize(get_read_buffer_size()); - - std::size_t current_read{}; - while (read(reinterpret_cast(buffer.data()), - buffer.size() * sizeof(data_buffer::value_type), offset, - ¤t_read)) { - if (total_read != nullptr) { - *total_read += current_read; - } - - if (current_read != 0U) { - offset += current_read; - - data.insert( - data.end(), buffer.begin(), - std::next(buffer.begin(), - static_cast( - current_read / sizeof(data_buffer::value_type)))); - continue; - } - - return true; - } - - return false; - } - -#if defined(PROJECT_ENABLE_JSON) -#if defined(PROJECT_ENABLE_LIBSODIUM) && defined(PROJECT_ENABLE_BOOST) - auto read_json_file(std::string_view path, nlohmann::json & data, - std::optional password) -> bool { -#else // !defined(PROJECT_ENABLE_LIBSODIUM) && defined(PROJECT_ENABLE_BOOST) - auto read_json_file(std::string_view path, nlohmann::json & data) -> bool { -#endif // defined(PROJECT_ENABLE_LIBSODIUM) && defined(PROJECT_ENABLE_BOOST) - REPERTORY_USES_FUNCTION_NAME(); - - try { - auto abs_path = utils::path::absolute(path); - auto file = file::open_file(abs_path); - if (not *file) { - return false; - } - - try { - data_buffer buffer{}; - if (not file->read_all(buffer, 0U)) { - return false; - } - -#if defined(PROJECT_ENABLE_LIBSODIUM) && defined(PROJECT_ENABLE_BOOST) - if (password.has_value()) { - data_buffer decrypted_data{}; - if (not utils::encryption::decrypt_data(*password, buffer, - decrypted_data)) { - return false; - } - - buffer = decrypted_data; - } -#endif // defined(PROJECT_ENABLE_LIBSODIUM) && defined(PROJECT_ENABLE_BOOST) - - std::string json_str(buffer.begin(), buffer.end()); - if (not json_str.empty()) { - data = nlohmann::json::parse(json_str); - } - } catch (const std::exception &e) { - utils::error::handle_exception(function_name, e); - return false; - } catch (...) { - utils::error::handle_exception(function_name); - return false; - } - - return true; - } catch (const std::exception &e) { - utils::error::handle_exception(function_name, e); - } catch (...) { - utils::error::handle_exception(function_name); - } - - return false; - } - -#if defined(PROJECT_ENABLE_LIBSODIUM) && defined(PROJECT_ENABLE_BOOST) - auto write_json_file(std::string_view path, const nlohmann::json &data, - std::optional password) -> bool { -#else // !defined(PROJECT_ENABLE_LIBSODIUM) && defined(PROJECT_ENABLE_BOOST) - auto write_json_file(std::string_view path, - const nlohmann::json &data) -> bool { -#endif // defined(PROJECT_ENABLE_LIBSODIUM) && defined(PROJECT_ENABLE_BOOST) - REPERTORY_USES_FUNCTION_NAME(); - - try { - auto file = file::open_or_create_file(path); - if (not file->truncate()) { - throw utils::error::create_exception({ - function_name, - "failed to truncate file", - std::to_string(utils::get_last_error_code()), - path, - }); - } - -#if defined(PROJECT_ENABLE_LIBSODIUM) && defined(PROJECT_ENABLE_BOOST) - if (password.has_value()) { - const auto str_data = data.dump(); - - data_buffer encrypted_data{}; - utils::encryption::encrypt_data( - *password, - reinterpret_cast(str_data.c_str()), - str_data.size(), encrypted_data); - return file->write(encrypted_data, 0U); - } -#endif // defined(PROJECT_ENABLE_LIBSODIUM) && defined(PROJECT_ENABLE_BOOST) - - auto json_str = data.dump(); - return file->write( - reinterpret_cast(json_str.c_str()), - json_str.size(), 0U); - } catch (const std::exception &e) { - utils::error::handle_exception(function_name, e); - } catch (...) { - utils::error::handle_exception(function_name); - } - - return false; - } - -#if defined(PROJECT_ENABLE_LIBSODIUM) && defined(PROJECT_ENABLE_BOOST) - auto read_json_file(std::wstring_view path, nlohmann::json & data, - std::optional password) -> bool { - if (password.has_value()) { - auto password_a = utils::string::to_utf8(*password); - return read_json_file(utils::string::to_utf8(path), data, password_a); - } - - return read_json_file(utils::string::to_utf8(path), data, std::nullopt); - } - - auto write_json_file(std::wstring_view path, const nlohmann::json &data, - std::optional password) -> bool { - if (password.has_value()) { - auto password_a = utils::string::to_utf8(*password); - return write_json_file(utils::string::to_utf8(path), data, password_a); - } - - return write_json_file(utils::string::to_utf8(path), data, std::nullopt); - } -#else // !defined(PROJECT_ENABLE_LIBSODIUM) && defined(PROJECT_ENABLE_BOOST) - auto read_json_file(std::wstring_view path, nlohmann::json & data) -> bool { - return read_json_file(utils::string::to_utf8(path), data); - } - - auto write_json_file(std::wstring_view path, - const nlohmann::json &data) -> bool { - return write_json_file(utils::string::to_utf8(path), data); - } -#endif // defined(PROJECT_ENABLE_LIBSODIUM) && defined(PROJECT_ENABLE_BOOST) -#endif // defined(PROJECT_ENABLE_JSON) - -#if defined(PROJECT_ENABLE_LIBDSM) - static constexpr const auto validate_smb_path = - [](std::string_view path) -> bool { - return (not utils::string::begins_with(path, "///") && - utils::string::begins_with(path, "//") && - // not utils::string::contains(path, " ") && - std::count(path.begin(), path.end(), '/') >= 3U); - }; - - auto smb_create_smb_path(std::string_view smb_path, - std::string_view rel_path) -> std::string { - REPERTORY_USES_FUNCTION_NAME(); - - if (not validate_smb_path(smb_path)) { + ULARGE_INTEGER li{}; + if (not ::GetDiskFreeSpaceEx(std::string{path}.c_str(), nullptr, &li, + nullptr)) { throw utils::error::create_exception({ function_name, - "invalid smb path", - smb_path, - }); - } - - std::string path{rel_path}; - utils::path::format_path(path, "/", "\\"); - utils::string::left_trim(path, '/'); - - auto old_parts = - repertory::utils::string::split(smb_path.substr(2U), '/', false); - - auto new_parts = repertory::utils::string::split(path, '/', false); - old_parts.insert(old_parts.end(), new_parts.begin(), new_parts.end()); - - path = utils::string::join(old_parts, '/'); - path = "//" + utils::path::format_path(path, "/", "\\"); - - if (not validate_smb_path(path)) { - throw utils::error::create_exception({ - function_name, - "invalid smb path", + "failed to get total disk space", + std::to_string(utils::get_last_error_code()), path, }); } - return path; - } + return li.QuadPart; +#endif // defined(_WIN32) - auto smb_create_and_validate_relative_path( - std::string_view smb_path, std::string_view path) -> std::string { - REPERTORY_USES_FUNCTION_NAME(); - - if (not validate_smb_path(smb_path)) { +#if defined(__linux__) + struct statfs64 st {}; + if (statfs64(std::string{path}.c_str(), &st) != 0) { throw utils::error::create_exception({ function_name, - "invalid smb path", - smb_path, + "failed to get total disk space", + std::to_string(utils::get_last_error_code()), + path, }); } - std::string dir_path; - if (utils::string::begins_with(path, "//")) { - if (not utils::file::smb_parent_is_same(smb_path, path)) { - throw utils::error::create_exception({ - function_name, - "failed to validate path", - "parent paths are not the same", - smb_path, - path, - }); + return st.f_blocks * static_cast(st.f_bsize); +#endif // defined(__linux__) + +#if defined(__APPLE__) + struct statvfs st {}; + if (statvfs(path.c_str(), &st) != 0) { + throw utils::error::create_exception({ + function_name, + "failed to get total disk space", + std::to_string(utils::get_last_error_code()), + path, + }); + } + + return st.f_blocks * static_cast(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_total_drive_space(std::wstring_view path) + -> std::optional { + return get_total_drive_space(utils::string::to_utf8(path)); +} + +auto i_fs_item::get_time(time_type type) const -> std::optional { + return utils::file::get_time(get_path(), type); +} + +auto i_file::read_all(data_buffer &data, std::uint64_t offset, + std::size_t *total_read) -> bool { + data_buffer buffer; + buffer.resize(get_read_buffer_size()); + + std::size_t current_read{}; + while (read(reinterpret_cast(buffer.data()), + buffer.size() * sizeof(data_buffer::value_type), offset, + ¤t_read)) { + if (total_read != nullptr) { + *total_read += current_read; + } + + if (current_read != 0U) { + offset += current_read; + + data.insert( + data.end(), buffer.begin(), + std::next(buffer.begin(), + static_cast( + current_read / sizeof(data_buffer::value_type)))); + continue; + } + + return true; + } + + return false; +} + +#if defined(PROJECT_ENABLE_JSON) +#if defined(PROJECT_ENABLE_LIBSODIUM) && defined(PROJECT_ENABLE_BOOST) +auto read_json_file(std::string_view path, nlohmann::json &data, + std::optional password) -> bool { +#else // !defined(PROJECT_ENABLE_LIBSODIUM) && defined(PROJECT_ENABLE_BOOST) +auto read_json_file(std::string_view path, nlohmann::json &data) -> bool { +#endif // defined(PROJECT_ENABLE_LIBSODIUM) && defined(PROJECT_ENABLE_BOOST) + REPERTORY_USES_FUNCTION_NAME(); + + try { + auto abs_path = utils::path::absolute(path); + auto file = file::open_file(abs_path); + if (not *file) { + return false; + } + + try { + data_buffer buffer{}; + if (not file->read_all(buffer, 0U)) { + return false; } - return utils::file::smb_create_relative_path(path); - } +#if defined(PROJECT_ENABLE_LIBSODIUM) && defined(PROJECT_ENABLE_BOOST) + if (password.has_value()) { + data_buffer decrypted_data{}; + if (not utils::encryption::decrypt_data(*password, buffer, + decrypted_data)) { + return false; + } - return utils::file::smb_create_relative_path(std::string{smb_path} + '/' + - std::string{path}); - } + buffer = decrypted_data; + } +#endif // defined(PROJECT_ENABLE_LIBSODIUM) && defined(PROJECT_ENABLE_BOOST) - auto smb_create_relative_path(std::string_view smb_path) -> std::string { - REPERTORY_USES_FUNCTION_NAME(); - - if (not validate_smb_path(smb_path)) { - throw utils::error::create_exception({ - function_name, - "invalid smb path", - smb_path, - }); - } - - std::string path{smb_path}; - utils::path::format_path(path, "\\", "/"); - utils::string::left_trim(path, '\\'); - - auto parts = repertory::utils::string::split(path, '\\', false); - parts.erase(parts.begin(), std::next(parts.begin(), 2U)); - return "\\" + utils::string::join(parts, '\\'); - } - - auto smb_create_search_path(std::string_view smb_path) -> std::string { - REPERTORY_USES_FUNCTION_NAME(); - - if (not validate_smb_path(smb_path)) { - throw utils::error::create_exception({ - function_name, - "invalid smb path", - smb_path, - }); - } - - std::string path{smb_path}; - utils::string::left_trim(path, '/'); - - auto parts = repertory::utils::string::split(path, '/', false); - parts.erase(parts.begin(), std::next(parts.begin(), 2U)); - - auto search_path = repertory::utils::string::join(parts, '\\'); - return search_path.empty() ? "\\*" : "\\" + search_path + "\\*"; - } - - auto smb_get_parent_path(std::string_view smb_path) -> std::string { - REPERTORY_USES_FUNCTION_NAME(); - - if (not validate_smb_path(smb_path)) { - throw utils::error::create_exception({ - function_name, - "invalid smb path", - smb_path, - }); - } - - auto parts = - repertory::utils::string::split(smb_path.substr(2U), '/', false); - if (parts.size() > 2U) { - parts.erase(std::prev(parts.end()), parts.end()); - } - - auto parent_smb_path = "//" + utils::string::join(parts, '/'); - if (not validate_smb_path(parent_smb_path)) { - throw utils::error::create_exception({ - function_name, - "invalid parent smb path", - parent_smb_path, - }); - } - - return parent_smb_path; - } - - auto smb_get_root_path(std::string_view smb_path) -> std::string { - REPERTORY_USES_FUNCTION_NAME(); - - if (not validate_smb_path(smb_path)) { - throw utils::error::create_exception({ - function_name, - "invalid smb path", - smb_path, - }); - } - - auto parts = - repertory::utils::string::split(smb_path.substr(2U), '/', false); - if (parts.size() > 2U) { - parts.erase(std::next(parts.begin(), 2U), parts.end()); - } - - return "//" + utils::string::join(parts, '/'); - } - - auto smb_get_unc_path(std::string_view smb_path) -> std::string { - REPERTORY_USES_FUNCTION_NAME(); - - if (not validate_smb_path(smb_path)) { - throw utils::error::create_exception({ - function_name, - "invalid smb path", - smb_path, - }); - } - - std::string unc_path{smb_path}; - utils::path::format_path(unc_path, "\\", "/"); - return '\\' + unc_path; - } - - auto smb_get_uri_path(std::string_view smb_path) -> std::string { - REPERTORY_USES_FUNCTION_NAME(); - - if (not validate_smb_path(smb_path)) { - throw utils::error::create_exception({ - function_name, - "invalid smb path", - smb_path, - }); - } - - return "smb:" + std::string{smb_path}; - } - - auto smb_get_uri_path(std::string_view smb_path, std::string_view user, - std::string_view password) -> std::string { - REPERTORY_USES_FUNCTION_NAME(); - - if (not validate_smb_path(smb_path)) { - throw utils::error::create_exception({ - function_name, - "invalid smb path", - smb_path, - }); - } - - return "smb://" + std::string{user} + ':' + std::string{password} + '@' + - std::string{smb_path.substr(2U)}; - } - - auto smb_parent_is_same(std::string_view smb_path1, - std::string_view smb_path2) -> bool { - if (not(validate_smb_path(smb_path1) && validate_smb_path(smb_path2))) { + std::string json_str(buffer.begin(), buffer.end()); + if (not json_str.empty()) { + data = nlohmann::json::parse(json_str); + } + } catch (const std::exception &e) { + utils::error::handle_exception(function_name, e); + return false; + } catch (...) { + utils::error::handle_exception(function_name); return false; } - auto parts1 = utils::string::split(smb_path1.substr(2U), "/", false); - auto parts2 = utils::string::split(smb_path2.substr(2U), "/", false); - if (parts1.size() < 2U || parts2.size() < 2U) { - return false; - } - - if (parts2.at(1U).empty() || parts1.at(1U).empty()) { - return false; - } - - return std::equal(parts1.begin(), std::next(parts1.begin(), 2U), - parts2.begin()); + return true; + } catch (const std::exception &e) { + utils::error::handle_exception(function_name, e); + } catch (...) { + utils::error::handle_exception(function_name); } + + return false; +} + +#if defined(PROJECT_ENABLE_LIBSODIUM) && defined(PROJECT_ENABLE_BOOST) +auto write_json_file(std::string_view path, const nlohmann::json &data, + std::optional password) -> bool { +#else // !defined(PROJECT_ENABLE_LIBSODIUM) && defined(PROJECT_ENABLE_BOOST) +auto write_json_file(std::string_view path, + const nlohmann::json &data) -> bool { +#endif // defined(PROJECT_ENABLE_LIBSODIUM) && defined(PROJECT_ENABLE_BOOST) + REPERTORY_USES_FUNCTION_NAME(); + + try { + auto file = file::open_or_create_file(path); + if (not file->truncate()) { + throw utils::error::create_exception({ + function_name, + "failed to truncate file", + std::to_string(utils::get_last_error_code()), + path, + }); + } + +#if defined(PROJECT_ENABLE_LIBSODIUM) && defined(PROJECT_ENABLE_BOOST) + if (password.has_value()) { + const auto str_data = data.dump(); + + data_buffer encrypted_data{}; + utils::encryption::encrypt_data( + *password, reinterpret_cast(str_data.c_str()), + str_data.size(), encrypted_data); + return file->write(encrypted_data, 0U); + } +#endif // defined(PROJECT_ENABLE_LIBSODIUM) && defined(PROJECT_ENABLE_BOOST) + + auto json_str = data.dump(); + return file->write( + reinterpret_cast(json_str.c_str()), + json_str.size(), 0U); + } catch (const std::exception &e) { + utils::error::handle_exception(function_name, e); + } catch (...) { + utils::error::handle_exception(function_name); + } + + return false; +} + +#if defined(PROJECT_ENABLE_LIBSODIUM) && defined(PROJECT_ENABLE_BOOST) +auto read_json_file(std::wstring_view path, nlohmann::json &data, + std::optional password) -> bool { + if (password.has_value()) { + auto password_a = utils::string::to_utf8(*password); + return read_json_file(utils::string::to_utf8(path), data, password_a); + } + + return read_json_file(utils::string::to_utf8(path), data, std::nullopt); +} + +auto write_json_file(std::wstring_view path, const nlohmann::json &data, + std::optional password) -> bool { + if (password.has_value()) { + auto password_a = utils::string::to_utf8(*password); + return write_json_file(utils::string::to_utf8(path), data, password_a); + } + + return write_json_file(utils::string::to_utf8(path), data, std::nullopt); +} +#else // !defined(PROJECT_ENABLE_LIBSODIUM) && defined(PROJECT_ENABLE_BOOST) +auto read_json_file(std::wstring_view path, nlohmann::json &data) -> bool { + return read_json_file(utils::string::to_utf8(path), data); +} + +auto write_json_file(std::wstring_view path, + const nlohmann::json &data) -> bool { + return write_json_file(utils::string::to_utf8(path), data); +} +#endif // defined(PROJECT_ENABLE_LIBSODIUM) && defined(PROJECT_ENABLE_BOOST) +#endif // defined(PROJECT_ENABLE_JSON) + +#if defined(PROJECT_ENABLE_LIBDSM) +static constexpr const auto validate_smb_path = + [](std::string_view path) -> bool { + return (not utils::string::begins_with(path, "///") && + utils::string::begins_with(path, "//") && + // not utils::string::contains(path, " ") && + std::count(path.begin(), path.end(), '/') >= 3U); +}; + +auto smb_create_smb_path(std::string_view smb_path, + std::string_view rel_path) -> std::string { + REPERTORY_USES_FUNCTION_NAME(); + + if (not validate_smb_path(smb_path)) { + throw utils::error::create_exception({ + function_name, + "invalid smb path", + smb_path, + }); + } + + std::string path{rel_path}; + utils::path::format_path(path, "/", "\\"); + utils::string::left_trim(path, '/'); + + auto old_parts = + repertory::utils::string::split(smb_path.substr(2U), '/', false); + + auto new_parts = repertory::utils::string::split(path, '/', false); + old_parts.insert(old_parts.end(), new_parts.begin(), new_parts.end()); + + path = utils::string::join(old_parts, '/'); + path = "//" + utils::path::format_path(path, "/", "\\"); + + if (not validate_smb_path(path)) { + throw utils::error::create_exception({ + function_name, + "invalid smb path", + path, + }); + } + + return path; +} + +auto smb_create_and_validate_relative_path( + std::string_view smb_path, std::string_view path) -> std::string { + REPERTORY_USES_FUNCTION_NAME(); + + if (not validate_smb_path(smb_path)) { + throw utils::error::create_exception({ + function_name, + "invalid smb path", + smb_path, + }); + } + + std::string dir_path; + if (utils::string::begins_with(path, "//")) { + if (not utils::file::smb_parent_is_same(smb_path, path)) { + throw utils::error::create_exception({ + function_name, + "failed to validate path", + "parent paths are not the same", + smb_path, + path, + }); + } + + return utils::file::smb_create_relative_path(path); + } + + return utils::file::smb_create_relative_path(std::string{smb_path} + '/' + + std::string{path}); +} + +auto smb_create_relative_path(std::string_view smb_path) -> std::string { + REPERTORY_USES_FUNCTION_NAME(); + + if (not validate_smb_path(smb_path)) { + throw utils::error::create_exception({ + function_name, + "invalid smb path", + smb_path, + }); + } + + std::string path{smb_path}; + utils::path::format_path(path, "\\", "/"); + utils::string::left_trim(path, '\\'); + + auto parts = repertory::utils::string::split(path, '\\', false); + parts.erase(parts.begin(), std::next(parts.begin(), 2U)); + return "\\" + utils::string::join(parts, '\\'); +} + +auto smb_create_search_path(std::string_view smb_path) -> std::string { + REPERTORY_USES_FUNCTION_NAME(); + + if (not validate_smb_path(smb_path)) { + throw utils::error::create_exception({ + function_name, + "invalid smb path", + smb_path, + }); + } + + std::string path{smb_path}; + utils::string::left_trim(path, '/'); + + auto parts = repertory::utils::string::split(path, '/', false); + parts.erase(parts.begin(), std::next(parts.begin(), 2U)); + + auto search_path = repertory::utils::string::join(parts, '\\'); + return search_path.empty() ? "\\*" : "\\" + search_path + "\\*"; +} + +auto smb_get_parent_path(std::string_view smb_path) -> std::string { + REPERTORY_USES_FUNCTION_NAME(); + + if (not validate_smb_path(smb_path)) { + throw utils::error::create_exception({ + function_name, + "invalid smb path", + smb_path, + }); + } + + auto parts = repertory::utils::string::split(smb_path.substr(2U), '/', false); + if (parts.size() > 2U) { + parts.erase(std::prev(parts.end()), parts.end()); + } + + auto parent_smb_path = "//" + utils::string::join(parts, '/'); + if (not validate_smb_path(parent_smb_path)) { + throw utils::error::create_exception({ + function_name, + "invalid parent smb path", + parent_smb_path, + }); + } + + return parent_smb_path; +} + +auto smb_get_root_path(std::string_view smb_path) -> std::string { + REPERTORY_USES_FUNCTION_NAME(); + + if (not validate_smb_path(smb_path)) { + throw utils::error::create_exception({ + function_name, + "invalid smb path", + smb_path, + }); + } + + auto parts = repertory::utils::string::split(smb_path.substr(2U), '/', false); + if (parts.size() > 2U) { + parts.erase(std::next(parts.begin(), 2U), parts.end()); + } + + return "//" + utils::string::join(parts, '/'); +} + +auto smb_get_unc_path(std::string_view smb_path) -> std::string { + REPERTORY_USES_FUNCTION_NAME(); + + if (not validate_smb_path(smb_path)) { + throw utils::error::create_exception({ + function_name, + "invalid smb path", + smb_path, + }); + } + + std::string unc_path{smb_path}; + utils::path::format_path(unc_path, "\\", "/"); + return '\\' + unc_path; +} + +auto smb_get_uri_path(std::string_view smb_path) -> std::string { + REPERTORY_USES_FUNCTION_NAME(); + + if (not validate_smb_path(smb_path)) { + throw utils::error::create_exception({ + function_name, + "invalid smb path", + smb_path, + }); + } + + return "smb:" + std::string{smb_path}; +} + +auto smb_get_uri_path(std::string_view smb_path, std::string_view user, + std::string_view password) -> std::string { + REPERTORY_USES_FUNCTION_NAME(); + + if (not validate_smb_path(smb_path)) { + throw utils::error::create_exception({ + function_name, + "invalid smb path", + smb_path, + }); + } + + return "smb://" + std::string{user} + ':' + std::string{password} + '@' + + std::string{smb_path.substr(2U)}; +} + +auto smb_parent_is_same(std::string_view smb_path1, + std::string_view smb_path2) -> bool { + if (not(validate_smb_path(smb_path1) && validate_smb_path(smb_path2))) { + return false; + } + + auto parts1 = utils::string::split(smb_path1.substr(2U), "/", false); + auto parts2 = utils::string::split(smb_path2.substr(2U), "/", false); + if (parts1.size() < 2U || parts2.size() < 2U) { + return false; + } + + if (parts2.at(1U).empty() || parts1.at(1U).empty()) { + return false; + } + + return std::equal(parts1.begin(), std::next(parts1.begin(), 2U), + parts2.begin()); +} #endif // defined(PROJECT_ENABLE_LIBDSM) } // namespace repertory::utils::file