From 5ab7301cbe0c301422f5cecbc0d32a25a61e3cc3 Mon Sep 17 00:00:00 2001 From: "Scott E. Graves" Date: Thu, 31 Jul 2025 06:58:43 -0500 Subject: [PATCH] v2.0.7-release (#56) Reviewed-on: https://git.fifthgrid.com/BlockStorage/repertory/pulls/56 --- CHANGELOG.md | 6 ++ config.sh | 2 +- .../fuse/remotefuse/remote_fuse_drive.cpp | 50 +++++++---- repertory/repertory/src/ui/handlers.cpp | 83 +++++++++++-------- 4 files changed, 91 insertions(+), 50 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index d3674096..0243d81b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,11 @@ # Changelog +## v2.0.7-release + +### Issues +* \#55 [bug] UI is unable to launch `repertory.exe` on Windows when absolute path contains spaces +* \#57 [bug] Directory entries . and .. are incorrectly being reported as files in Linux remote mounts + ## v2.0.6-release ### Issues diff --git a/config.sh b/config.sh index da28760a..5fe91976 100755 --- a/config.sh +++ b/config.sh @@ -10,7 +10,7 @@ PROJECT_DESC="Mount utility for Sia and S3" PROJECT_MAJOR_VERSION=2 PROJECT_MINOR_VERSION=0 -PROJECT_REVISION_VERSION=6 +PROJECT_REVISION_VERSION=7 PROJECT_RELEASE_NUM=1 PROJECT_RELEASE_ITER=release diff --git a/repertory/librepertory/src/drives/fuse/remotefuse/remote_fuse_drive.cpp b/repertory/librepertory/src/drives/fuse/remotefuse/remote_fuse_drive.cpp index f86d991a..f2ae5aea 100644 --- a/repertory/librepertory/src/drives/fuse/remotefuse/remote_fuse_drive.cpp +++ b/repertory/librepertory/src/drives/fuse/remotefuse/remote_fuse_drive.cpp @@ -102,7 +102,7 @@ void remote_fuse_drive::destroy_impl(void *ptr) { } if (remote_instance_) { - const auto res = remote_instance_->fuse_destroy(); + auto res = remote_instance_->fuse_destroy(); if (res != 0) { utils::error::raise_error(function_name, "remote fuse_destroy() failed|err|" + @@ -128,8 +128,8 @@ auto remote_fuse_drive::fgetattr_impl(std::string api_path, remote::stat r_stat{}; auto directory = false; - const auto res = remote_instance_->fuse_fgetattr(api_path.c_str(), r_stat, - directory, f_info->fh); + auto res = remote_instance_->fuse_fgetattr(api_path.c_str(), r_stat, + directory, f_info->fh); if (res == 0) { populate_stat(r_stat, directory, *unix_st); } @@ -191,7 +191,7 @@ auto remote_fuse_drive::getattr_impl(std::string api_path, struct stat *unix_st) bool directory = false; remote::stat r_stat{}; - const auto res = + auto res = remote_instance_->fuse_getattr(api_path.c_str(), r_stat, directory); if (res == 0) { populate_stat(r_stat, directory, *unix_st); @@ -208,9 +208,9 @@ api_error remote_fuse_drive::getxtimes_impl(std::string api_path, return utils::to_api_error(-EFAULT); } - remote::file_time repertory_bkuptime = 0u; - remote::file_time repertory_crtime = 0u; - const auto res = remote_instance_->fuse_getxtimes( + remote::file_time repertory_bkuptime{0U}; + remote::file_time repertory_crtime{0U}; + auto res = remote_instance_->fuse_getxtimes( api_path.c_str(), repertory_bkuptime, repertory_crtime); if (res == 0) { bkuptime->tv_nsec = @@ -381,7 +381,7 @@ auto remote_fuse_drive::readdir_impl(std::string api_path, void *buf, fuse_fill_dir_t fuse_fill_dir, off_t offset, struct fuse_file_info *f_info, - fuse_readdir_flags /*flags*/) + fuse_readdir_flags /* flags */) -> api_error { #else // FUSE_USE_VERSION < 30 auto remote_fuse_drive::readdir_impl(std::string api_path, void *buf, @@ -390,20 +390,42 @@ auto remote_fuse_drive::readdir_impl(std::string api_path, void *buf, struct fuse_file_info *f_info) -> api_error { #endif // FUSE_USE_VERSION >= 30 + std::string item_path; - int res = 0; + int res{0}; while ((res = remote_instance_->fuse_readdir( api_path.c_str(), static_cast(offset), f_info->fh, item_path)) == 0) { - if ((item_path != ".") && (item_path != "..")) { + std::unique_ptr p_stat{nullptr}; + int stat_res{0}; + if ((item_path == ".") || (item_path == "..")) { + p_stat = std::make_unique(); + std::memset(p_stat.get(), 0, sizeof(struct stat)); + if (item_path == ".") { + stat_res = + stat(utils::path::combine(get_mount_location(), {api_path}).c_str(), + p_stat.get()); + } else { + stat_res = + stat(utils::path::get_parent_path( + utils::path::combine(get_mount_location(), {api_path})) + .c_str(), + p_stat.get()); + } + + if (stat_res != 0) { + res = stat_res; + break; + } + } else { item_path = utils::path::strip_to_file_name(item_path); } #if FUSE_USE_VERSION >= 30 - if (fuse_fill_dir(buf, item_path.c_str(), nullptr, ++offset, - static_cast(0)) != 0) { + if (fuse_fill_dir(buf, item_path.c_str(), p_stat.get(), ++offset, + FUSE_FILL_DIR_PLUS) != 0) { #else // FUSE_USE_VERSION < 30 - if (fuse_fill_dir(buf, item_path.c_str(), nullptr, ++offset) != 0) { + if (fuse_fill_dir(buf, item_path.c_str(), p_stat.get(), ++offset) != 0) { #endif // FUSE_USE_VERSION >= 30 break; } @@ -592,7 +614,7 @@ auto remote_fuse_drive::write_impl(std::string api_path, const char *buffer, size_t write_size, off_t write_offset, struct fuse_file_info *f_info, std::size_t &bytes_written) -> api_error { - const auto res = remote_instance_->fuse_write( + auto res = remote_instance_->fuse_write( api_path.c_str(), buffer, write_size, static_cast(write_offset), f_info->fh); if (res >= 0) { diff --git a/repertory/repertory/src/ui/handlers.cpp b/repertory/repertory/src/ui/handlers.cpp index b5e2edf7..8da7e00d 100644 --- a/repertory/repertory/src/ui/handlers.cpp +++ b/repertory/repertory/src/ui/handlers.cpp @@ -38,6 +38,7 @@ #include #include #include +namespace bp1 = boost::process::v1; namespace { [[nodiscard]] auto decrypt(std::string_view data, std::string_view password) @@ -227,23 +228,6 @@ handlers::handlers(mgmt_app_config *config, httplib::Server *server) handle_put_settings(req, res); }); - static std::atomic this_server{server_}; - static const auto quit_handler = [](int /* sig */) { - auto *ptr = this_server.load(); - if (ptr == nullptr) { - return; - } - - this_server = nullptr; - ptr->stop(); - }; - - std::signal(SIGINT, quit_handler); -#if !defined(_WIN32) - std::signal(SIGQUIT, quit_handler); -#endif // !defined(_WIN32) - std::signal(SIGTERM, quit_handler); - #if defined(_WIN32) system(fmt::format( R"(start "Repertory Management Portal" "http://127.0.0.1:{}/ui")", @@ -270,6 +254,23 @@ handlers::handlers(mgmt_app_config *config, httplib::Server *server) return; } + static std::atomic this_server{server_}; + static const auto quit_handler = [](int /* sig */) { + auto *ptr = this_server.load(); + if (ptr == nullptr) { + return; + } + + this_server = nullptr; + ptr->stop(); + }; + + std::signal(SIGINT, quit_handler); +#if !defined(_WIN32) + std::signal(SIGQUIT, quit_handler); +#endif // !defined(_WIN32) + std::signal(SIGTERM, quit_handler); + event_system::instance().start(); nonce_thread_ = @@ -711,19 +712,37 @@ auto handlers::launch_process(provider_type prov, std::string_view name, recur_mutex_lock inst_lock(inst_mtx); if (background) { #if defined(_WIN32) - std::array path{}; - ::GetSystemDirectoryA(path.data(), path.size()); + args.insert(args.begin(), "--hidden"); - args.insert(args.begin(), utils::path::combine(path.data(), {"cmd.exe"})); - args.insert(std::next(args.begin()), "/c"); - args.insert(std::next(args.begin(), 2U), "start"); - args.insert(std::next(args.begin(), 3U), ""); - args.insert(std::next(args.begin(), 4U), "/MIN"); - args.insert(std::next(args.begin(), 5U), repertory_binary_); + auto cmdline = fmt::format("{}{}{}", '"', repertory_binary_, '"'); + for (const auto &arg : args) { + cmdline += " "; + if (arg.find_first_of(" \t") != std::string::npos) { + cmdline += fmt::format("{}{}{}", '"', arg, '"'); + } else { + cmdline += arg; + } + } + + STARTUPINFOA start_info{}; + start_info.cb = sizeof(start_info); + start_info.dwFlags = STARTF_USESHOWWINDOW; + start_info.wShowWindow = SW_SHOWMINNOACTIVE; + + PROCESS_INFORMATION proc_info{}; + auto result = ::CreateProcessA( + nullptr, &cmdline[0U], nullptr, nullptr, FALSE, + CREATE_NEW_CONSOLE | CREATE_NEW_PROCESS_GROUP, nullptr, + utils::path::get_parent_path(repertory_binary_).c_str(), &start_info, + &proc_info); + + if (result) { + ::CloseHandle(proc_info.hProcess); + ::CloseHandle(proc_info.hThread); + } #else // !defined(_WIN32) - args.insert(args.begin(), "-f"); args.insert(args.begin(), repertory_binary_); -#endif // defined(_WIN32) + args.insert(std::next(args.begin()), "-f"); std::vector exec_args; exec_args.reserve(args.size() + 1U); @@ -732,10 +751,6 @@ auto handlers::launch_process(provider_type prov, std::string_view name, } exec_args.push_back(nullptr); -#if defined(_WIN32) - _spawnv(_P_DETACH, exec_args.at(0U), - const_cast(exec_args.data())); -#else // !defined(_WIN32) auto pid = fork(); if (pid < 0) { exit(1); @@ -769,10 +784,8 @@ auto handlers::launch_process(provider_type prov, std::string_view name, return {}; } - boost::process::v1::ipstream out; - boost::process::v1::child proc(repertory_binary_, - boost::process::v1::args(args), - boost::process::v1::std_out > out); + bp1::ipstream out; + bp1::child proc(repertory_binary_, bp1::args(args), bp1::std_out > out); std::string data; std::string line;