From 2fb53e34af5e17ff8b7d99c1ce07c6ad2741ffea Mon Sep 17 00:00:00 2001 From: "Scott E. Graves" Date: Sat, 19 Oct 2024 11:10:36 -0500 Subject: [PATCH] updated build system --- cmake/versions.cmake | 12 +- .../include/file_manager/file_manager.hpp | 38 +- .../src/file_manager/file_manager.cpp | 173 ++-- .../providers/encrypt/encrypt_provider.cpp | 32 +- .../librepertory/src/providers/meta_db.cpp | 50 +- support/include/utils/collection.hpp | 16 +- support/include/utils/db/sqlite/db_common.hpp | 22 +- .../include/utils/db/sqlite/db_where_t.hpp | 4 +- support/include/utils/encryption.hpp | 8 +- support/include/utils/error.hpp | 34 +- support/include/utils/hash.hpp | 31 +- .../include/utils/types/file/i_fs_item.hpp | 8 +- support/src/utils/db/sqlite/db_common.cpp | 96 +- support/src/utils/encrypting_reader.cpp | 78 +- support/src/utils/error.cpp | 5 + support/src/utils/file.cpp | 879 ++++++++++-------- support/src/utils/file_directory.cpp | 67 +- support/src/utils/file_file.cpp | 99 +- support/src/utils/file_smb_directory.cpp | 233 ++++- support/src/utils/file_smb_file.cpp | 196 +++- support/src/utils/hash.cpp | 46 +- support/src/utils/path.cpp | 8 +- support/src/utils/windows.cpp | 12 +- support/test/src/utils/db_sqlite_test.cpp | 14 +- 24 files changed, 1330 insertions(+), 831 deletions(-) diff --git a/cmake/versions.cmake b/cmake/versions.cmake index aefb4bcb..fb10e730 100644 --- a/cmake/versions.cmake +++ b/cmake/versions.cmake @@ -1,15 +1,15 @@ set(BINUTILS_VERSION 2.41) -set(BOOST_MAJOR_VERSION 1) -set(BOOST_MINOR_VERSION 85) -set(BOOST_PATCH_VERSION 0) set(BOOST2_MAJOR_VERSION 1) set(BOOST2_MINOR_VERSION 76) set(BOOST2_PATCH_VERSION 0) +set(BOOST_MAJOR_VERSION 1) +set(BOOST_MINOR_VERSION 85) +set(BOOST_PATCH_VERSION 0) set(CPP_HTTPLIB_VERSION 0.16.3) -set(CURL_VERSION 8.9.1) set(CURL2_VERSION 8_9_1) -set(EXPAT_VERSION 2.6.2) +set(CURL_VERSION 8.9.1) set(EXPAT2_VERSION 2_6_2) +set(EXPAT_VERSION 2.6.2) set(GCC_VERSION 14.2.0) set(GTEST_VERSION 1.15.2) set(ICU_VERSION 75-1) @@ -21,7 +21,7 @@ set(OPENSSL_VERSION 3.3.1) set(PKG_CONFIG_VERSION 0.29.2) set(PUGIXML_VERSION 1.14) set(SPDLOG_VERSION 1.14.1) -set(SQLITE_VERSION 3460100) set(SQLITE2_VERSION 3.46.1) +set(SQLITE_VERSION 3460100) set(STDUUID_VERSION 1.2.3) set(ZLIB_VERSION 1.3.1) diff --git a/repertory/librepertory/include/file_manager/file_manager.hpp b/repertory/librepertory/include/file_manager/file_manager.hpp index 87332df7..c4fa7879 100644 --- a/repertory/librepertory/include/file_manager/file_manager.hpp +++ b/repertory/librepertory/include/file_manager/file_manager.hpp @@ -57,6 +57,7 @@ private: i_provider &provider_; private: + utils::db::sqlite::db3_t db_; std::atomic next_handle_{0U}; mutable std::recursive_mutex open_file_mtx_; std::unordered_map> @@ -68,8 +69,6 @@ private: std::unique_ptr upload_thread_; private: - [[nodiscard]] auto create_db() const -> utils::db::sqlite::db3_t; - void close_timed_out_files(); auto get_open_file_by_handle(std::uint64_t handle) const @@ -83,22 +82,12 @@ private: std::shared_ptr closeable_file) -> api_error; void queue_upload(const std::string &api_path, const std::string &source_path, - bool no_lock, sqlite3 *db); + bool no_lock); - void remove_resume(const std::string &api_path, - const std::string &source_path, sqlite3 *db); + void remove_upload(const std::string &api_path, bool no_lock); - void remove_upload(const std::string &api_path, bool no_lock, sqlite3 *db); - - [[nodiscard]] auto rename_directory(const std::string &from_api_path, - const std::string &to_api_path, - sqlite3 *db) -> api_error; - - [[nodiscard]] auto rename_file(const std::string &from_api_path, - const std::string &to_api_path, bool overwrite, - sqlite3 *db) -> api_error; void swap_renamed_items(std::string from_api_path, std::string to_api_path, - bool directory, sqlite3 *db); + bool directory); void upload_completed(const file_upload_completed &evt); @@ -108,8 +97,7 @@ public: [[nodiscard]] auto get_next_handle() -> std::uint64_t; auto handle_file_rename(const std::string &from_api_path, - const std::string &to_api_path, sqlite3 *db) - -> api_error; + const std::string &to_api_path) -> api_error; void queue_upload(const i_open_file &file) override; @@ -148,27 +136,27 @@ public: [[nodiscard]] auto has_no_open_file_handles() const -> bool override; - [[nodiscard]] auto is_processing(const std::string &api_path) const - -> bool override; + [[nodiscard]] auto + is_processing(const std::string &api_path) const -> bool override; #if defined(PROJECT_TESTING) [[nodiscard]] auto open(std::shared_ptr of, const open_file_data &ofd, std::uint64_t &handle, std::shared_ptr &file) -> api_error; -#endif +#endif // defined(PROJECT_TESTING) [[nodiscard]] auto open(const std::string &api_path, bool directory, const open_file_data &ofd, std::uint64_t &handle, std::shared_ptr &file) -> api_error; [[nodiscard]] auto remove_file(const std::string &api_path) -> api_error; - [[nodiscard]] auto rename_directory(const std::string &from_api_path, - const std::string &to_api_path) - -> api_error; + [[nodiscard]] auto + rename_directory(const std::string &from_api_path, + const std::string &to_api_path) -> api_error; [[nodiscard]] auto rename_file(const std::string &from_api_path, - const std::string &to_api_path, bool overwrite) - -> api_error; + const std::string &to_api_path, + bool overwrite) -> api_error; void start(); diff --git a/repertory/librepertory/src/file_manager/file_manager.cpp b/repertory/librepertory/src/file_manager/file_manager.cpp index 7e9e8880..d6942e30 100644 --- a/repertory/librepertory/src/file_manager/file_manager.cpp +++ b/repertory/librepertory/src/file_manager/file_manager.cpp @@ -43,8 +43,8 @@ #include "utils/time.hpp" namespace { -[[nodiscard]] auto create_resume_entry(const repertory::i_open_file &file) - -> json { +[[nodiscard]] auto +create_resume_entry(const repertory::i_open_file &file) -> json { return { {"chunk_size", file.get_chunk_size()}, {"path", file.get_api_path()}, @@ -106,6 +106,10 @@ const std::map sql_create_tables{ namespace repertory { file_manager::file_manager(app_config &config, i_provider &provider) : config_(config), provider_(provider) { + db_ = utils::db::sqlite::create_db( + utils::path::combine(config_.get_data_directory(), {"file_manager.db"}), + sql_create_tables); + if (not provider_.is_direct_only()) { E_SUBSCRIBE_EXACT(file_upload_completed, [this](const file_upload_completed &completed) { @@ -116,6 +120,7 @@ file_manager::file_manager(app_config &config, i_provider &provider) file_manager::~file_manager() { stop(); + db_.reset(); E_CONSUMER_RELEASE(); } @@ -170,38 +175,6 @@ void file_manager::close_timed_out_files() { closeable_list.clear(); } -auto file_manager::create_db() const -> utils::db::sqlite::db3_t { - auto db_path = - utils::path::combine(config_.get_data_directory(), {"file_manager.db"}); - - sqlite3 *db3{nullptr}; - auto db_res = - sqlite3_open_v2(db_path.c_str(), &db3, - SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE, nullptr); - if (db_res != SQLITE_OK) { - throw std::runtime_error("failed to open db|" + db_path + '|' + - std::to_string(db_res) + '|' + - sqlite3_errstr(db_res)); - } - - auto db = utils::db::sqlite::db3_t{ - db3, - utils::db::sqlite::sqlite3_deleter(), - }; - - for (auto &&create_item : sql_create_tables) { - std::string err; - if (not utils::db::sqlite::execute_sql(*db, create_item.second, err)) { - db.reset(); - throw std::runtime_error(err); - } - } - - utils::db::sqlite::set_journal_mode(*db); - - return db; -} - auto file_manager::create(const std::string &api_path, api_meta_map &meta, open_file_data ofd, std::uint64_t &handle, std::shared_ptr &file) -> api_error { @@ -361,10 +334,8 @@ auto file_manager::get_stored_downloads() const -> std::vector { return {}; } - auto db = create_db(); - std::vector ret; - auto result = utils::db::sqlite::db_select{*db.get(), resume_table}.go(); + auto result = utils::db::sqlite::db_select{*db_, resume_table}.go(); while (result.has_row()) { try { std::optional row; @@ -385,8 +356,8 @@ auto file_manager::get_stored_downloads() const -> std::vector { } auto file_manager::handle_file_rename(const std::string &from_api_path, - const std::string &to_api_path, - sqlite3 *db) -> api_error { + const std::string &to_api_path) + -> api_error { std::string source_path{}; auto file_iter = open_file_lookup_.find(from_api_path); if (file_iter != open_file_lookup_.end()) { @@ -399,7 +370,7 @@ auto file_manager::handle_file_rename(const std::string &from_api_path, source_path = upload_lookup_.at(from_api_path)->get_source_path(); } } else { - auto result = utils::db::sqlite::db_select{*db, upload_table} + auto result = utils::db::sqlite::db_select{*db_, upload_table} .column("source_path") .where("api_path") .equals(from_api_path) @@ -411,22 +382,22 @@ auto file_manager::handle_file_rename(const std::string &from_api_path, } } - remove_upload(from_api_path, true, db); + remove_upload(from_api_path, true); auto ret = provider_.rename_file(from_api_path, to_api_path); if (ret != api_error::success) { - queue_upload(from_api_path, source_path, false, db); + queue_upload(from_api_path, source_path, false); return ret; } - swap_renamed_items(from_api_path, to_api_path, false, db); + swap_renamed_items(from_api_path, to_api_path, false); ret = source_path.empty() ? api_error::success : provider_.set_item_meta(to_api_path, META_SOURCE, source_path); if (should_upload) { - queue_upload(to_api_path, source_path, false, db); + queue_upload(to_api_path, source_path, false); } return ret; @@ -447,9 +418,7 @@ auto file_manager::is_processing(const std::string &api_path) const -> bool { } upload_lock.unlock(); - auto db = create_db(); - - utils::db::sqlite::db_select query{*db.get(), upload_table}; + utils::db::sqlite::db_select query{*db_, upload_table}; if (query.where("api_path").equals(api_path).go().has_row()) { return true; }; @@ -469,11 +438,10 @@ auto file_manager::open(const std::string &api_path, bool directory, return open(api_path, directory, ofd, handle, file, nullptr); } -auto file_manager::open(const std::string &api_path, bool directory, - const open_file_data &ofd, std::uint64_t &handle, - std::shared_ptr &file, - std::shared_ptr closeable_file) - -> api_error { +auto file_manager::open( + const std::string &api_path, bool directory, const open_file_data &ofd, + std::uint64_t &handle, std::shared_ptr &file, + std::shared_ptr closeable_file) -> api_error { const auto create_and_add_handle = [&](std::shared_ptr cur_file) { handle = get_next_handle(); @@ -517,14 +485,11 @@ auto file_manager::open(const std::string &api_path, bool directory, } void file_manager::queue_upload(const i_open_file &file) { - auto db = create_db(); - return queue_upload(file.get_api_path(), file.get_source_path(), false, - db.get()); + return queue_upload(file.get_api_path(), file.get_source_path(), false); } void file_manager::queue_upload(const std::string &api_path, - const std::string &source_path, bool no_lock, - sqlite3 *db) { + const std::string &source_path, bool no_lock) { if (provider_.is_direct_only()) { return; } @@ -533,10 +498,10 @@ void file_manager::queue_upload(const std::string &api_path, if (not no_lock) { lock = std::make_unique(upload_mtx_); } - remove_upload(api_path, true, db); + remove_upload(api_path, true); auto result = - utils::db::sqlite::db_insert{*db, upload_table} + utils::db::sqlite::db_insert{*db_, upload_table} .or_replace() .column_value("api_path", api_path) .column_value("date_time", @@ -544,7 +509,7 @@ void file_manager::queue_upload(const std::string &api_path, .column_value("source_path", source_path) .go(); if (result.ok()) { - remove_resume(api_path, source_path, db); + remove_resume(api_path, source_path); event_system::instance().raise(api_path, source_path); } else { event_system::instance().raise( @@ -570,10 +535,9 @@ auto file_manager::remove_file(const std::string &api_path) -> api_error { close_all(api_path); - auto db = create_db(); - remove_upload(api_path, true, db.get()); + remove_upload(api_path, true); - auto result = utils::db::sqlite::db_delete{*db.get(), resume_table} + auto result = utils::db::sqlite::db_delete{*db_, resume_table} .where("api_path") .equals(api_path) .go(); @@ -599,13 +563,7 @@ auto file_manager::remove_file(const std::string &api_path) -> api_error { void file_manager::remove_resume(const std::string &api_path, const std::string &source_path) { - auto db = create_db(); - return remove_resume(api_path, source_path, db.get()); -} - -void file_manager::remove_resume(const std::string &api_path, - const std::string &source_path, sqlite3 *db) { - auto result = utils::db::sqlite::db_delete{*db, resume_table} + auto result = utils::db::sqlite::db_delete{*db_, resume_table} .where("api_path") .equals(api_path) .go(); @@ -616,12 +574,10 @@ void file_manager::remove_resume(const std::string &api_path, } void file_manager::remove_upload(const std::string &api_path) { - auto db = create_db(); - remove_upload(api_path, false, db.get()); + remove_upload(api_path, false); } -void file_manager::remove_upload(const std::string &api_path, bool no_lock, - sqlite3 *db) { +void file_manager::remove_upload(const std::string &api_path, bool no_lock) { REPERTORY_USES_FUNCTION_NAME(); if (provider_.is_direct_only()) { @@ -633,7 +589,7 @@ void file_manager::remove_upload(const std::string &api_path, bool no_lock, lock = std::make_unique(upload_mtx_); } - auto result = utils::db::sqlite::db_delete{*db, upload_table} + auto result = utils::db::sqlite::db_delete{*db_, upload_table} .where("api_path") .equals(api_path) .go(); @@ -643,7 +599,7 @@ void file_manager::remove_upload(const std::string &api_path, bool no_lock, "failed to remove from upload table"); } - result = utils::db::sqlite::db_delete{*db, upload_active_table} + result = utils::db::sqlite::db_delete{*db_, upload_active_table} .where("api_path") .equals(api_path) .go(); @@ -670,13 +626,6 @@ void file_manager::remove_upload(const std::string &api_path, bool no_lock, auto file_manager::rename_directory(const std::string &from_api_path, const std::string &to_api_path) -> api_error { - auto db = create_db(); - return rename_directory(from_api_path, to_api_path, db.get()); -} - -auto file_manager::rename_directory(const std::string &from_api_path, - const std::string &to_api_path, sqlite3 *db) - -> api_error { if (not provider_.is_rename_supported()) { return api_error::not_implemented; } @@ -732,9 +681,8 @@ auto file_manager::rename_directory(const std::string &from_api_path, auto old_api_path = api_path; auto new_api_path = utils::path::create_api_path(utils::path::combine( to_api_path, {old_api_path.substr(from_api_path.size())})); - res = list[i].directory - ? rename_directory(old_api_path, new_api_path, db) - : rename_file(old_api_path, new_api_path, false, db); + res = list[i].directory ? rename_directory(old_api_path, new_api_path) + : rename_file(old_api_path, new_api_path, false); } } @@ -747,20 +695,13 @@ auto file_manager::rename_directory(const std::string &from_api_path, return res; } - swap_renamed_items(from_api_path, to_api_path, true, db); + swap_renamed_items(from_api_path, to_api_path, true); return api_error::success; } auto file_manager::rename_file(const std::string &from_api_path, - const std::string &to_api_path, bool overwrite) - -> api_error { - auto db = create_db(); - return rename_file(from_api_path, to_api_path, overwrite, db.get()); -} - -auto file_manager::rename_file(const std::string &from_api_path, - const std::string &to_api_path, bool overwrite, - sqlite3 *db) -> api_error { + const std::string &to_api_path, + bool overwrite) -> api_error { if (not provider_.is_rename_supported()) { return api_error::not_implemented; } @@ -828,7 +769,7 @@ auto file_manager::rename_file(const std::string &from_api_path, } } - return handle_file_rename(from_api_path, to_api_path, db); + return handle_file_rename(from_api_path, to_api_path); } void file_manager::start() { @@ -849,8 +790,6 @@ void file_manager::start() { return; } - auto db = create_db(); - struct active_item final { std::string api_path; std::string source_path; @@ -858,8 +797,7 @@ void file_manager::start() { std::vector active_items{}; - auto result = - utils::db::sqlite::db_select{*db.get(), upload_active_table}.go(); + auto result = utils::db::sqlite::db_select{*db_, upload_active_table}.go(); while (result.has_row()) { try { std::optional row; @@ -875,12 +813,11 @@ void file_manager::start() { } for (auto &&active_item : active_items) { - queue_upload(active_item.api_path, active_item.source_path, false, - db.get()); + queue_upload(active_item.api_path, active_item.source_path, false); } active_items.clear(); - result = utils::db::sqlite::db_select{*db.get(), resume_table}.go(); + result = utils::db::sqlite::db_select{*db_, resume_table}.go(); if (not result.ok()) { return; } @@ -999,8 +936,7 @@ void file_manager::store_resume(const i_open_file &file) { return; } - auto db = create_db(); - auto result = utils::db::sqlite::db_insert{*db.get(), resume_table} + auto result = utils::db::sqlite::db_insert{*db_, resume_table} .or_replace() .column_value("api_path", file.get_api_path()) .column_value("data", create_resume_entry(file).dump()) @@ -1018,8 +954,7 @@ void file_manager::store_resume(const i_open_file &file) { } void file_manager::swap_renamed_items(std::string from_api_path, - std::string to_api_path, bool directory, - sqlite3 *db) { + std::string to_api_path, bool directory) { REPERTORY_USES_FUNCTION_NAME(); auto file_iter = open_file_lookup_.find(from_api_path); @@ -1034,7 +969,7 @@ void file_manager::swap_renamed_items(std::string from_api_path, return; } - auto result = utils::db::sqlite::db_update{*db, resume_table} + auto result = utils::db::sqlite::db_update{*db_, resume_table} .column_value("api_path", to_api_path) .where("api_path") .equals(from_api_path) @@ -1052,11 +987,9 @@ void file_manager::upload_completed(const file_upload_completed &evt) { unique_mutex_lock upload_lock(upload_mtx_); if (not utils::string::to_bool(evt.get_cancelled().get())) { - auto db = create_db(); - auto err = api_error_from_string(evt.get_result().get()); if (err == api_error::success) { - auto result = utils::db::sqlite::db_delete{*db.get(), upload_active_table} + auto result = utils::db::sqlite::db_delete{*db_, upload_active_table} .where("api_path") .equals(evt.get_api_path().get()) .go(); @@ -1075,12 +1008,12 @@ void file_manager::upload_completed(const file_upload_completed &evt) { not utils::file::file(evt.get_source().get()).exists()) { event_system::instance().raise( evt.get_api_path(), evt.get_source()); - remove_upload(evt.get_api_path(), true, db.get()); + remove_upload(evt.get_api_path(), true); } else { event_system::instance().raise( evt.get_api_path(), evt.get_source(), err); - queue_upload(evt.get_api_path(), evt.get_source(), true, db.get()); + queue_upload(evt.get_api_path(), evt.get_source(), true); upload_notify_.wait_for(upload_lock, 5s); } } @@ -1092,8 +1025,6 @@ void file_manager::upload_completed(const file_upload_completed &evt) { void file_manager::upload_handler() { REPERTORY_USES_FUNCTION_NAME(); - auto db = create_db(); - while (not stop_requested_) { auto should_wait{true}; unique_mutex_lock upload_lock(upload_mtx_); @@ -1103,7 +1034,7 @@ void file_manager::upload_handler() { } if (upload_lookup_.size() < config_.get_max_upload_count()) { - auto result = utils::db::sqlite::db_select{*db.get(), upload_table} + auto result = utils::db::sqlite::db_select{*db_, upload_table} .order_by("api_path", true) .limit(1) .go(); @@ -1121,7 +1052,7 @@ void file_manager::upload_handler() { should_wait = false; event_system::instance().raise(api_path, source_path); - remove_upload(api_path, true, db.get()); + remove_upload(api_path, true); } break; case api_error::success: { @@ -1129,13 +1060,13 @@ void file_manager::upload_handler() { upload_lookup_[fsi.api_path] = std::make_unique(fsi, provider_); - auto del_res = utils::db::sqlite::db_delete{*db.get(), upload_table} + auto del_res = utils::db::sqlite::db_delete{*db_, upload_table} .where("api_path") .equals(api_path) .go(); if (del_res.ok()) { auto ins_res = - utils::db::sqlite::db_insert{*db.get(), upload_active_table} + utils::db::sqlite::db_insert{*db_, upload_active_table} .column_value("api_path", api_path) .column_value("source_path", source_path) .go(); @@ -1150,7 +1081,7 @@ void file_manager::upload_handler() { default: { event_system::instance().raise(api_path, source_path, res); - queue_upload(api_path, source_path, true, db.get()); + queue_upload(api_path, source_path, true); } break; } } diff --git a/repertory/librepertory/src/providers/encrypt/encrypt_provider.cpp b/repertory/librepertory/src/providers/encrypt/encrypt_provider.cpp index 59bce566..e50f0c05 100644 --- a/repertory/librepertory/src/providers/encrypt/encrypt_provider.cpp +++ b/repertory/librepertory/src/providers/encrypt/encrypt_provider.cpp @@ -1025,35 +1025,9 @@ auto encrypt_provider::start(api_item_added_callback /*api_item_added*/, return false; } - auto db_path = - utils::path::combine(config_.get_data_directory(), {"meta.db"}); - - sqlite3 *db3{nullptr}; - auto res = - sqlite3_open_v2(db_path.c_str(), &db3, - SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE, nullptr); - if (res != SQLITE_OK) { - utils::error::raise_error(function_name, "failed to open db|" + db_path + - '|' + std::to_string(res) + - '|' + sqlite3_errstr(res)); - return false; - } - db_ = utils::db::sqlite::db3_t{ - db3, - utils::db::sqlite::sqlite3_deleter(), - }; - - for (auto &&create : sql_create_tables) { - std::string err; - if (not utils::db::sqlite::execute_sql(*db_, create.second, err)) { - utils::error::raise_error(function_name, "failed to create table|" + - create.first + '|' + err); - db_.reset(); - return false; - } - } - - utils::db::sqlite::set_journal_mode(*db_); + db_ = utils::db::sqlite::create_db( + utils::path::combine(config_.get_data_directory(), {"meta.db"}), + sql_create_tables); const auto cfg = config_.get_encrypt_config(); diff --git a/repertory/librepertory/src/providers/meta_db.cpp b/repertory/librepertory/src/providers/meta_db.cpp index f2470a8f..6da89931 100644 --- a/repertory/librepertory/src/providers/meta_db.cpp +++ b/repertory/librepertory/src/providers/meta_db.cpp @@ -34,42 +34,24 @@ namespace repertory { meta_db::meta_db(const app_config &cfg) { REPERTORY_USES_FUNCTION_NAME(); - auto db_path = utils::path::combine(cfg.get_data_directory(), {"meta.db"}); - - sqlite3 *db3{nullptr}; - auto res = - sqlite3_open_v2(db_path.c_str(), &db3, - SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE, nullptr); - if (res != SQLITE_OK) { - utils::error::raise_error(function_name, "failed to open db|" + db_path + - '|' + std::to_string(res) + - '|' + sqlite3_errstr(res)); - return; - } - - db_ = utils::db::sqlite::db3_t{ - db3, - utils::db::sqlite::sqlite3_deleter(), + const std::map sql_create_tables{ + { + {"meta"}, + {"CREATE TABLE IF NOT EXISTS " + "meta " + "(" + "api_path TEXT PRIMARY KEY ASC, " + "data TEXT, " + "directory INTEGER, " + "pinned INTEGER, " + "source_path TEXT" + ");"}, + }, }; - const auto *create = "CREATE TABLE IF NOT EXISTS " - "meta " - "(" - "api_path TEXT PRIMARY KEY ASC, " - "data TEXT, " - "directory INTEGER, " - "pinned INTEGER, " - "source_path TEXT" - ");"; - std::string err; - if (not utils::db::sqlite::execute_sql(*db_, create, err)) { - utils::error::raise_error(function_name, - "failed to create db|" + db_path + '|' + err); - db_.reset(); - return; - } - - utils::db::sqlite::set_journal_mode(*db_); + db_ = utils::db::sqlite::create_db( + utils::path::combine(cfg.get_data_directory(), {"meta.db"}), + sql_create_tables); } meta_db::~meta_db() { db_.reset(); } diff --git a/support/include/utils/collection.hpp b/support/include/utils/collection.hpp index 0c24ded3..b1e57bf6 100644 --- a/support/include/utils/collection.hpp +++ b/support/include/utils/collection.hpp @@ -92,7 +92,11 @@ template } if (fmt_val.empty()) { - throw std::runtime_error("hex string is invalid|" + std::string{str}); + throw utils::error::create_exception({ + function_name, + "hex string is invalid", + str, + }); } if (fmt_val.length() % 2U) { @@ -107,9 +111,13 @@ template }); if (iter != fmt_val.end()) { auto invalid_idx{std::distance(fmt_val.begin(), iter)}; - throw std::range_error( - "invalid character in hex string|" + std::to_string(invalid_idx) + - '|' + std::string(1U, str.at(invalid_idx)) + '|' + std::string{str}); + throw std::range_error(utils::error::create_error_message({ + function_name, + "invalid character in hex string", + std::to_string(invalid_idx), + std::string(1U, str.at(invalid_idx)), + str, + })); } val.resize(fmt_val.length() / 2U); diff --git a/support/include/utils/db/sqlite/db_common.hpp b/support/include/utils/db/sqlite/db_common.hpp index b379dd67..b8a23899 100644 --- a/support/include/utils/db/sqlite/db_common.hpp +++ b/support/include/utils/db/sqlite/db_common.hpp @@ -25,6 +25,8 @@ #include "utils/config.hpp" +#include "utils/error.hpp" + namespace repertory::utils::db::sqlite { using db_types_t = std::variant; @@ -44,6 +46,10 @@ struct sqlite3_statement_deleter final { using db3_stmt_t = std::unique_ptr; +[[nodiscard]] auto +create_db(std::string db_path, + const std::map &sql_create_tables) -> db3_t; + [[nodiscard]] auto execute_sql(sqlite3 &db3, const std::string &sql, std::string &err) -> bool; @@ -89,11 +95,16 @@ public: template [[nodiscard]] auto get_value() const -> data_type { + REPERTORY_USES_FUNCTION_NAME(); + return std::visit( overloaded{ [](const data_type &value) -> data_type { return value; }, [](auto &&) -> data_type { - throw std::runtime_error("data type not supported"); + throw utils::error::create_exception({ + function_name, + "data type not supported", + }); }, }, value_); @@ -107,6 +118,8 @@ public: template class db_row final { public: db_row(std::shared_ptr ctx) { + REPERTORY_USES_FUNCTION_NAME(); + auto column_count = sqlite3_column_count(ctx->stmt.get()); for (std::int32_t col = 0; col < column_count; col++) { std::string name{sqlite3_column_name(ctx->stmt.get(), col)}; @@ -125,8 +138,11 @@ public: } break; default: - throw std::runtime_error("column type not implemented|" + name + '|' + - std::to_string(column_type)); + throw utils::error::create_exception({ + function_name, + "column type not implemented", + std::to_string(column_type), + }); } columns_[name] = db_column{col, name, value}; diff --git a/support/include/utils/db/sqlite/db_where_t.hpp b/support/include/utils/db/sqlite/db_where_t.hpp index 40ea6119..5178eee2 100644 --- a/support/include/utils/db/sqlite/db_where_t.hpp +++ b/support/include/utils/db/sqlite/db_where_t.hpp @@ -157,8 +157,8 @@ template struct db_where_t final { using action_t = std::variant; - [[nodiscard]] static auto dump(std::int32_t &idx, auto &&actions) - -> std::string { + [[nodiscard]] static auto dump(std::int32_t &idx, + auto &&actions) -> std::string { std::stringstream stream; for (auto &&action : actions) { diff --git a/support/include/utils/encryption.hpp b/support/include/utils/encryption.hpp index 9834d305..4ce213d2 100644 --- a/support/include/utils/encryption.hpp +++ b/support/include/utils/encryption.hpp @@ -25,6 +25,7 @@ #include "utils/config.hpp" +#include "utils/error.hpp" #include "utils/hash.hpp" namespace repertory::utils::encryption { @@ -108,6 +109,8 @@ encrypt_data(const std::array &key, const unsigned char *buffer, std::size_t buffer_size, result_t &res) { + REPERTORY_USES_FUNCTION_NAME(); + std::array mac{}; const std::uint32_t size = boost::endian::native_to_big( @@ -121,7 +124,10 @@ encrypt_data(const std::array(&size), sizeof(size), nullptr, iv.data(), key.data()) != 0) { - throw std::runtime_error("encryption failed"); + throw repertory::utils::error::create_exception({ + function_name, + "encryption failed", + }); } std::memcpy(res.data(), iv.data(), iv.size()); diff --git a/support/include/utils/error.hpp b/support/include/utils/error.hpp index 87d94714..add7e62f 100644 --- a/support/include/utils/error.hpp +++ b/support/include/utils/error.hpp @@ -25,6 +25,12 @@ #include "utils/config.hpp" namespace repertory::utils::error { +[[nodiscard]] auto +create_error_message(std::vector items) -> std::string; + +[[nodiscard]] auto +create_exception(std::vector items) -> std::runtime_error; + struct i_exception_handler { virtual ~i_exception_handler() {} @@ -48,17 +54,30 @@ protected: struct iostream_exception_handler final : i_exception_handler { void handle_error(std::string_view function_name, std::string_view msg) const override { - std::cerr << function_name << '|' << msg << std::endl; + std::cerr << create_error_message({ + function_name, + msg, + }) + << std::endl; } void handle_exception(std::string_view function_name) const override { - std::cerr << function_name << "|exception|unknown" << std::endl; + std::cerr << create_error_message({ + function_name, + "exception", + "unknown", + }) + << std::endl; } void handle_exception(std::string_view function_name, const std::exception &ex) const override { - std::cerr << function_name << "|exception|" - << (ex.what() == nullptr ? "unknown" : ex.what()) << std::endl; + std::cerr << create_error_message({ + function_name, + "exception", + (ex.what() == nullptr ? "unknown" : ex.what()), + }) + << std::endl; } }; inline const iostream_exception_handler default_exception_handler{}; @@ -66,15 +85,12 @@ inline const iostream_exception_handler default_exception_handler{}; extern std::atomic exception_handler; #if defined(PROJECT_ENABLE_TESTING) -[[nodiscard]] inline auto get_exception_handler() - -> const i_exception_handler * { +[[nodiscard]] inline auto +get_exception_handler() -> const i_exception_handler * { return exception_handler; } #endif // defined(PROJECT_ENABLE_TESTING) -[[nodiscard]] auto create_error_message(std::vector items) - -> std::string; - void handle_error(std::string_view function_name, std::string_view msg); void handle_exception(std::string_view function_name); diff --git a/support/include/utils/hash.hpp b/support/include/utils/hash.hpp index a79c9023..ece6c109 100644 --- a/support/include/utils/hash.hpp +++ b/support/include/utils/hash.hpp @@ -25,6 +25,8 @@ #include "utils/config.hpp" +#include "utils/error.hpp" + namespace repertory::utils::encryption { using hash_256_t = std::array; using hash_384_t = std::array; @@ -83,28 +85,39 @@ template template auto create_hash_blake2b_t(const unsigned char *data, std::size_t data_size) -> hash_t { + REPERTORY_USES_FUNCTION_NAME(); + hash_t hash{}; crypto_generichash_blake2b_state state{}; auto res = crypto_generichash_blake2b_init(&state, nullptr, 0U, hash.size()); if (res != 0) { - throw std::runtime_error("failed to initialize blake2b-" + - std::to_string(hash.size() * 8U) + "|" + - std::to_string(res)); + throw utils::error::create_exception({ + function_name, + "failed to initialize blake2b", + std::to_string(hash.size() * 8U), + std::to_string(res), + }); } res = crypto_generichash_blake2b_update(&state, data, data_size); if (res != 0) { - throw std::runtime_error("failed to update blake2b-" + - std::to_string(hash.size() * 8U) + "|" + - std::to_string(res)); + throw utils::error::create_exception({ + function_name, + "failed to update blake2b", + std::to_string(hash.size() * 8U), + std::to_string(res), + }); } res = crypto_generichash_blake2b_final(&state, hash.data(), hash.size()); if (res != 0) { - throw std::runtime_error("failed to finalize blake2b-" + - std::to_string(hash.size() * 8U) + "|" + - std::to_string(res)); + throw utils::error::create_exception({ + function_name, + "failed to finalize blake2b", + std::to_string(hash.size() * 8U), + std::to_string(res), + }); } return hash; diff --git a/support/include/utils/types/file/i_fs_item.hpp b/support/include/utils/types/file/i_fs_item.hpp index db4e647c..674dea96 100644 --- a/support/include/utils/types/file/i_fs_item.hpp +++ b/support/include/utils/types/file/i_fs_item.hpp @@ -24,6 +24,7 @@ #include "utils/config.hpp" +#include "utils/error.hpp" #include "utils/string.hpp" namespace repertory::utils::file { @@ -41,6 +42,8 @@ struct file_times final { std::uint64_t written{}; [[nodiscard]] auto get(time_type type) const -> std::uint64_t { + REPERTORY_USES_FUNCTION_NAME(); + switch (type) { case time_type::accessed: return accessed; @@ -52,7 +55,10 @@ struct file_times final { return written; } - throw std::runtime_error("type_type not supported"); + throw utils::error::create_exception({ + function_name, + "type_type not supported", + }); } }; diff --git a/support/src/utils/db/sqlite/db_common.cpp b/support/src/utils/db/sqlite/db_common.cpp index e58f18d2..3b8c5a89 100644 --- a/support/src/utils/db/sqlite/db_common.cpp +++ b/support/src/utils/db/sqlite/db_common.cpp @@ -34,25 +34,30 @@ void sqlite3_deleter::operator()(sqlite3 *db3) const { return; } - utils::error::handle_error(function_name, "closing database handle"); + std::string err_msg; + if (not execute_sql(*db3, "VACUUM;", err_msg)) { + utils::error::handle_error(function_name, + utils::error::create_error_message({ + "failed to vacuum database", + err_msg, + })); + } - if (not utils::retry_action( - [&db3]() -> bool { - auto res = sqlite3_close_v2(db3); - if (res == SQLITE_OK) { - return true; - } + if (not utils::retry_action([&db3]() -> bool { + auto res = sqlite3_close_v2(db3); + if (res == SQLITE_OK) { + return true; + } - auto &&err_str = sqlite3_errstr(res); - utils::error::handle_error( - function_name, - utils::error::create_error_message({ - "failed to close database", - (err_str == nullptr ? std::to_string(res) : err_str), - })); - return false; - }, - 60U)) { + auto &&err_str = sqlite3_errstr(res); + utils::error::handle_error( + function_name, + utils::error::create_error_message({ + "failed to close database", + (err_str == nullptr ? std::to_string(res) : err_str), + })); + return false; + })) { repertory::utils::error::handle_error(function_name, "failed to close database"); } @@ -71,8 +76,50 @@ auto db_column::get_value_as_json() const -> nlohmann::json { } #endif // defined(PROJECT_ENABLE_JSON) -auto execute_sql(sqlite3 &db3, const std::string &sql, std::string &err) - -> bool { +auto create_db(std::string db_path, + const std::map &sql_create_tables) + -> db3_t { + REPERTORY_USES_FUNCTION_NAME(); + + sqlite3 *db_ptr{nullptr}; + auto db_res = + sqlite3_open_v2(db_path.c_str(), &db_ptr, + SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE, nullptr); + if (db_res != SQLITE_OK) { + const auto *msg = sqlite3_errstr(db_res); + throw utils::error::create_exception({ + function_name, + "failed to open db", + db_path, + (msg == nullptr ? std::to_string(db_res) : msg), + }); + } + + auto db3 = db3_t{ + db_ptr, + sqlite3_deleter(), + }; + + for (auto &&create_item : sql_create_tables) { + std::string err_msg; + if (not sqlite::execute_sql(*db3, create_item.second, err_msg)) { + db3.reset(); + throw utils::error::create_exception({ + function_name, + err_msg, + }); + } + } + + set_journal_mode(*db3); + + return db3; +} + +auto execute_sql(sqlite3 &db3, const std::string &sql, + std::string &err) -> bool { + REPERTORY_USES_FUNCTION_NAME(); + char *err_msg{nullptr}; auto res = sqlite3_exec(&db3, sql.c_str(), nullptr, nullptr, &err_msg); if (err_msg != nullptr) { @@ -85,15 +132,20 @@ auto execute_sql(sqlite3 &db3, const std::string &sql, std::string &err) return true; } - err = "failed to execute sql|" + sql + "|" + std::to_string(res) + '|' + - (err.empty() ? sqlite3_errstr(res) : err); + err = utils::error::create_error_message({ + function_name, + "failed to execute sql", + err, + sql, + }); + return false; } void set_journal_mode(sqlite3 &db3) { sqlite3_exec(&db3, "PRAGMA journal_mode = WAL;PRAGMA synchronous = NORMAL;PRAGMA " - "auto_vacuum = FULL;", + "auto_vacuum = NONE;", nullptr, nullptr, nullptr); } } // namespace repertory::utils::db::sqlite diff --git a/support/src/utils/encrypting_reader.cpp b/support/src/utils/encrypting_reader.cpp index 8dbd2035..4346593d 100644 --- a/support/src/utils/encrypting_reader.cpp +++ b/support/src/utils/encrypting_reader.cpp @@ -60,8 +60,13 @@ protected: std::ios_base::openmode which = std::ios_base::out | std::ios_base::in) -> pos_type override { + REPERTORY_USES_FUNCTION_NAME(); + if ((which & std::ios_base::in) != std::ios_base::in) { - throw std::runtime_error("output is not supported"); + throw utils::error::create_exception({ + function_name, + "output is not supported", + }); } const auto set_position = [this](char *next) -> pos_type { @@ -179,9 +184,14 @@ encrypting_reader::encrypting_reader( stop_requested_(stop_requested), error_return_(error_return), source_file_(utils::file::file::open_or_create_file(source_path, true)) { + REPERTORY_USES_FUNCTION_NAME(); + if (not *source_file_) { - throw std::runtime_error("file open failed|src|" + - std::string{source_path}); + throw utils::error::create_exception({ + function_name, + "file open failed", + source_path, + }); } data_buffer result; @@ -204,8 +214,11 @@ encrypting_reader::encrypting_reader( auto opt_size = source_file_->size(); if (not opt_size.has_value()) { - throw std::runtime_error("failed to get file size|" + - source_file_->get_path()); + throw utils::error::create_exception({ + function_name, + "failed to get file size", + source_file_->get_path(), + }); } auto file_size = opt_size.value(); @@ -233,9 +246,14 @@ encrypting_reader::encrypting_reader(std::string_view encrypted_file_path, stop_requested_(stop_requested), error_return_(error_return), source_file_(utils::file::file::open_or_create_file(source_path, true)) { + REPERTORY_USES_FUNCTION_NAME(); + if (not *source_file_) { - throw std::runtime_error("file open failed|src|" + - std::string{source_path}); + throw utils::error::create_exception({ + function_name, + "file open failed", + source_path, + }); } encrypted_file_path_ = encrypted_file_path; @@ -243,8 +261,11 @@ encrypting_reader::encrypting_reader(std::string_view encrypted_file_path, auto opt_size = source_file_->size(); if (not opt_size.has_value()) { - throw std::runtime_error("failed to get file size|" + - source_file_->get_path()); + throw utils::error::create_exception({ + function_name, + "failed to get file size", + source_file_->get_path(), + }); } auto file_size = opt_size.value(); @@ -274,9 +295,14 @@ encrypting_reader::encrypting_reader( stop_requested_(stop_requested), error_return_(error_return), source_file_(utils::file::file::open_or_create_file(source_path, true)) { + REPERTORY_USES_FUNCTION_NAME(); + if (not *source_file_) { - throw std::runtime_error("file open failed|src|" + - std::string{source_path}); + throw utils::error::create_exception({ + function_name, + "file open failed", + source_path, + }); } encrypted_file_path_ = encrypted_file_path; @@ -284,9 +310,12 @@ encrypting_reader::encrypting_reader( auto opt_size = source_file_->size(); if (not opt_size.has_value()) { - throw std::runtime_error("get file size failed|src|" + - source_file_->get_path() + '|' + - std::to_string(utils::get_last_error_code())); + throw utils::error::create_exception({ + function_name, + "get file size failed", + std::to_string(utils::get_last_error_code()), + source_file_->get_path(), + }); } auto file_size{opt_size.value()}; @@ -315,9 +344,15 @@ encrypting_reader::encrypting_reader(const encrypting_reader &reader) last_data_chunk_size_(reader.last_data_chunk_size_), read_offset_(reader.read_offset_), total_size_(reader.total_size_) { + REPERTORY_USES_FUNCTION_NAME(); + if (not *source_file_) { - throw std::runtime_error("file open failed|src|" + - source_file_->get_path()); + throw utils::error::create_exception({ + function_name, + "file open failed", + std::to_string(utils::get_last_error_code()), + source_file_->get_path(), + }); } } @@ -331,11 +366,16 @@ auto encrypting_reader::calculate_decrypted_size(std::uint64_t total_size) auto encrypting_reader::calculate_encrypted_size(std::string_view source_path) -> std::uint64_t { + REPERTORY_USES_FUNCTION_NAME(); + auto opt_size = utils::file::file{source_path}.size(); if (not opt_size.has_value()) { - throw std::runtime_error("get file size failed|src|" + - std::string{source_path} + '|' + - std::to_string(utils::get_last_error_code())); + throw utils::error::create_exception({ + function_name, + "get file size failed", + std::to_string(utils::get_last_error_code()), + source_path, + }); } auto file_size{opt_size.value()}; diff --git a/support/src/utils/error.cpp b/support/src/utils/error.cpp index 50fe05c7..222e6eb2 100644 --- a/support/src/utils/error.cpp +++ b/support/src/utils/error.cpp @@ -38,6 +38,11 @@ auto create_error_message(std::vector items) -> std::string { return stream.str(); } +auto create_exception(std::vector items) + -> std::runtime_error { + return std::runtime_error(create_error_message(items)); +} + void handle_error(std::string_view function_name, std::string_view msg) { const i_exception_handler *handler{exception_handler}; if (handler != nullptr) { diff --git a/support/src/utils/file.cpp b/support/src/utils/file.cpp index da3c00f9..e9bd0bd5 100644 --- a/support/src/utils/file.cpp +++ b/support/src/utils/file.cpp @@ -51,15 +51,23 @@ auto change_to_process_directory() -> bool { #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)); + throw utils::error::create_exception({ + function_name, + "failed to readlink", + std::to_string(utils::get_last_error_code()), + path, + }); } #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)); + throw utils::error::create_exception({ + function_name, + "failed to chdir", + std::to_string(utils::get_last_error_code()), + path, + }); } #endif // defined(_WIN32) @@ -105,106 +113,126 @@ auto get_free_drive_space(std::string_view path) ULARGE_INTEGER li{}; if (not ::GetDiskFreeSpaceEx(std::string{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())); - } + throw utils::error::create_exception({ + function_name, + "failed to get free disk space", + std::to_string(utils::get_last_error_code()), + path, + }); - return li.QuadPart; + 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())); - } + 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 std::runtime_error("failed to get free disk space|" + - std::string{path} + '|' + - std::to_string(utils::get_last_error_code())); + 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); +#endif // defined(__APPLE__) + } + catch (const std::exception &e) { + utils::error::handle_exception(function_name, e); + } + catch (...) { + utils::error::handle_exception(function_name); } - 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; } - 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_free_drive_space( + std::wstring_view path) -> std::optional { + return get_free_drive_space(utils::string::to_utf8(path)); } - return std::nullopt; -} + 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::wstring_view path, - time_type type) -> std::optional { - return get_time(utils::string::to_utf8(path), type); -} + return std::nullopt; + } -auto get_times(std::string_view path) -> std::optional { - REPERTORY_USES_FUNCTION_NAME(); + auto get_time(std::wstring_view path, + time_type type) -> std::optional { + return get_time(utils::string::to_utf8(path), type); + } - try { - file_times ret{}; + auto get_times(std::string_view path) -> std::optional { + REPERTORY_USES_FUNCTION_NAME(); + + 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 std::runtime_error("failed to get file times|" + std::string{path} + - '|' + std::to_string(errno)); - } + 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) { - throw std::runtime_error("failed to get file times|" + std::string{path} + - '|' + std::to_string(errno)); + throw utils::error::create_exception({ + function_name, + "failed to get file times", + std::to_string(utils::get_last_error_code()), + path, + }); } ret.accessed = static_cast(st.st_atim.tv_nsec) + @@ -222,396 +250,477 @@ auto get_times(std::string_view path) -> std::optional { #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; -} - -auto get_times(std::wstring_view path) -> std::optional { - return get_times(utils::string::to_utf8(path)); -} - -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 std::runtime_error("failed to get total disk space|" + - std::string{path} + '|' + - std::to_string(utils::get_last_error_code())); + return ret; + } catch (const std::exception &e) { + utils::error::handle_exception(function_name, e); + } catch (...) { + utils::error::handle_exception(function_name); } - return li.QuadPart; + return std::nullopt; + } + + auto get_times(std::wstring_view path) -> std::optional { + return get_times(utils::string::to_utf8(path)); + } + + 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 std::runtime_error("failed to get total disk space|" + - std::string{path} + '|' + - std::to_string(utils::get_last_error_code())); - } + 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); + 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 std::runtime_error("failed to get total disk space|" + - std::string{path} + '|' + - std::to_string(utils::get_last_error_code())); - } + 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); + 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; + } catch (const std::exception &e) { + utils::error::handle_exception(function_name, e); + } catch (...) { + utils::error::handle_exception(function_name); } - 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 std::nullopt; } - return false; -} + 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 { + 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 { + 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; - } + REPERTORY_USES_FUNCTION_NAME(); try { - data_buffer buffer{}; - if (not file->read_all(buffer, 0U)) { + 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()) { - data_buffer decrypted_data{}; - if (not utils::encryption::decrypt_data(*password, buffer, - decrypted_data)) { - return false; - } + const auto str_data = data.dump(); - buffer = decrypted_data; + 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) - std::string json_str(buffer.begin(), buffer.end()); - if (not json_str.empty()) { - data = nlohmann::json::parse(json_str); - } + 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); - 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; } - 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 std::runtime_error("failed to truncate file"); - } - #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()) { - 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); + auto password_a = utils::string::to_utf8(*password); + return read_json_file(utils::string::to_utf8(path), data, password_a); } -#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 read_json_file(utils::string::to_utf8(path), data, std::nullopt); } - return false; -} + 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); + } -#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 write_json_file(utils::string::to_utf8(path), data, std::nullopt); } - - 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 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); -} + 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); -}; + 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 { - if (not validate_smb_path(smb_path)) { - throw std::runtime_error("invalid smb path|" + std::string{smb_path}); - } + auto smb_create_smb_path(std::string_view smb_path, + std::string_view rel_path) -> std::string { + REPERTORY_USES_FUNCTION_NAME(); - 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 std::runtime_error("invalid smb path|" + std::string{path}); - } - - return path; -} - -auto smb_create_and_validate_relative_path( - std::string_view smb_path, std::string_view path) -> std::string { - if (not validate_smb_path(smb_path)) { - throw std::runtime_error("invalid smb path|" + std::string{smb_path}); - } - - std::string dir_path; - if (utils::string::begins_with(path, "//")) { - if (not utils::file::smb_parent_is_same(smb_path, path)) { - throw std::runtime_error("failed to validate path|" + - std::string{smb_path} + '|' + std::string{path} + - "|parent paths are not the same"); + if (not validate_smb_path(smb_path)) { + throw utils::error::create_exception({ + function_name, + "invalid smb path", + smb_path, + }); } - return utils::file::smb_create_relative_path(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; } - return utils::file::smb_create_relative_path(std::string{smb_path} + '/' + - std::string{path}); -} + auto smb_create_and_validate_relative_path( + std::string_view smb_path, std::string_view path) -> std::string { + REPERTORY_USES_FUNCTION_NAME(); -auto smb_create_relative_path(std::string_view smb_path) -> std::string { - if (not validate_smb_path(smb_path)) { - throw std::runtime_error("invalid smb path|" + std::string{smb_path}); + 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}); } - std::string path{smb_path}; - utils::path::format_path(path, "\\", "/"); - utils::string::left_trim(path, '\\'); + auto smb_create_relative_path(std::string_view smb_path) -> std::string { + REPERTORY_USES_FUNCTION_NAME(); - auto parts = repertory::utils::string::split(path, '\\', false); - parts.erase(parts.begin(), std::next(parts.begin(), 2U)); - return "\\" + utils::string::join(parts, '\\'); -} + if (not validate_smb_path(smb_path)) { + throw utils::error::create_exception({ + function_name, + "invalid smb path", + smb_path, + }); + } -auto smb_create_search_path(std::string_view smb_path) -> std::string { - if (not validate_smb_path(smb_path)) { - throw std::runtime_error("invalid smb path|" + std::string{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, '\\'); } - std::string path{smb_path}; - utils::string::left_trim(path, '/'); + auto smb_create_search_path(std::string_view smb_path) -> std::string { + REPERTORY_USES_FUNCTION_NAME(); - auto parts = repertory::utils::string::split(path, '/', false); - parts.erase(parts.begin(), std::next(parts.begin(), 2U)); + if (not validate_smb_path(smb_path)) { + throw utils::error::create_exception({ + function_name, + "invalid smb path", + smb_path, + }); + } - auto search_path = repertory::utils::string::join(parts, '\\'); - return search_path.empty() ? "\\*" : "\\" + search_path + "\\*"; -} + std::string path{smb_path}; + utils::string::left_trim(path, '/'); -auto smb_get_parent_path(std::string_view smb_path) -> std::string { - if (not validate_smb_path(smb_path)) { - throw std::runtime_error("invalid smb path|" + std::string{smb_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 parts = repertory::utils::string::split(smb_path.substr(2U), '/', false); - if (parts.size() > 2U) { - parts.erase(std::prev(parts.end()), parts.end()); + 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 parent_smb_path = "//" + utils::string::join(parts, '/'); - if (not validate_smb_path(parent_smb_path)) { - throw std::runtime_error("invalid smb path|" + 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, '/'); } - return parent_smb_path; -} + auto smb_get_unc_path(std::string_view smb_path) -> std::string { + REPERTORY_USES_FUNCTION_NAME(); -auto smb_get_root_path(std::string_view smb_path) -> std::string { - if (not validate_smb_path(smb_path)) { - throw std::runtime_error("invalid smb path|" + std::string{smb_path}); + 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 parts = repertory::utils::string::split(smb_path.substr(2U), '/', false); - if (parts.size() > 2U) { - parts.erase(std::next(parts.begin(), 2U), parts.end()); + 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}; } - return "//" + utils::string::join(parts, '/'); -} + auto smb_get_uri_path(std::string_view smb_path, std::string_view user, + std::string_view password) -> std::string { + if (not validate_smb_path(smb_path)) { + throw utils::error::create_exception({ + function_name, + "invalid smb path", + smb_path, + }); + } -auto smb_get_unc_path(std::string_view smb_path) -> std::string { - if (not validate_smb_path(smb_path)) { - throw std::runtime_error("invalid smb path|" + std::string{smb_path}); + return "smb://" + std::string{user} + ':' + std::string{password} + '@' + + std::string{smb_path.substr(2U)}; } - std::string unc_path{smb_path}; - utils::path::format_path(unc_path, "\\", "/"); - return '\\' + unc_path; -} + 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 smb_get_uri_path(std::string_view smb_path) -> std::string { - if (not validate_smb_path(smb_path)) { - throw std::runtime_error("invalid smb path|" + std::string{smb_path}); + 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 "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 { - if (not validate_smb_path(smb_path)) { - throw std::runtime_error("invalid smb path|" + std::string{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 diff --git a/support/src/utils/file_directory.cpp b/support/src/utils/file_directory.cpp index 932d5329..28b5114b 100644 --- a/support/src/utils/file_directory.cpp +++ b/support/src/utils/file_directory.cpp @@ -23,6 +23,7 @@ #include "utils/common.hpp" #include "utils/error.hpp" +#include "utils/string.hpp" #include "utils/unix.hpp" #include "utils/windows.hpp" @@ -32,6 +33,8 @@ auto traverse_directory( std::function directory_action, std::function file_action, repertory::stop_type *stop_requested) -> bool { + REPERTORY_USES_FUNCTION_NAME(); + auto res{true}; const auto is_stop_requested = [&stop_requested]() -> bool { @@ -43,9 +46,12 @@ auto traverse_directory( auto search = repertory::utils::path::combine(path, {"*.*"}); auto find = ::FindFirstFileA(search.c_str(), &fd); if (find == INVALID_HANDLE_VALUE) { - throw std::runtime_error( - "failed to open directory|" + std::string{path} + '|' + - std::to_string(repertory::utils::get_last_error_code())); + throw repertory::utils::error::create_exception({ + function_name, + "failed to open directory", + std::to_string(repertory::utils::get_last_error_code()), + path, + }); } do { @@ -67,9 +73,12 @@ auto traverse_directory( #else // !defined(_WIN32) auto *root = opendir(std::string{path}.c_str()); if (root == nullptr) { - throw std::runtime_error( - "failed to open directory|" + std::string{path} + '|' + - std::to_string(repertory::utils::get_last_error_code())); + throw repertory::utils::error::create_exception({ + function_name, + "failed to open directory", + std::to_string(repertory::utils::get_last_error_code()), + path, + }); } struct dirent *de{nullptr}; @@ -94,14 +103,19 @@ auto traverse_directory( } // namespace namespace repertory::utils::file { -auto directory::copy_to(std::string_view new_path, bool overwrite) const - -> bool { +auto directory::copy_to(std::string_view new_path, + bool overwrite) const -> bool { REPERTORY_USES_FUNCTION_NAME(); try { - throw std::runtime_error("failed to copy directory|" + path_ + '|' + - std::string{new_path} + '+' + - std::to_string(overwrite) + "|not implemented"); + throw utils::error::create_exception({ + function_name, + "failed to copy directory", + "not implemented", + path_, + new_path, + utils::string::from_bool(overwrite), + }); } catch (const std::exception &e) { utils::error::handle_exception(function_name, e); } catch (...) { @@ -157,11 +171,14 @@ auto directory::create_directory(std::string_view path) const auto res = ::SHCreateDirectory(nullptr, utils::string::from_utf8(abs_path).c_str()); if (res != ERROR_SUCCESS) { - throw std::runtime_error("failed to create directory|" + - std::string{abs_path} + '|' + - std::to_string(res)); + throw utils::error::create_exception({ + function_name, + "failed to create directory", + std::to_string(res), + abs_path, + }); } -#else // !defined(_WIN32) +#else // !defined(_WIN32) auto ret{true}; auto paths = utils::string::split(abs_path, utils::path::directory_seperator, false); @@ -194,7 +211,7 @@ auto directory::exists() const -> bool { #if defined(_WIN32) return ::PathIsDirectoryA(path_.c_str()) != 0; #else // !defined(_WIN32) - struct stat64 st{}; + struct stat64 st {}; return (stat64(path_.c_str(), &st) == 0 && S_ISDIR(st.st_mode)); #endif // defined(_WIN32) @@ -247,8 +264,8 @@ auto directory::get_directories() const -> std::vector { return {}; } -auto directory::create_file(std::string_view file_name, bool read_only) const - -> fs_file_t { +auto directory::create_file(std::string_view file_name, + bool read_only) const -> fs_file_t { REPERTORY_USES_FUNCTION_NAME(); try { @@ -360,8 +377,13 @@ auto directory::move_to(std::string_view new_path) -> bool { REPERTORY_USES_FUNCTION_NAME(); try { - throw std::runtime_error("failed to move directory|" + path_ + '|' + - std::string{new_path} + "|not implemented"); + throw utils::error::create_exception({ + function_name, + "failed to move directory", + "not implemented", + path_, + new_path, + }); } catch (const std::exception &e) { utils::error::handle_exception(function_name, e); } catch (...) { @@ -383,7 +405,10 @@ auto directory::remove() -> bool { #endif // defined(_WIN32) if (not ret) { utils::error::handle_error(function_name, - "failed to remove directory|" + path_); + utils::error::create_error_message({ + "failed to remove directory", + path_, + })); } return ret; diff --git a/support/src/utils/file_file.cpp b/support/src/utils/file_file.cpp index 10eadd49..7ec179a9 100644 --- a/support/src/utils/file_file.cpp +++ b/support/src/utils/file_file.cpp @@ -33,7 +33,7 @@ namespace { file_size = 0U; #if defined(_WIN32) - struct _stat64 st{}; + struct _stat64 st {}; auto res = _stat64(std::string{path}.c_str(), &st); if (res != 0) { return false; @@ -55,7 +55,7 @@ namespace { return ((::PathFileExistsA(abs_path.c_str()) != 0) && (::PathIsDirectoryA(abs_path.c_str()) == 0)); #else // !defined(_WIN32) - struct stat64 st{}; + struct stat64 st {}; return (stat64(abs_path.c_str(), &st) == 0 && not S_ISDIR(st.st_mode)); #endif // defined(_WIN32) } @@ -112,8 +112,14 @@ namespace repertory::utils::file { // } void file::open() { + REPERTORY_USES_FUNCTION_NAME(); + if (not is_file(path_)) { - throw std::runtime_error("file not found: " + path_); + throw utils::error::create_exception({ + function_name, + "file not found", + path_, + }); } #if defined(_WIN32) @@ -150,8 +156,8 @@ auto file::open_file(std::string_view path, bool read_only) -> fs_file_t { return new_file; } -auto file::open_or_create_file(std::string_view path, bool read_only) - -> fs_file_t { +auto file::open_or_create_file(std::string_view path, + bool read_only) -> fs_file_t { auto abs_path = utils::path::absolute(path); if (not is_file(abs_path)) { #if defined(_WIN32) @@ -294,12 +300,20 @@ auto file::read(unsigned char *data, std::size_t to_read, std::uint64_t offset, try { if (not file_) { - throw std::runtime_error("file is not open for reading"); + throw utils::error::create_exception({ + function_name, + "file is not open for reading", + path_, + }); } if (fseeko(file_.get(), static_cast(offset), SEEK_SET) == -1) { - throw std::runtime_error("failed to seek before read"); + throw utils::error::create_exception({ + function_name, + "failed to seek before read", + path_, + }); } std::size_t bytes_read{0U}; @@ -307,7 +321,11 @@ auto file::read(unsigned char *data, std::size_t to_read, std::uint64_t offset, auto res = fread(&data[bytes_read], 1U, to_read - bytes_read, file_.get()); if (not feof(file_.get()) && ferror(file_.get())) { - throw std::runtime_error("failed to read file bytes"); + throw utils::error::create_exception({ + function_name, + "failed to read file bytes", + path_, + }); } if (res == 0) { @@ -349,8 +367,12 @@ auto file::sha256() -> std::optional { crypto_hash_sha256_state state{}; auto res = crypto_hash_sha256_init(&state); if (res != 0) { - throw std::runtime_error("failed to initialize sha256|" + - std::to_string(res)); + throw utils::error::create_exception({ + function_name, + "failed to initialize sha256", + std::to_string(res), + path_, + }); } { @@ -367,8 +389,12 @@ auto file::sha256() -> std::optional { &state, reinterpret_cast(buffer.data()), bytes_read); if (res != 0) { - throw std::runtime_error("failed to update sha256|" + - std::to_string(res)); + throw utils::error::create_exception({ + function_name, + "failed to update sha256", + std::to_string(res), + path_, + }); } } } @@ -376,8 +402,12 @@ auto file::sha256() -> std::optional { std::array out{}; res = crypto_hash_sha256_final(&state, out.data()); if (res != 0) { - throw std::runtime_error("failed to finalize sha256|" + - std::to_string(res)); + throw utils::error::create_exception({ + function_name, + "failed to finalize sha256", + std::to_string(res), + path_, + }); } ret = utils::collection::to_hex_string(out); @@ -411,7 +441,10 @@ auto file::remove() -> bool { #endif // defined(_WIN32) if (not ret) { utils::error::handle_error(function_name, - "failed to remove file|" + path_); + utils::error::create_error_message({ + "failed to remove file", + path_, + })); } return ret; @@ -464,12 +497,20 @@ auto file::write(const unsigned char *data, std::size_t to_write, try { if (not file_) { - throw std::runtime_error("file is not open for writing"); + throw utils::error::create_exception({ + function_name, + "file is not open for writing", + path_, + }); } auto res = fseeko(file_.get(), static_cast(offset), SEEK_SET); if (res == -1) { - throw std::runtime_error("failed to seek before write"); + throw utils::error::create_exception({ + function_name, + "failed to seek before write", + path_, + }); } std::size_t bytes_written{0U}; @@ -478,7 +519,11 @@ auto file::write(const unsigned char *data, std::size_t to_write, fwrite(reinterpret_cast(&data[bytes_written]), 1U, to_write - bytes_written, file_.get()); if (not feof(file_.get()) && ferror(file_.get())) { - throw std::runtime_error("failed to write file bytes"); + throw utils::error::create_exception({ + function_name, + "failed to write file bytes", + path_, + }); } if (written == 0U) { @@ -510,12 +555,20 @@ auto file::size() const -> std::optional { try { if (file_) { if (fseeko(file_.get(), 0, SEEK_END) == -1) { - throw std::runtime_error("failed to seek"); + throw utils::error::create_exception({ + function_name, + "failed to seek", + path_, + }); } auto size = ftello(file_.get()); if (size == -1) { - throw std::runtime_error("failed to get position"); + throw utils::error::create_exception({ + function_name, + "failed to get position", + path_, + }); } return static_cast(size); @@ -523,7 +576,11 @@ auto file::size() const -> std::optional { std::uint64_t size{}; if (not get_file_size(path_, size)) { - throw std::runtime_error("failed to get file size"); + throw utils::error::create_exception({ + function_name, + "failed to get file size", + path_, + }); } return size; diff --git a/support/src/utils/file_smb_directory.cpp b/support/src/utils/file_smb_directory.cpp index cb223bf7..d5f2aaa1 100644 --- a/support/src/utils/file_smb_directory.cpp +++ b/support/src/utils/file_smb_directory.cpp @@ -50,8 +50,12 @@ auto smb_directory::open(std::string_view host, std::string_view user, if (res != DSM_SUCCESS) { res = inet_pton(AF_INET, std::string{host}.c_str(), &addr.sin_addr); if (res != 1) { - throw std::runtime_error("failed to resolve host|" + std::string{host} + - '|' + std::to_string(errno)); + throw utils::error::create_exception({ + function_name, + "failed to resolve host", + std::to_string(utils::get_last_error_code()), + host, + }); } } @@ -59,8 +63,12 @@ auto smb_directory::open(std::string_view host, std::string_view user, static_cast(addr.sin_addr.s_addr), SMB_TRANSPORT_TCP); if (res != DSM_SUCCESS) { - throw std::runtime_error("failed to connect to host|" + - std::string{host} + '|' + std::to_string(res)); + throw utils::error::create_exception({ + function_name, + "failed to connect to host", + std::to_string(res), + host, + }); } smb_session_set_creds(session.get(), std::string{host}.c_str(), @@ -68,9 +76,13 @@ auto smb_directory::open(std::string_view host, std::string_view user, std::string{password}.c_str()); res = smb_session_login(session.get()); if (res != DSM_SUCCESS) { - throw std::runtime_error("failed to logon to host|" + std::string{host} + - '|' + std::string{user} + '|' + - std::to_string(res)); + throw utils::error::create_exception({ + function_name, + "failed to logon to host", + std::to_string(res), + host, + user, + }); } auto share_name = utils::string::split(path, '/', false).at(0U); @@ -78,9 +90,12 @@ auto smb_directory::open(std::string_view host, std::string_view user, smb_tid tid{}; res = smb_tree_connect(session.get(), share_name.c_str(), &tid); if (res != DSM_SUCCESS) { - throw std::runtime_error("failed to connect to share|" + - std::string{share_name} + '|' + - std::to_string(res)); + throw utils::error::create_exception({ + function_name, + "failed to connect to share", + std::to_string(res), + share_name, + }); } return smb_directory_t{ @@ -115,13 +130,22 @@ auto smb_directory::copy_to(std::string_view new_path, try { if (not session_) { - throw std::runtime_error("session not found|" + path_); + throw utils::error::create_exception({ + function_name, + "session not found", + path_, + }); } // auto to_path = utils::path::absolute(new_path); - throw std::runtime_error("failed to copy directory|" + path_ + '|' + - std::string{new_path} + "|not implemented"); + throw utils::error::create_exception({ + function_name, + "failed to copy directory", + "not implemented", + path_, + new_path, + }); } catch (const std::exception &e) { utils::error::handle_exception(function_name, e); } catch (...) { @@ -136,7 +160,11 @@ auto smb_directory::count(bool recursive) const -> std::uint64_t { try { if (not session_) { - throw std::runtime_error("session not found|" + path_); + throw utils::error::create_exception({ + function_name, + "session not found", + path_, + }); } smb_stat_list_t list{ @@ -149,8 +177,13 @@ auto smb_directory::count(bool recursive) const -> std::uint64_t { return count; } - throw std::runtime_error("failed to get directory count recursively|" + - path_ + "|not implemented"); + throw utils::error::create_exception({ + function_name, + "failed to get directory count recursively", + "not implemented", + utils::string::from_bool(recursive), + path_, + }); } catch (const std::exception &e) { utils::error::handle_exception(function_name, e); } catch (...) { @@ -166,7 +199,11 @@ auto smb_directory::create_directory(std::string_view path) const try { if (not session_) { - throw std::runtime_error("session not found|" + path_); + throw utils::error::create_exception({ + function_name, + "session not found", + path_, + }); } auto dir = get_directory(path); @@ -178,8 +215,12 @@ auto smb_directory::create_directory(std::string_view path) const session_.get(), tid_, smb_create_and_validate_relative_path(path_, path).c_str()); if (res != DSM_SUCCESS) { - throw std::runtime_error("failed to create directory|" + path_ + '/' + - std::string{path} + '|' + std::to_string(res)); + throw utils::error::create_exception({ + function_name, + "failed to create directory", + std::to_string(res), + path_, + }); } return get_directory(path); @@ -198,14 +239,21 @@ auto smb_directory::create_file(std::string_view file_name, try { if (not session_) { - throw std::runtime_error("session not found|" + path_); + throw utils::error::create_exception({ + function_name, + "session not found", + path_, + }); } auto fs_file = get_file(file_name); if (fs_file) { if (not dynamic_cast(fs_file.get())->open(read_only)) { - throw std::runtime_error("failed to open existing file|" + - std::string{file_name}); + throw utils::error::create_exception({ + function_name, + "failed to open existing file", + file_name, + }); } return fs_file; @@ -243,7 +291,11 @@ auto smb_directory::exists() const -> bool { try { if (not session_) { - throw std::runtime_error("session not found|" + path_); + throw utils::error::create_exception({ + function_name, + "session not found", + path_, + }); } smb_stat_t st{ @@ -271,7 +323,11 @@ auto smb_directory::get_directory(std::string_view path) const try { if (not session_) { - throw std::runtime_error("session not found|" + path_); + throw utils::error::create_exception({ + function_name, + "session not found", + path_, + }); } auto rel_path = smb_create_and_validate_relative_path(path_, path); @@ -280,12 +336,20 @@ auto smb_directory::get_directory(std::string_view path) const smb_stat_deleter(), }; if (not st) { - throw std::runtime_error("failed to stat directory|" + rel_path); + throw utils::error::create_exception({ + function_name, + "failed to stat directory", + rel_path, + }); } bool is_dir{smb_stat_get(st.get(), SMB_STAT_ISDIR) != 0U}; if (not is_dir) { - throw std::runtime_error("path is not a directory|" + rel_path); + throw utils::error::create_exception({ + function_name, + "path is not a directory", + rel_path, + }); } return smb_directory_t{ @@ -311,7 +375,11 @@ auto smb_directory::get_directories() const -> std::vector { try { if (not session_) { - throw std::runtime_error("session not found|" + path_); + throw utils::error::create_exception({ + function_name, + "session not found", + path_, + }); } smb_stat_list_t list{ smb_find(session_.get(), tid_, smb_create_search_path(path_).c_str()), @@ -319,7 +387,11 @@ auto smb_directory::get_directories() const -> std::vector { smb_stat_list_deleter(), }; if (not list) { - throw std::runtime_error("failed to get directory list|" + path_); + throw utils::error::create_exception({ + function_name, + "failed to get directory list", + path_, + }); } std::vector ret{}; @@ -370,7 +442,11 @@ auto smb_directory::get_file(std::string_view path) const -> fs_file_t { try { if (not session_) { - throw std::runtime_error("session not found|" + path_); + throw utils::error::create_exception({ + function_name, + "session not found", + path_, + }); } auto rel_path = smb_create_and_validate_relative_path(path_, path); @@ -379,12 +455,20 @@ auto smb_directory::get_file(std::string_view path) const -> fs_file_t { smb_stat_deleter(), }; if (not st) { - throw std::runtime_error("failed to stat file|" + rel_path); + throw utils::error::create_exception({ + function_name, + "failed to stat file", + rel_path, + }); } bool is_dir{smb_stat_get(st.get(), SMB_STAT_ISDIR) != 0U}; if (is_dir) { - throw std::runtime_error("path is not a file|" + rel_path); + throw utils::error::create_exception({ + function_name, + "path is not a file", + rel_path, + }); } return std::make_unique( @@ -404,7 +488,11 @@ auto smb_directory::get_files() const -> std::vector { try { if (not session_) { - throw std::runtime_error("session not found|" + path_); + throw utils::error::create_exception({ + function_name, + "session not found", + path_, + }); } smb_stat_list_t list{ @@ -412,7 +500,11 @@ auto smb_directory::get_files() const -> std::vector { smb_stat_list_deleter(), }; if (not list) { - throw std::runtime_error("failed to get file list|" + path_); + throw utils::error::create_exception({ + function_name, + "failed to get file list", + path_, + }); } std::vector ret{}; @@ -453,7 +545,11 @@ auto smb_directory::get_items() const -> std::vector { try { if (not session_) { - throw std::runtime_error("session not found|" + path_); + throw utils::error::create_exception({ + function_name, + "session not found", + path_, + }); } smb_stat_list_t list{ @@ -461,7 +557,11 @@ auto smb_directory::get_items() const -> std::vector { smb_stat_list_deleter(), }; if (not list) { - throw std::runtime_error("failed to get item list|" + path_); + throw utils::error::create_exception({ + function_name, + "failed to get item list", + path_, + }); } std::vector ret{}; @@ -530,7 +630,11 @@ auto smb_directory::is_symlink() const -> bool { try { if (not session_) { - throw std::runtime_error("session not found|" + path_); + throw utils::error::create_exception({ + function_name, + "session not found", + path_, + }); } } catch (const std::exception &e) { @@ -547,11 +651,20 @@ auto smb_directory::move_to(std::string_view new_path) -> bool { try { if (not session_) { - throw std::runtime_error("session not found|" + path_); + throw utils::error::create_exception({ + function_name, + "session not found", + path_, + }); } - throw std::runtime_error("failed to move directory|" + path_ + '|' + - std::string{new_path} + "|not implemented"); + throw utils::error::create_exception({ + function_name, + "failed to move directory", + "not implemented", + path_, + new_path, + }); } catch (const std::exception &e) { utils::error::handle_exception(function_name, e); } catch (...) { @@ -566,7 +679,11 @@ auto smb_directory::remove() -> bool { try { if (not session_) { - throw std::runtime_error("session not found|" + path_); + throw utils::error::create_exception({ + function_name, + "session not found", + path_, + }); } return utils::retry_action([this]() -> bool { @@ -578,8 +695,12 @@ auto smb_directory::remove() -> bool { auto res = smb_directory_rm(session_.get(), tid_, smb_create_relative_path(path_).c_str()); if (res != DSM_SUCCESS) { - throw std::runtime_error("failed to remove directory|" + path_ + '|' + - std::to_string(res)); + throw utils::error::create_exception({ + function_name, + "failed to remove directory", + std::to_string(res), + path_, + }); } return true; @@ -605,15 +726,23 @@ auto smb_directory::remove_recursively() -> bool { try { if (not session_) { - throw std::runtime_error("session not found|" + path_); + throw utils::error::create_exception({ + function_name, + "session not found", + path_, + }); } if (not exists()) { return true; } - throw std::runtime_error("failed to remove directory recursively|" + path_ + - "|not implemented"); + throw utils::error::create_exception({ + function_name, + "failed to remove directory recursively", + "not implemented", + path_, + }); } catch (const std::exception &e) { utils::error::handle_exception(function_name, e); } catch (...) { @@ -628,11 +757,19 @@ auto smb_directory::size(bool /* recursive */) const -> std::uint64_t { try { if (not session_) { - throw std::runtime_error("session not found|" + path_); + throw utils::error::create_exception({ + function_name, + "session not found", + path_, + }); } - throw std::runtime_error("failed to get directory size|" + path_ + - "|not implemented"); + throw utils::error::create_exception({ + function_name, + "failed to get directory size", + "not implemented", + path_, + }); } catch (const std::exception &e) { utils::error::handle_exception(function_name, e); } catch (...) { diff --git a/support/src/utils/file_smb_file.cpp b/support/src/utils/file_smb_file.cpp index 1bd669c1..908a322c 100644 --- a/support/src/utils/file_smb_file.cpp +++ b/support/src/utils/file_smb_file.cpp @@ -41,14 +41,23 @@ auto smb_file::copy_to(std::string_view new_path, try { if (not session_) { - throw std::runtime_error("session not found|" + path_); + throw utils::error::create_exception({ + function_name, + "session not found", + path_, + }); } // auto to_path = utils::path::absolute(new_path); - throw std::runtime_error("failed to copy file|" + path_ + '|' + - std::string{new_path} + '|' + - std::to_string(overwrite) + "|not implemented"); + throw utils::error::create_exception({ + function_name, + "failed to copy file", + "not implemented", + std::to_string(overwrite), + path_, + new_path, + }); } catch (const std::exception &e) { utils::error::handle_exception(function_name, e); } catch (...) { @@ -63,7 +72,11 @@ auto smb_file::exists() const -> bool { try { if (not session_) { - throw std::runtime_error("session not found|" + path_); + throw utils::error::create_exception({ + function_name, + "session not found", + path_, + }); } smb_stat_t st{ @@ -89,8 +102,12 @@ void smb_file::flush() const { REPERTORY_USES_FUNCTION_NAME(); try { - throw std::runtime_error("failed to flush file|" + path_ + - "|not implemented"); + throw utils::error::create_exception({ + function_name, + "failed to flush file", + "not implemented", + path_, + }); } catch (const std::exception &e) { utils::error::handle_exception(function_name, e); } catch (...) { @@ -104,7 +121,11 @@ auto smb_file::get_time(smb_session *session, smb_tid tid, std::string path, try { if (session == nullptr) { - throw std::runtime_error("session not found|" + path); + throw utils::error::create_exception({ + function_name, + "session not found", + path_, + }); } auto rel_path = smb_create_relative_path(path); @@ -113,7 +134,12 @@ auto smb_file::get_time(smb_session *session, smb_tid tid, std::string path, smb_stat_deleter(), }; if (not st) { - throw std::runtime_error("failed to stat directory|" + rel_path); + throw utils::error::create_exception({ + function_name, + "failed to stat file", + "not implemented", + rel_path, + }); } switch (type) { @@ -143,7 +169,11 @@ auto smb_file::is_symlink() const -> bool { try { if (not session_) { - throw std::runtime_error("session not found|" + path_); + throw utils::error::create_exception({ + function_name, + "session not found", + path_, + }); } } catch (const std::exception &e) { @@ -160,9 +190,13 @@ auto smb_file::move_to(std::string_view new_path) -> bool { try { if (utils::string::begins_with(new_path, "//")) { - throw std::runtime_error("failed to move file|" + path_ + '|' + - std::string{new_path} + - "|new path must be in same share"); + throw utils::error::create_exception({ + function_name, + "failed to move file", + "new path must be in same share", + path_, + new_path, + }); } auto from_path = smb_create_relative_path(path_); @@ -179,15 +213,23 @@ auto smb_file::move_to(std::string_view new_path) -> bool { auto res = smb_tree_connect(session_.get(), share_name_.c_str(), &tid_); if (res != DSM_SUCCESS) { - throw std::runtime_error("failed to connect to share|" + share_name_ + - '|' + std::to_string(res)); + throw utils::error::create_exception({ + function_name, + "failed to connect to share", + path_std::to_string(res), + share_name_, + }); } res = smb_file_mv(session_.get(), tid_, from_path.c_str(), to_path.c_str()); if (res != DSM_SUCCESS) { - throw std::runtime_error("failed to move file|" + path_ + '|' + - from_path + '|' + to_path + '|' + - std::to_string(res)); + throw utils::error::create_exception({ + function_name, + "failed to move file", + path_std::to_string(res), + from_path, + to_path, + }); } path_ = smb_create_smb_path(path_, to_path); @@ -221,17 +263,26 @@ auto smb_file::open(bool read_only) -> bool { auto res = smb_tree_connect(session_.get(), share_name_.c_str(), &tid_); if (res != DSM_SUCCESS) { - throw std::runtime_error("failed to connect to share|" + share_name_ + - '|' + std::to_string(res)); + throw utils::error::create_exception({ + function_name, + "failed to connect to share", + path_std::to_string(res), + share_name_, + }); } smb_fd fd{}; res = smb_fopen(session_.get(), tid_, rel_path.c_str(), read_only ? SMB_MOD_RO : SMB_MOD_RW2, &fd); if (res != DSM_SUCCESS) { - throw std::runtime_error("failed to open file|" + path_ + '|' + rel_path + - '|' + utils::string::from_bool(read_only) + '|' + - std::to_string(res)); + throw utils::error::create_exception({ + function_name, + "failed to open file", + utils::string::from_bool(read_only), + path_std::to_string(res), + path_, + rel_path, + }); } fd_ = fd; @@ -257,16 +308,24 @@ auto smb_file::read(unsigned char *data, std::size_t to_read, } if (not fd_.has_value()) { - throw std::runtime_error("failed to read file|" + path_ + - "|file not open"); + throw utils::error::create_exception({ + function_name, + "failed to read file", + "file not open", + path_, + }); } auto res = smb_fseek(session_.get(), *fd_, static_cast(offset), SMB_SEEK_SET); if (res == -1) { - throw std::runtime_error("failed to seek file|" + path_ + '|' + - std::to_string(offset) + '|' + - std::to_string(res)); + throw utils::error::create_exception({ + function_name, + "failed to seek file", + std::to_string(res), + std::to_string(offset), + path_, + }); } std::size_t bytes_read{0U}; @@ -274,9 +333,14 @@ auto smb_file::read(unsigned char *data, std::size_t to_read, res = smb_fread(session_.get(), *fd_, &data[bytes_read], to_read - bytes_read); if (res == -1) { - throw std::runtime_error("failed to read file|" + path_ + '|' + - std::to_string(to_read) + '|' + - std::to_string(res)); + throw utils::error::create_exception({ + function_name, + "failed to read file", + std::to_string(res), + std::to_string(offset), + std::to_string(to_read), + path_, + }); } if (res == 0) { @@ -314,17 +378,25 @@ auto smb_file::remove() -> bool { try { auto res = smb_tree_connect(session_.get(), share_name_.c_str(), &tid_); if (res != DSM_SUCCESS) { - throw std::runtime_error("failed to connect to share|" + share_name_ + - '|' + std::to_string(res)); + throw utils::error::create_exception({ + function_name, + "failed to connect to share", + path_std::to_string(res), + share_name_, + }); } auto rel_path = smb_create_relative_path(path_); res = smb_file_rm(session_.get(), tid_, rel_path.c_str()); if (res != DSM_SUCCESS) { - throw std::runtime_error( - "failed to remove file|" + path_ + '|' + rel_path + '|' + - std::to_string(res) + '|' + - std::to_string(smb_session_get_nt_status(session_.get()))); + throw utils::error::create_exception({ + function_name, + "failed to remove file", + std::to_string(res), + std::to_string(smb_session_get_nt_status(session_.get())), + path_, + rel_path, + }); } return true; @@ -350,7 +422,11 @@ auto smb_file::size() const -> std::optional { try { if (not session_) { - throw std::runtime_error("session not found|" + path_); + throw utils::error::create_exception({ + function_name, + "session not found", + path_, + }); } auto rel_path = smb_create_relative_path(path_); @@ -359,7 +435,11 @@ auto smb_file::size() const -> std::optional { smb_stat_deleter(), }; if (not st) { - throw std::runtime_error("failed to stat directory|" + rel_path); + throw utils::error::create_exception({ + function_name, + "failed to stat directory", + rel_path, + }); } return smb_stat_get(st.get(), SMB_STAT_SIZE); @@ -376,8 +456,13 @@ auto smb_file::truncate(std::size_t size) -> bool { REPERTORY_USES_FUNCTION_NAME(); try { - throw std::runtime_error("failed to truncate file|" + path_ + '|' + - std::to_string(size) + "|not implemented"); + throw utils::error::create_exception({ + function_name, + "failed to truncate file", + "not implemented", + std::to_string(size), + path_, + }); } catch (const std::exception &e) { utils::error::handle_exception(function_name, e); } catch (...) { @@ -397,16 +482,24 @@ auto smb_file::write(const unsigned char *data, std::size_t to_write, } if (not fd_.has_value()) { - throw std::runtime_error("failed to write file|" + path_ + - "|file not open"); + throw utils::error::create_exception({ + function_name, + "failed to write file", + "file not open", + path_, + }); } auto res = smb_fseek(session_.get(), *fd_, static_cast(offset), SMB_SEEK_SET); if (res == -1) { - throw std::runtime_error("failed to seek file|" + path_ + '|' + - std::to_string(offset) + '|' + - std::to_string(res)); + throw utils::error::create_exception({ + function_name, + "failed to seek file", + std::to_string(res), + std::to_string(offset), + path_, + }); } std::size_t bytes_written{0U}; @@ -415,9 +508,14 @@ auto smb_file::write(const unsigned char *data, std::size_t to_write, const_cast(&data[bytes_written]), to_write - bytes_written); if (res == -1) { - throw std::runtime_error("failed to write file|" + path_ + '|' + - std::to_string(to_write) + '|' + - std::to_string(res)); + throw utils::error::create_exception({ + function_name, + "failed to write file", + std::to_string(res), + std::to_string(offset), + std::to_string(to_write), + path_, + }); } if (res == 0) { diff --git a/support/src/utils/hash.cpp b/support/src/utils/hash.cpp index 9dce122f..cda40959 100644 --- a/support/src/utils/hash.cpp +++ b/support/src/utils/hash.cpp @@ -23,6 +23,8 @@ #include "utils/hash.hpp" +#include "utils/error.hpp" + namespace repertory::utils::encryption { auto create_hash_blake2b_256(std::string_view data) -> hash_256_t { return create_hash_blake2b_t( @@ -111,24 +113,36 @@ auto create_hash_sha512(const data_buffer &data) -> hash_512_t { auto create_hash_sha512(const unsigned char *data, std::size_t data_size) -> hash_512_t { + REPERTORY_USES_FUNCTION_NAME(); + hash_512_t hash{}; crypto_hash_sha512_state state{}; auto res = crypto_hash_sha512_init(&state); if (res != 0) { - throw std::runtime_error("failed to initialize sha-512|" + - std::to_string(res)); + throw utils::error::create_exception({ + function_name, + "failed to initialize sha-512", + std::to_string(res), + }); } res = crypto_hash_sha512_update(&state, data, data_size); if (res != 0) { - throw std::runtime_error("failed to update sha-512|" + std::to_string(res)); + throw utils::error::create_exception({ + function_name, + "failed to update sha-512", + std::to_string(res), + }); } res = crypto_hash_sha512_final(&state, hash.data()); if (res != 0) { - throw std::runtime_error("failed to finalize sha-512|" + - std::to_string(res)); + throw utils::error::create_exception({ + function_name, + "failed to finalize sha-512", + std::to_string(res), + }); } return hash; @@ -136,24 +150,36 @@ auto create_hash_sha512(const unsigned char *data, auto create_hash_sha256(const unsigned char *data, std::size_t data_size) -> hash_256_t { + REPERTORY_USES_FUNCTION_NAME(); + hash_256_t hash{}; crypto_hash_sha256_state state{}; auto res = crypto_hash_sha256_init(&state); if (res != 0) { - throw std::runtime_error("failed to initialize sha-256|" + - std::to_string(res)); + throw utils::error::create_exception({ + function_name, + "failed to initialize sha-256", + std::to_string(res), + }); } res = crypto_hash_sha256_update(&state, data, data_size); if (res != 0) { - throw std::runtime_error("failed to update sha-256|" + std::to_string(res)); + throw utils::error::create_exception({ + function_name, + "failed to update sha-256", + std::to_string(res), + }); } res = crypto_hash_sha256_final(&state, hash.data()); if (res != 0) { - throw std::runtime_error("failed to finalize sha-256|" + - std::to_string(res)); + throw utils::error::create_exception({ + function_name, + "failed to finalize sha-256", + std::to_string(res), + }); } return hash; diff --git a/support/src/utils/path.cpp b/support/src/utils/path.cpp index bd3e8a41..a742f9e9 100644 --- a/support/src/utils/path.cpp +++ b/support/src/utils/path.cpp @@ -29,6 +29,8 @@ namespace { [[nodiscard]] auto resolve(std::string path) -> std::string { + REPERTORY_USES_FUNCTION_NAME(); + #if defined(_WIN32) if (repertory::utils::string::contains(path, "~\\")) { repertory::utils::string::replace(path, "~\\", "%USERPROFILE%\\"); @@ -63,7 +65,11 @@ namespace { } }); if (res) { - throw std::runtime_error("failed to getpwuid: " + res.reason); + throw repertory::utils::error::create_exception({ + function_name, + "failed to getpwuid", + res.reason, + }); } path = repertory::utils::string::replace(path, "~/", home + "/"); diff --git a/support/src/utils/windows.cpp b/support/src/utils/windows.cpp index 6935f513..273569dd 100644 --- a/support/src/utils/windows.cpp +++ b/support/src/utils/windows.cpp @@ -24,6 +24,7 @@ #include "utils/windows.hpp" #include "utils/com_init_wrapper.hpp" +#include "utils/error.hpp" #include "utils/string.hpp" namespace repertory::utils { @@ -56,13 +57,13 @@ void create_console() { std::wcin.clear(); } -void free_console() { - ::FreeConsole(); -} +void free_console() { ::FreeConsole(); } auto get_last_error_code() -> DWORD { return ::GetLastError(); } auto get_local_app_data_directory() -> const std::string & { + REPERTORY_USES_FUNCTION_NAME(); + static std::string app_data = ([]() -> std::string { com_init_wrapper cw; PWSTR local_app_data{}; @@ -73,7 +74,10 @@ auto get_local_app_data_directory() -> const std::string & { return ret; } - throw std::runtime_error("unable to detect local application data folder"); + throw utils::error::create_exception({ + function_name, + "unable to detect local application data folder", + }); })(); return app_data; diff --git a/support/test/src/utils/db_sqlite_test.cpp b/support/test/src/utils/db_sqlite_test.cpp index c4351a37..9575ca28 100644 --- a/support/test/src/utils/db_sqlite_test.cpp +++ b/support/test/src/utils/db_sqlite_test.cpp @@ -64,8 +64,8 @@ public: void TearDown() override { db3.reset(); } }; -static void common_insert(sqlite3 &db, bool dump = false) { - auto query = utils::db::sqlite::db_insert{db, "table"} +static void common_insert(sqlite3 &db3, bool dump = false) { + auto query = utils::db::sqlite::db_insert{db3, "table"} .column_value("column1", "test0") .column_value("column2", "test1"); if (dump) { @@ -76,9 +76,9 @@ static void common_insert(sqlite3 &db, bool dump = false) { EXPECT_TRUE(res.ok()); } -static void common_select(sqlite3 &db, std::string value1, std::string value2, +static void common_select(sqlite3 &db3, std::string value1, std::string value2, bool dump = false) { - auto query = utils::db::sqlite::db_select{db, "table"}; + auto query = utils::db::sqlite::db_select{db3, "table"}; if (dump) { std::cout << query.dump() << std::endl; } @@ -113,9 +113,9 @@ static void common_select(sqlite3 &db, std::string value1, std::string value2, EXPECT_EQ(std::size_t(1U), row_count); } -static void common_delete(sqlite3 &db, bool dump = false) { +static void common_delete(sqlite3 &db3, bool dump = false) { { - auto query = utils::db::sqlite::db_delete{db, "table"}; + auto query = utils::db::sqlite::db_delete{db3, "table"}; if (dump) { std::cout << query.dump() << std::endl; } @@ -125,7 +125,7 @@ static void common_delete(sqlite3 &db, bool dump = false) { } { - auto query = utils::db::sqlite::db_select{db, "table"}; + auto query = utils::db::sqlite::db_select{db3, "table"}; auto res = query.go(); EXPECT_TRUE(res.ok());