prefer execvp and _spawnv
All checks were successful
BlockStorage/repertory/pipeline/head This commit looks good
All checks were successful
BlockStorage/repertory/pipeline/head This commit looks good
This commit is contained in:
parent
1cc3e6baf0
commit
d301e8d871
@ -3,6 +3,7 @@ _mkgmtime
|
|||||||
_sh_denyno
|
_sh_denyno
|
||||||
_sh_denyrd
|
_sh_denyrd
|
||||||
_sh_denyrw
|
_sh_denyrw
|
||||||
|
_spawnv
|
||||||
aarch64
|
aarch64
|
||||||
advapi32
|
advapi32
|
||||||
armv8
|
armv8
|
||||||
@ -121,6 +122,7 @@ icui18n
|
|||||||
icuuc
|
icuuc
|
||||||
iostreams
|
iostreams
|
||||||
iphlpapi
|
iphlpapi
|
||||||
|
ipstream
|
||||||
jthread
|
jthread
|
||||||
libbitcoin
|
libbitcoin
|
||||||
libbitcoinsystem
|
libbitcoinsystem
|
||||||
@ -165,6 +167,7 @@ nuspell_version
|
|||||||
oleaut32
|
oleaut32
|
||||||
openal_version
|
openal_version
|
||||||
openssldir
|
openssldir
|
||||||
|
pistream
|
||||||
pkgconfig
|
pkgconfig
|
||||||
plarge_integer
|
plarge_integer
|
||||||
plex
|
plex
|
||||||
|
@ -23,7 +23,6 @@
|
|||||||
#define REPERTORY_INCLUDE_UI_HANDLERS_HPP_
|
#define REPERTORY_INCLUDE_UI_HANDLERS_HPP_
|
||||||
|
|
||||||
#include "events/consumers/console_consumer.hpp"
|
#include "events/consumers/console_consumer.hpp"
|
||||||
#include <unordered_map>
|
|
||||||
|
|
||||||
namespace repertory::ui {
|
namespace repertory::ui {
|
||||||
class mgmt_app_config;
|
class mgmt_app_config;
|
||||||
@ -74,7 +73,8 @@ private:
|
|||||||
void handle_put_settings(auto &&req, auto &&res) const;
|
void handle_put_settings(auto &&req, auto &&res) const;
|
||||||
|
|
||||||
auto launch_process(provider_type prov, std::string_view name,
|
auto launch_process(provider_type prov, std::string_view name,
|
||||||
std::string_view args, bool background = false) const
|
std::vector<std::string> args,
|
||||||
|
bool background = false) const
|
||||||
-> std::vector<std::string>;
|
-> std::vector<std::string>;
|
||||||
|
|
||||||
void set_key_value(provider_type prov, std::string_view name,
|
void set_key_value(provider_type prov, std::string_view name,
|
||||||
|
@ -35,6 +35,8 @@
|
|||||||
#include "utils/path.hpp"
|
#include "utils/path.hpp"
|
||||||
#include "utils/string.hpp"
|
#include "utils/string.hpp"
|
||||||
|
|
||||||
|
#include <boost/process.hpp>
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
[[nodiscard]] auto decrypt(std::string_view data, std::string_view password)
|
[[nodiscard]] auto decrypt(std::string_view data, std::string_view password)
|
||||||
-> std::string {
|
-> std::string {
|
||||||
@ -93,11 +95,6 @@ namespace {
|
|||||||
|
|
||||||
return std::string{value};
|
return std::string{value};
|
||||||
}
|
}
|
||||||
|
|
||||||
[[nodiscard]] constexpr auto is_restricted(std::string_view data) -> bool {
|
|
||||||
constexpr std::string_view invalid_chars = "&;|><$()`{}!*?";
|
|
||||||
return data.find_first_of(invalid_chars) != std::string_view::npos;
|
|
||||||
}
|
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|
||||||
namespace repertory::ui {
|
namespace repertory::ui {
|
||||||
@ -267,7 +264,7 @@ void handlers::handle_get_mount(auto &&req, auto &&res) const {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto lines = launch_process(prov, name, "-dc");
|
auto lines = launch_process(prov, name, {"-dc"});
|
||||||
|
|
||||||
if (lines.at(0U) != "0") {
|
if (lines.at(0U) != "0") {
|
||||||
throw utils::error::create_exception(function_name, {
|
throw utils::error::create_exception(function_name, {
|
||||||
@ -348,7 +345,8 @@ void handlers::handle_get_mount_status(auto &&req, auto &&res) const {
|
|||||||
switch (prov) {
|
switch (prov) {
|
||||||
case provider_type::remote: {
|
case provider_type::remote: {
|
||||||
auto parts = utils::string::split(name, '_', false);
|
auto parts = utils::string::split(name, '_', false);
|
||||||
status_name = fmt::format("{}{}:{}", status_name, parts[0U], parts[1U]);
|
status_name =
|
||||||
|
fmt::format("{}{}:{}", status_name, parts.at(0U), parts.at(1U));
|
||||||
} break;
|
} break;
|
||||||
|
|
||||||
case provider_type::encrypt:
|
case provider_type::encrypt:
|
||||||
@ -366,7 +364,7 @@ void handlers::handle_get_mount_status(auto &&req, auto &&res) const {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
auto lines = launch_process(prov, name, "-status");
|
auto lines = launch_process(prov, name, {"-status"});
|
||||||
|
|
||||||
nlohmann::json result(
|
nlohmann::json result(
|
||||||
nlohmann::json::parse(utils::string::join(lines, '\n')).at(status_name));
|
nlohmann::json::parse(utils::string::join(lines, '\n')).at(status_name));
|
||||||
@ -425,7 +423,7 @@ void handlers::handle_post_add_mount(auto &&req, auto &&res) const {
|
|||||||
values[key] = decrypted;
|
values[key] = decrypted;
|
||||||
}
|
}
|
||||||
|
|
||||||
launch_process(prov, name, "-gc");
|
launch_process(prov, name, {"-gc"});
|
||||||
for (auto &[key, value] : values) {
|
for (auto &[key, value] : values) {
|
||||||
set_key_value(prov, name, key, value);
|
set_key_value(prov, name, key, value);
|
||||||
}
|
}
|
||||||
@ -446,7 +444,7 @@ void handlers::handle_post_mount(auto &&req, auto &&res) const {
|
|||||||
auto unmount = utils::string::to_bool(req.get_param_value("unmount"));
|
auto unmount = utils::string::to_bool(req.get_param_value("unmount"));
|
||||||
|
|
||||||
if (unmount) {
|
if (unmount) {
|
||||||
launch_process(prov, name, "-unmount");
|
launch_process(prov, name, {"-unmount"});
|
||||||
} else {
|
} else {
|
||||||
#if defined(_WIN32)
|
#if defined(_WIN32)
|
||||||
if (utils::file::directory{location}.exists()) {
|
if (utils::file::directory{location}.exists()) {
|
||||||
@ -457,7 +455,7 @@ void handlers::handle_post_mount(auto &&req, auto &&res) const {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
launch_process(prov, name, fmt::format(R"("{}")", location), true);
|
launch_process(prov, name, {location}, true);
|
||||||
config_->set_mount_location(prov, name, location);
|
config_->set_mount_location(prov, name, location);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -466,7 +464,6 @@ void handlers::handle_post_mount(auto &&req, auto &&res) const {
|
|||||||
|
|
||||||
void handlers::handle_put_set_value_by_name(auto &&req, auto &&res) const {
|
void handlers::handle_put_set_value_by_name(auto &&req, auto &&res) const {
|
||||||
auto name = req.get_param_value("name");
|
auto name = req.get_param_value("name");
|
||||||
|
|
||||||
auto prov = provider_type_from_string(req.get_param_value("type"));
|
auto prov = provider_type_from_string(req.get_param_value("type"));
|
||||||
|
|
||||||
if (not data_directory_exists(prov, name)) {
|
if (not data_directory_exists(prov, name)) {
|
||||||
@ -510,34 +507,34 @@ void handlers::handle_put_settings(auto &&req, auto &&res) const {
|
|||||||
}
|
}
|
||||||
|
|
||||||
auto handlers::launch_process(provider_type prov, std::string_view name,
|
auto handlers::launch_process(provider_type prov, std::string_view name,
|
||||||
std::string_view args, bool background) const
|
std::vector<std::string> args,
|
||||||
|
bool background) const
|
||||||
-> std::vector<std::string> {
|
-> std::vector<std::string> {
|
||||||
REPERTORY_USES_FUNCTION_NAME();
|
REPERTORY_USES_FUNCTION_NAME();
|
||||||
|
|
||||||
if (is_restricted(name) || is_restricted(args)) {
|
|
||||||
throw utils::error::create_exception(function_name,
|
|
||||||
{
|
|
||||||
"invalid data detected",
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
std::string str_type;
|
|
||||||
switch (prov) {
|
switch (prov) {
|
||||||
case provider_type::encrypt:
|
case provider_type::encrypt:
|
||||||
str_type = fmt::format("-en -na {}", name);
|
args.insert(args.begin(), "-en");
|
||||||
|
args.insert(std::next(args.begin()), "-na");
|
||||||
|
args.insert(std::next(args.begin(), 2U), std::string{name});
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case provider_type::remote: {
|
case provider_type::remote: {
|
||||||
auto parts = utils::string::split(name, '_', false);
|
auto parts = utils::string::split(name, '_', false);
|
||||||
str_type = fmt::format("-rm {}:{}", parts[0U], parts[1U]);
|
args.insert(args.begin(), "-rm");
|
||||||
|
args.insert(std::next(args.begin()),
|
||||||
|
fmt::format("{}:{}", parts.at(0U), parts.at(1U)));
|
||||||
} break;
|
} break;
|
||||||
|
|
||||||
case provider_type::s3:
|
case provider_type::s3:
|
||||||
str_type = fmt::format("-s3 -na {}", name);
|
args.insert(args.begin(), "-s3");
|
||||||
|
args.insert(std::next(args.begin()), "-na");
|
||||||
|
args.insert(std::next(args.begin(), 2U), std::string{name});
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case provider_type::sia:
|
case provider_type::sia:
|
||||||
str_type = fmt::format("-na {}", name);
|
args.insert(args.begin(), "-na");
|
||||||
|
args.insert(std::next(args.begin()), std::string{name});
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
@ -549,8 +546,6 @@ auto handlers::launch_process(provider_type prov, std::string_view name,
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
auto cmd_line = fmt::format(R"({} {} {})", repertory_binary_, str_type, args);
|
|
||||||
|
|
||||||
unique_mutex_lock lock(mtx_);
|
unique_mutex_lock lock(mtx_);
|
||||||
auto &inst_mtx = mtx_lookup_[fmt::format(
|
auto &inst_mtx = mtx_lookup_[fmt::format(
|
||||||
"{}-{}", name, app_config::get_provider_name(prov))];
|
"{}-{}", name, app_config::get_provider_name(prov))];
|
||||||
@ -559,33 +554,53 @@ auto handlers::launch_process(provider_type prov, std::string_view name,
|
|||||||
recur_mutex_lock inst_lock(inst_mtx);
|
recur_mutex_lock inst_lock(inst_mtx);
|
||||||
if (background) {
|
if (background) {
|
||||||
#if defined(_WIN32)
|
#if defined(_WIN32)
|
||||||
system(fmt::format(R"(start "" /MIN {})", cmd_line).c_str());
|
std::array<char, MAX_PATH + 1U> path{};
|
||||||
|
::GetSystemDirectoryA(path.data(), path.size());
|
||||||
|
|
||||||
|
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_);
|
||||||
#elif defined(__linux__) // defined(__linux__)
|
#elif defined(__linux__) // defined(__linux__)
|
||||||
system(fmt::format("nohup {} 1>/dev/null 2>&1", cmd_line).c_str());
|
args.insert(args.begin(), "nohup");
|
||||||
|
args.insert(std::next(args.begin()), repertory_binary_);
|
||||||
|
args.emplace_back("1>/dev/null");
|
||||||
|
args.emplace_back("2>&1");
|
||||||
|
args.emplace_back("&");
|
||||||
|
#else // !defined(__linux__) && !defined(_WIN32)
|
||||||
|
build fails here
|
||||||
|
#endif // defined(_WIN32)
|
||||||
|
|
||||||
|
std::vector<const char *> exec_args;
|
||||||
|
exec_args.reserve(args.size() + 1U);
|
||||||
|
for (const auto &arg : args) {
|
||||||
|
fmt::println("{}", arg);
|
||||||
|
exec_args.push_back(arg.c_str());
|
||||||
|
}
|
||||||
|
exec_args.push_back(nullptr);
|
||||||
|
|
||||||
|
#if defined(_WIN32)
|
||||||
|
_spawnv(_P_DETACH, exec_args.at(0U),
|
||||||
|
const_cast<char *const *>(exec_args.data()));
|
||||||
|
#elif defined(__linux__) // defined(__linux__)
|
||||||
|
execvp(exec_args.at(0U), const_cast<char *const *>(exec_args.data()));
|
||||||
#else // !defined(__linux__) && !defined(_WIN32)
|
#else // !defined(__linux__) && !defined(_WIN32)
|
||||||
build fails here
|
build fails here
|
||||||
#endif // defined(_WIN32)
|
#endif // defined(_WIN32)
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
auto *pipe = popen(cmd_line.c_str(), "r");
|
boost::process::ipstream out;
|
||||||
if (pipe == nullptr) {
|
boost::process::child proc(repertory_binary_, boost::process::args(args),
|
||||||
throw utils::error::create_exception(function_name,
|
boost::process::std_out > out);
|
||||||
{
|
|
||||||
"failed to execute command",
|
|
||||||
provider_type_to_string(prov),
|
|
||||||
name,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
std::string data;
|
std::string data;
|
||||||
std::array<char, 1024U> buffer{};
|
std::string line;
|
||||||
while (std::feof(pipe) == 0) {
|
while (out && std::getline(out, line)) {
|
||||||
while (std::fgets(buffer.data(), buffer.size(), pipe) != nullptr) {
|
data += line + "\n";
|
||||||
data += buffer.data();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
pclose(pipe);
|
|
||||||
|
|
||||||
return utils::string::split(utils::string::replace(data, "\r", ""), '\n',
|
return utils::string::split(utils::string::replace(data, "\r", ""), '\n',
|
||||||
false);
|
false);
|
||||||
@ -594,10 +609,10 @@ auto handlers::launch_process(provider_type prov, std::string_view name,
|
|||||||
void handlers::set_key_value(provider_type prov, std::string_view name,
|
void handlers::set_key_value(provider_type prov, std::string_view name,
|
||||||
std::string_view key,
|
std::string_view key,
|
||||||
std::string_view value) const {
|
std::string_view value) const {
|
||||||
#if defined(_WIN32)
|
std::vector<std::string> args;
|
||||||
launch_process(prov, name, fmt::format(R"(-set {} "{}")", key, value));
|
args.emplace_back("-set");
|
||||||
#else // !defined(_WIN32)
|
args.emplace_back(key);
|
||||||
launch_process(prov, name, fmt::format("-set {} '{}'", key, value));
|
args.emplace_back(value);
|
||||||
#endif // defined(_WIN32)
|
launch_process(prov, name, args, false);
|
||||||
}
|
}
|
||||||
} // namespace repertory::ui
|
} // namespace repertory::ui
|
||||||
|
Loading…
x
Reference in New Issue
Block a user