Add macOS support #34
This commit is contained in:
@@ -88,11 +88,16 @@ auto fuse_drive::chown_impl(std::string api_path, uid_t uid, gid_t gid,
|
|||||||
auto fuse_drive::chown_impl(std::string api_path, uid_t uid, gid_t gid)
|
auto fuse_drive::chown_impl(std::string api_path, uid_t uid, gid_t gid)
|
||||||
-> api_error {
|
-> api_error {
|
||||||
#endif
|
#endif
|
||||||
|
REPERTORY_USES_FUNCTION_NAME();
|
||||||
|
|
||||||
return check_and_perform(
|
return check_and_perform(
|
||||||
api_path, X_OK, [&](api_meta_map &meta) -> api_error {
|
api_path, X_OK, [&](api_meta_map &meta) -> api_error {
|
||||||
meta.clear();
|
meta.clear();
|
||||||
if (uid != static_cast<uid_t>(-1)) {
|
if (uid != static_cast<uid_t>(-1)) {
|
||||||
if (get_effective_uid() != 0 && get_effective_uid() != uid) {
|
if (get_effective_uid() != 0 && get_effective_uid() != uid) {
|
||||||
|
utils::error::raise_error(
|
||||||
|
function_name, fmt::format("failed user|{}|{}",
|
||||||
|
get_effective_uid(), getuid()));
|
||||||
return api_error::permission_denied;
|
return api_error::permission_denied;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -102,6 +107,9 @@ auto fuse_drive::chown_impl(std::string api_path, uid_t uid, gid_t gid)
|
|||||||
if (gid != static_cast<gid_t>(-1)) {
|
if (gid != static_cast<gid_t>(-1)) {
|
||||||
if (get_effective_uid() != 0 &&
|
if (get_effective_uid() != 0 &&
|
||||||
not utils::is_uid_member_of_group(get_effective_uid(), gid)) {
|
not utils::is_uid_member_of_group(get_effective_uid(), gid)) {
|
||||||
|
utils::error::raise_error(
|
||||||
|
function_name, fmt::format("failed group|{}|{}",
|
||||||
|
get_effective_gid(), getgid()));
|
||||||
return api_error::permission_denied;
|
return api_error::permission_denied;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -36,20 +36,20 @@ auto client::get_drive_information() -> rpc_response {
|
|||||||
auto resp = cli.Get("/api/v1/" + rpc_method::get_drive_information);
|
auto resp = cli.Get("/api/v1/" + rpc_method::get_drive_information);
|
||||||
if (resp.error() != httplib::Error::Success) {
|
if (resp.error() != httplib::Error::Success) {
|
||||||
return rpc_response{
|
return rpc_response{
|
||||||
rpc_response_type::http_error,
|
.response_type = rpc_response_type::http_error,
|
||||||
{{"error", httplib::to_string(resp.error())}},
|
.data = {{"error", httplib::to_string(resp.error())}},
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
if (resp->status != http_error_codes::ok) {
|
if (resp->status != http_error_codes::ok) {
|
||||||
return rpc_response{
|
return rpc_response{
|
||||||
rpc_response_type::http_error,
|
.response_type = rpc_response_type::http_error,
|
||||||
{{"error", std::to_string(resp->status)}},
|
.data = {{"error", std::to_string(resp->status)}},
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
return rpc_response{
|
return rpc_response{
|
||||||
rpc_response_type::success,
|
.response_type = rpc_response_type::success,
|
||||||
json::parse(resp->body),
|
.data = json::parse(resp->body),
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -63,20 +63,20 @@ auto client::get_config() -> rpc_response {
|
|||||||
auto resp = cli.Get("/api/v1/" + rpc_method::get_config);
|
auto resp = cli.Get("/api/v1/" + rpc_method::get_config);
|
||||||
if (resp.error() != httplib::Error::Success) {
|
if (resp.error() != httplib::Error::Success) {
|
||||||
return rpc_response{
|
return rpc_response{
|
||||||
rpc_response_type::http_error,
|
.response_type = rpc_response_type::http_error,
|
||||||
{{"error", httplib::to_string(resp.error())}},
|
.data = {{"error", httplib::to_string(resp.error())}},
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
if (resp->status != http_error_codes::ok) {
|
if (resp->status != http_error_codes::ok) {
|
||||||
return rpc_response{
|
return rpc_response{
|
||||||
rpc_response_type::http_error,
|
.response_type = rpc_response_type::http_error,
|
||||||
{{"error", std::to_string(resp->status)}},
|
.data = {{"error", std::to_string(resp->status)}},
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
return rpc_response{
|
return rpc_response{
|
||||||
rpc_response_type::success,
|
.response_type = rpc_response_type::success,
|
||||||
json::parse(resp->body),
|
.data = json::parse(resp->body),
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -92,20 +92,20 @@ auto client::get_config_value_by_name(const std::string &name) -> rpc_response {
|
|||||||
cli.Get("/api/v1/" + rpc_method::get_config_value_by_name, params, {});
|
cli.Get("/api/v1/" + rpc_method::get_config_value_by_name, params, {});
|
||||||
if (resp.error() != httplib::Error::Success) {
|
if (resp.error() != httplib::Error::Success) {
|
||||||
return rpc_response{
|
return rpc_response{
|
||||||
rpc_response_type::http_error,
|
.response_type = rpc_response_type::http_error,
|
||||||
{{"error", httplib::to_string(resp.error())}},
|
.data = {{"error", httplib::to_string(resp.error())}},
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
if (resp->status != http_error_codes::ok) {
|
if (resp->status != http_error_codes::ok) {
|
||||||
return rpc_response{
|
return rpc_response{
|
||||||
rpc_response_type::http_error,
|
.response_type = rpc_response_type::http_error,
|
||||||
{{"error", std::to_string(resp->status)}},
|
.data = {{"error", std::to_string(resp->status)}},
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
return rpc_response{
|
return rpc_response{
|
||||||
rpc_response_type::success,
|
.response_type = rpc_response_type::success,
|
||||||
json::parse(resp->body),
|
.data = json::parse(resp->body),
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -120,20 +120,20 @@ auto client::get_directory_items(const std::string &api_path) -> rpc_response {
|
|||||||
auto resp = cli.Get("/api/v1/" + rpc_method::get_directory_items, params, {});
|
auto resp = cli.Get("/api/v1/" + rpc_method::get_directory_items, params, {});
|
||||||
if (resp.error() != httplib::Error::Success) {
|
if (resp.error() != httplib::Error::Success) {
|
||||||
return rpc_response{
|
return rpc_response{
|
||||||
rpc_response_type::http_error,
|
.response_type = rpc_response_type::http_error,
|
||||||
{{"error", httplib::to_string(resp.error())}},
|
.data = {{"error", httplib::to_string(resp.error())}},
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
if (resp->status != http_error_codes::ok) {
|
if (resp->status != http_error_codes::ok) {
|
||||||
return rpc_response{
|
return rpc_response{
|
||||||
rpc_response_type::http_error,
|
.response_type = rpc_response_type::http_error,
|
||||||
{{"error", std::to_string(resp->status)}},
|
.data = {{"error", std::to_string(resp->status)}},
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
return rpc_response{
|
return rpc_response{
|
||||||
rpc_response_type::success,
|
.response_type = rpc_response_type::success,
|
||||||
json::parse(resp->body),
|
.data = json::parse(resp->body),
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -147,20 +147,20 @@ auto client::get_open_files() -> rpc_response {
|
|||||||
auto resp = cli.Get("/api/v1/" + rpc_method::get_open_files);
|
auto resp = cli.Get("/api/v1/" + rpc_method::get_open_files);
|
||||||
if (resp.error() != httplib::Error::Success) {
|
if (resp.error() != httplib::Error::Success) {
|
||||||
return rpc_response{
|
return rpc_response{
|
||||||
rpc_response_type::http_error,
|
.response_type = rpc_response_type::http_error,
|
||||||
{{"error", httplib::to_string(resp.error())}},
|
.data = {{"error", httplib::to_string(resp.error())}},
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
if (resp->status != http_error_codes::ok) {
|
if (resp->status != http_error_codes::ok) {
|
||||||
return rpc_response{
|
return rpc_response{
|
||||||
rpc_response_type::http_error,
|
.response_type = rpc_response_type::http_error,
|
||||||
{{"error", std::to_string(resp->status)}},
|
.data = {{"error", std::to_string(resp->status)}},
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
return rpc_response{
|
return rpc_response{
|
||||||
rpc_response_type::success,
|
.response_type = rpc_response_type::success,
|
||||||
json::parse(resp->body),
|
.data = json::parse(resp->body),
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -174,20 +174,20 @@ auto client::get_pinned_files() -> rpc_response {
|
|||||||
auto resp = cli.Get("/api/v1/" + rpc_method::get_pinned_files);
|
auto resp = cli.Get("/api/v1/" + rpc_method::get_pinned_files);
|
||||||
if (resp.error() != httplib::Error::Success) {
|
if (resp.error() != httplib::Error::Success) {
|
||||||
return rpc_response{
|
return rpc_response{
|
||||||
rpc_response_type::http_error,
|
.response_type = rpc_response_type::http_error,
|
||||||
{{"error", httplib::to_string(resp.error())}},
|
.data = {{"error", httplib::to_string(resp.error())}},
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
if (resp->status != http_error_codes::ok) {
|
if (resp->status != http_error_codes::ok) {
|
||||||
return rpc_response{
|
return rpc_response{
|
||||||
rpc_response_type::http_error,
|
.response_type = rpc_response_type::http_error,
|
||||||
{{"error", std::to_string(resp->status)}},
|
.data = {{"error", std::to_string(resp->status)}},
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
return rpc_response{
|
return rpc_response{
|
||||||
rpc_response_type::success,
|
.response_type = rpc_response_type::success,
|
||||||
json::parse(resp->body),
|
.data = json::parse(resp->body),
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -202,20 +202,20 @@ auto client::pin_file(const std::string &api_path) -> rpc_response {
|
|||||||
auto resp = cli.Post("/api/v1/" + rpc_method::pin_file, params);
|
auto resp = cli.Post("/api/v1/" + rpc_method::pin_file, params);
|
||||||
if (resp.error() != httplib::Error::Success) {
|
if (resp.error() != httplib::Error::Success) {
|
||||||
return rpc_response{
|
return rpc_response{
|
||||||
rpc_response_type::http_error,
|
.response_type = rpc_response_type::http_error,
|
||||||
{{"error", httplib::to_string(resp.error())}},
|
.data = {{"error", httplib::to_string(resp.error())}},
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
if (resp->status != http_error_codes::ok) {
|
if (resp->status != http_error_codes::ok) {
|
||||||
return rpc_response{
|
return rpc_response{
|
||||||
rpc_response_type::http_error,
|
.response_type = rpc_response_type::http_error,
|
||||||
{{"error", std::to_string(resp->status)}},
|
.data = {{"error", std::to_string(resp->status)}},
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
return rpc_response{
|
return rpc_response{
|
||||||
rpc_response_type::success,
|
.response_type = rpc_response_type::success,
|
||||||
{},
|
.data = {},
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -230,20 +230,20 @@ auto client::pinned_status(const std::string &api_path) -> rpc_response {
|
|||||||
auto resp = cli.Get("/api/v1/" + rpc_method::pinned_status, params, {});
|
auto resp = cli.Get("/api/v1/" + rpc_method::pinned_status, params, {});
|
||||||
if (resp.error() != httplib::Error::Success) {
|
if (resp.error() != httplib::Error::Success) {
|
||||||
return rpc_response{
|
return rpc_response{
|
||||||
rpc_response_type::http_error,
|
.response_type = rpc_response_type::http_error,
|
||||||
{{"error", httplib::to_string(resp.error())}},
|
.data = {{"error", httplib::to_string(resp.error())}},
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
if (resp->status != http_error_codes::ok) {
|
if (resp->status != http_error_codes::ok) {
|
||||||
return rpc_response{
|
return rpc_response{
|
||||||
rpc_response_type::http_error,
|
.response_type = rpc_response_type::http_error,
|
||||||
{{"error", std::to_string(resp->status)}},
|
.data = {{"error", std::to_string(resp->status)}},
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
return rpc_response{
|
return rpc_response{
|
||||||
rpc_response_type::success,
|
.response_type = rpc_response_type::success,
|
||||||
json::parse(resp->body),
|
.data = json::parse(resp->body),
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -265,20 +265,20 @@ auto client::set_config_value_by_name(const std::string &name,
|
|||||||
cli.Post("/api/v1/" + rpc_method::set_config_value_by_name, params);
|
cli.Post("/api/v1/" + rpc_method::set_config_value_by_name, params);
|
||||||
if (resp.error() != httplib::Error::Success) {
|
if (resp.error() != httplib::Error::Success) {
|
||||||
return rpc_response{
|
return rpc_response{
|
||||||
rpc_response_type::http_error,
|
.response_type = rpc_response_type::http_error,
|
||||||
{{"error", httplib::to_string(resp.error())}},
|
.data = {{"error", httplib::to_string(resp.error())}},
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
if (resp->status != http_error_codes::ok) {
|
if (resp->status != http_error_codes::ok) {
|
||||||
return rpc_response{
|
return rpc_response{
|
||||||
rpc_response_type::http_error,
|
.response_type = rpc_response_type::http_error,
|
||||||
{{"error", std::to_string(resp->status)}},
|
.data = {{"error", std::to_string(resp->status)}},
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
return rpc_response{
|
return rpc_response{
|
||||||
rpc_response_type::success,
|
.response_type = rpc_response_type::success,
|
||||||
nlohmann::json::parse(resp->body),
|
.data = nlohmann::json::parse(resp->body),
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -292,20 +292,20 @@ auto client::unmount() -> rpc_response {
|
|||||||
auto resp = cli.Post("/api/v1/" + rpc_method::unmount);
|
auto resp = cli.Post("/api/v1/" + rpc_method::unmount);
|
||||||
if (resp.error() != httplib::Error::Success) {
|
if (resp.error() != httplib::Error::Success) {
|
||||||
return rpc_response{
|
return rpc_response{
|
||||||
rpc_response_type::http_error,
|
.response_type = rpc_response_type::http_error,
|
||||||
{{"error", httplib::to_string(resp.error())}},
|
.data = {{"error", httplib::to_string(resp.error())}},
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
if (resp->status != http_error_codes::ok) {
|
if (resp->status != http_error_codes::ok) {
|
||||||
return rpc_response{
|
return rpc_response{
|
||||||
rpc_response_type::http_error,
|
.response_type = rpc_response_type::http_error,
|
||||||
{{"error", std::to_string(resp->status)}},
|
.data = {{"error", std::to_string(resp->status)}},
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
return rpc_response{
|
return rpc_response{
|
||||||
rpc_response_type::success,
|
.response_type = rpc_response_type::success,
|
||||||
{},
|
.data = {},
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -320,20 +320,20 @@ auto client::unpin_file(const std::string &api_path) -> rpc_response {
|
|||||||
auto resp = cli.Post("/api/v1/" + rpc_method::unpin_file, params);
|
auto resp = cli.Post("/api/v1/" + rpc_method::unpin_file, params);
|
||||||
if (resp.error() != httplib::Error::Success) {
|
if (resp.error() != httplib::Error::Success) {
|
||||||
return rpc_response{
|
return rpc_response{
|
||||||
rpc_response_type::http_error,
|
.response_type = rpc_response_type::http_error,
|
||||||
{{"error", httplib::to_string(resp.error())}},
|
.data = {{"error", httplib::to_string(resp.error())}},
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
if (resp->status != http_error_codes::ok) {
|
if (resp->status != http_error_codes::ok) {
|
||||||
return rpc_response{
|
return rpc_response{
|
||||||
rpc_response_type::http_error,
|
.response_type = rpc_response_type::http_error,
|
||||||
{{"error", std::to_string(resp->status)}},
|
.data = {{"error", std::to_string(resp->status)}},
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
return rpc_response{
|
return rpc_response{
|
||||||
rpc_response_type::success,
|
.response_type = rpc_response_type::success,
|
||||||
{},
|
.data = {},
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
} // namespace repertory
|
} // namespace repertory
|
||||||
|
@@ -29,8 +29,8 @@ namespace repertory::cli::actions {
|
|||||||
const std::string &data_directory,
|
const std::string &data_directory,
|
||||||
const provider_type &prov,
|
const provider_type &prov,
|
||||||
const std::string &unique_id,
|
const std::string &unique_id,
|
||||||
std::string user,
|
std::string user, std::string password)
|
||||||
std::string password) -> exit_code {
|
-> exit_code {
|
||||||
lock_data lock(prov, unique_id);
|
lock_data lock(prov, unique_id);
|
||||||
const auto res = lock.grab_lock(1U);
|
const auto res = lock.grab_lock(1U);
|
||||||
if (res == lock_result::success) {
|
if (res == lock_result::success) {
|
||||||
@@ -42,8 +42,11 @@ namespace repertory::cli::actions {
|
|||||||
auto port = app_config::default_api_port(prov);
|
auto port = app_config::default_api_port(prov);
|
||||||
utils::cli::get_api_authentication_data(user, password, port, prov,
|
utils::cli::get_api_authentication_data(user, password, port, prov,
|
||||||
data_directory);
|
data_directory);
|
||||||
const auto response =
|
auto response = client({.host = "localhost",
|
||||||
client({"localhost", password, port, user}).get_config();
|
.password = password,
|
||||||
|
.port = port,
|
||||||
|
.user = user})
|
||||||
|
.get_config();
|
||||||
std::cout << static_cast<int>(response.response_type) << std::endl;
|
std::cout << static_cast<int>(response.response_type) << std::endl;
|
||||||
std::cout << response.data.dump(2) << std::endl;
|
std::cout << response.data.dump(2) << std::endl;
|
||||||
}
|
}
|
||||||
|
@@ -38,8 +38,11 @@ drive_information(std::vector<const char *> /* args */,
|
|||||||
auto port = app_config::default_api_port(prov);
|
auto port = app_config::default_api_port(prov);
|
||||||
utils::cli::get_api_authentication_data(user, password, port, prov,
|
utils::cli::get_api_authentication_data(user, password, port, prov,
|
||||||
data_directory);
|
data_directory);
|
||||||
const auto response =
|
auto response = client({.host = "localhost",
|
||||||
client({"localhost", password, port, user}).get_drive_information();
|
.password = password,
|
||||||
|
.port = port,
|
||||||
|
.user = user})
|
||||||
|
.get_drive_information();
|
||||||
std::cout << static_cast<int>(response.response_type) << std::endl;
|
std::cout << static_cast<int>(response.response_type) << std::endl;
|
||||||
std::cout << response.data.dump(2) << std::endl;
|
std::cout << response.data.dump(2) << std::endl;
|
||||||
} else {
|
} else {
|
||||||
|
@@ -49,7 +49,10 @@ namespace repertory::cli::actions {
|
|||||||
auto port = app_config::default_api_port(prov);
|
auto port = app_config::default_api_port(prov);
|
||||||
utils::cli::get_api_authentication_data(user, password, port, prov,
|
utils::cli::get_api_authentication_data(user, password, port, prov,
|
||||||
data_directory);
|
data_directory);
|
||||||
const auto response = client({"localhost", password, port, user})
|
auto response = client({.host = "localhost",
|
||||||
|
.password = password,
|
||||||
|
.port = port,
|
||||||
|
.user = user})
|
||||||
.get_config_value_by_name(data);
|
.get_config_value_by_name(data);
|
||||||
std::cout << static_cast<int>(response.response_type) << std::endl;
|
std::cout << static_cast<int>(response.response_type) << std::endl;
|
||||||
std::cout << response.data.dump(2) << std::endl;
|
std::cout << response.data.dump(2) << std::endl;
|
||||||
|
@@ -36,8 +36,11 @@ namespace repertory::cli::actions {
|
|||||||
auto port = app_config::default_api_port(prov);
|
auto port = app_config::default_api_port(prov);
|
||||||
utils::cli::get_api_authentication_data(user, password, port, prov,
|
utils::cli::get_api_authentication_data(user, password, port, prov,
|
||||||
data_directory);
|
data_directory);
|
||||||
const auto response =
|
auto response = client({.host = "localhost",
|
||||||
client({"localhost", password, port, user}).get_directory_items(data);
|
.password = password,
|
||||||
|
.port = port,
|
||||||
|
.user = user})
|
||||||
|
.get_directory_items(data);
|
||||||
if (response.response_type == rpc_response_type::success) {
|
if (response.response_type == rpc_response_type::success) {
|
||||||
std::cout << response.data.dump(2) << std::endl;
|
std::cout << response.data.dump(2) << std::endl;
|
||||||
} else {
|
} else {
|
||||||
|
@@ -35,8 +35,11 @@ namespace repertory::cli::actions {
|
|||||||
auto port = app_config::default_api_port(prov);
|
auto port = app_config::default_api_port(prov);
|
||||||
utils::cli::get_api_authentication_data(user, password, port, prov,
|
utils::cli::get_api_authentication_data(user, password, port, prov,
|
||||||
data_directory);
|
data_directory);
|
||||||
const auto response =
|
auto response = client({.host = "localhost",
|
||||||
client({"localhost", password, port, user}).get_pinned_files();
|
.password = password,
|
||||||
|
.port = port,
|
||||||
|
.user = user})
|
||||||
|
.get_pinned_files();
|
||||||
if (response.response_type == rpc_response_type::success) {
|
if (response.response_type == rpc_response_type::success) {
|
||||||
std::cout << response.data.dump(2) << std::endl;
|
std::cout << response.data.dump(2) << std::endl;
|
||||||
} else {
|
} else {
|
||||||
|
@@ -37,8 +37,11 @@ open_files(std::vector<const char *> /* args */,
|
|||||||
auto port = app_config::default_api_port(prov);
|
auto port = app_config::default_api_port(prov);
|
||||||
utils::cli::get_api_authentication_data(user, password, port, prov,
|
utils::cli::get_api_authentication_data(user, password, port, prov,
|
||||||
data_directory);
|
data_directory);
|
||||||
const auto response =
|
auto response = client({.host = "localhost",
|
||||||
client({"localhost", password, port, user}).get_open_files();
|
.password = password,
|
||||||
|
.port = port,
|
||||||
|
.user = user})
|
||||||
|
.get_open_files();
|
||||||
std::cout << static_cast<int>(response.response_type) << std::endl;
|
std::cout << static_cast<int>(response.response_type) << std::endl;
|
||||||
std::cout << response.data.dump(2) << std::endl;
|
std::cout << response.data.dump(2) << std::endl;
|
||||||
} else {
|
} else {
|
||||||
|
@@ -36,8 +36,11 @@ pin_file(std::vector<const char *> args, const std::string &data_directory,
|
|||||||
auto port = app_config::default_api_port(prov);
|
auto port = app_config::default_api_port(prov);
|
||||||
utils::cli::get_api_authentication_data(user, password, port, prov,
|
utils::cli::get_api_authentication_data(user, password, port, prov,
|
||||||
data_directory);
|
data_directory);
|
||||||
const auto response =
|
auto response = client({.host = "localhost",
|
||||||
client({"localhost", password, port, user}).pin_file(data);
|
.password = password,
|
||||||
|
.port = port,
|
||||||
|
.user = user})
|
||||||
|
.pin_file(data);
|
||||||
if (response.response_type == rpc_response_type::success) {
|
if (response.response_type == rpc_response_type::success) {
|
||||||
std::cout << response.data.dump(2) << std::endl;
|
std::cout << response.data.dump(2) << std::endl;
|
||||||
} else {
|
} else {
|
||||||
|
@@ -36,8 +36,11 @@ pinned_status(std::vector<const char *> args, const std::string &data_directory,
|
|||||||
auto port = app_config::default_api_port(prov);
|
auto port = app_config::default_api_port(prov);
|
||||||
utils::cli::get_api_authentication_data(user, password, port, prov,
|
utils::cli::get_api_authentication_data(user, password, port, prov,
|
||||||
data_directory);
|
data_directory);
|
||||||
const auto response =
|
auto response = client({.host = "localhost",
|
||||||
client({"localhost", password, port, user}).pinned_status(data);
|
.password = password,
|
||||||
|
.port = port,
|
||||||
|
.user = user})
|
||||||
|
.pinned_status(data);
|
||||||
if (response.response_type == rpc_response_type::success) {
|
if (response.response_type == rpc_response_type::success) {
|
||||||
std::cout << response.data.dump(2) << std::endl;
|
std::cout << response.data.dump(2) << std::endl;
|
||||||
} else {
|
} else {
|
||||||
|
@@ -56,7 +56,10 @@ namespace repertory::cli::actions {
|
|||||||
auto port = app_config::default_api_port(prov);
|
auto port = app_config::default_api_port(prov);
|
||||||
utils::cli::get_api_authentication_data(user, password, port, prov,
|
utils::cli::get_api_authentication_data(user, password, port, prov,
|
||||||
data_directory);
|
data_directory);
|
||||||
const auto response = client({"localhost", password, port, user})
|
auto response = client({.host = "localhost",
|
||||||
|
.password = password,
|
||||||
|
.port = port,
|
||||||
|
.user = user})
|
||||||
.set_config_value_by_name(data[0U], data[1U]);
|
.set_config_value_by_name(data[0U], data[1U]);
|
||||||
std::cout << static_cast<int>(response.response_type) << std::endl;
|
std::cout << static_cast<int>(response.response_type) << std::endl;
|
||||||
std::cout << response.data.dump(2) << std::endl;
|
std::cout << response.data.dump(2) << std::endl;
|
||||||
|
@@ -29,14 +29,40 @@ namespace repertory::cli::actions {
|
|||||||
unmount(std::vector<const char *> /* args */, const std::string &data_directory,
|
unmount(std::vector<const char *> /* args */, const std::string &data_directory,
|
||||||
const provider_type &prov, const std::string & /* unique_id */,
|
const provider_type &prov, const std::string & /* unique_id */,
|
||||||
std::string user, std::string password) -> exit_code {
|
std::string user, std::string password) -> exit_code {
|
||||||
auto ret = exit_code::success;
|
constexpr const std::uint8_t retry_count{30U};
|
||||||
auto port = app_config::default_api_port(prov);
|
|
||||||
|
auto ret{exit_code::success};
|
||||||
|
auto port{app_config::default_api_port(prov)};
|
||||||
utils::cli::get_api_authentication_data(user, password, port, prov,
|
utils::cli::get_api_authentication_data(user, password, port, prov,
|
||||||
data_directory);
|
data_directory);
|
||||||
const auto response = client({"localhost", password, port, user}).unmount();
|
auto response = client({.host = "localhost",
|
||||||
std::cout << static_cast<int>(response.response_type) << std::endl;
|
.password = password,
|
||||||
|
.port = port,
|
||||||
|
.user = user})
|
||||||
|
.unmount();
|
||||||
if (response.response_type == rpc_response_type::success) {
|
if (response.response_type == rpc_response_type::success) {
|
||||||
|
std::cout << "waiting for unmount ..." << std::flush;
|
||||||
|
for (std::uint8_t retry{0U};
|
||||||
|
retry < retry_count &&
|
||||||
|
response.response_type == rpc_response_type::success;
|
||||||
|
++retry) {
|
||||||
|
std::this_thread::sleep_for(1s);
|
||||||
|
response = client({.host = "localhost",
|
||||||
|
.password = password,
|
||||||
|
.port = port,
|
||||||
|
.user = user})
|
||||||
|
.unmount();
|
||||||
|
std::cout << "." << std::flush;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (response.response_type == rpc_response_type::success) {
|
||||||
|
std::cerr << " failed! mount still active" << std::endl;
|
||||||
|
ret = exit_code::mount_active;
|
||||||
|
} else {
|
||||||
|
std::cout << " done!" << std::endl;
|
||||||
|
std::cout << static_cast<int>(rpc_response_type::success) << std::endl;
|
||||||
std::cout << response.data.dump(2) << std::endl;
|
std::cout << response.data.dump(2) << std::endl;
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
std::cerr << response.data.dump(2) << std::endl;
|
std::cerr << response.data.dump(2) << std::endl;
|
||||||
ret = exit_code::communication_error;
|
ret = exit_code::communication_error;
|
||||||
|
@@ -36,8 +36,11 @@ unpin_file(std::vector<const char *> args, const std::string &data_directory,
|
|||||||
auto port = app_config::default_api_port(prov);
|
auto port = app_config::default_api_port(prov);
|
||||||
utils::cli::get_api_authentication_data(user, password, port, prov,
|
utils::cli::get_api_authentication_data(user, password, port, prov,
|
||||||
data_directory);
|
data_directory);
|
||||||
const auto response =
|
auto response = client({.host = "localhost",
|
||||||
client({"localhost", password, port, user}).unpin_file(data);
|
.password = password,
|
||||||
|
.port = port,
|
||||||
|
.user = user})
|
||||||
|
.unpin_file(data);
|
||||||
if (response.response_type == rpc_response_type::success) {
|
if (response.response_type == rpc_response_type::success) {
|
||||||
std::cout << response.data.dump(2) << std::endl;
|
std::cout << response.data.dump(2) << std::endl;
|
||||||
} else {
|
} else {
|
||||||
|
@@ -360,22 +360,12 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
static void execute_unmount(auto args) {
|
static void execute_unmount(auto args) {
|
||||||
auto unmounted{false};
|
|
||||||
|
|
||||||
args.emplace_back("-unmount");
|
args.emplace_back("-unmount");
|
||||||
auto unmount_cmd = "./repertory " + utils::string::join(args, ' ');
|
auto unmount_cmd = "./repertory " + utils::string::join(args, ' ');
|
||||||
std::cout << "unmount command: " << unmount_cmd << std::endl;
|
std::cout << "unmount command: " << unmount_cmd << std::endl;
|
||||||
|
|
||||||
for (int i = 0; not unmounted && (i < 50); i++) {
|
|
||||||
auto res = system(unmount_cmd.c_str());
|
auto res = system(unmount_cmd.c_str());
|
||||||
unmounted = res == 0;
|
|
||||||
EXPECT_EQ(0, res);
|
EXPECT_EQ(0, res);
|
||||||
if (not unmounted) {
|
|
||||||
std::this_thread::sleep_for(5s);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
EXPECT_TRUE(unmounted);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void rmdir_and_test(std::string_view dir_path) {
|
static void rmdir_and_test(std::string_view dir_path) {
|
||||||
|
@@ -379,8 +379,11 @@ TYPED_TEST(fuse_test, create_fails_with_excl_if_path_is_directory) {
|
|||||||
for (const auto &flags : ops) {
|
for (const auto &flags : ops) {
|
||||||
auto handle = open(dir_path.c_str(), flags, ACCESSPERMS);
|
auto handle = open(dir_path.c_str(), flags, ACCESSPERMS);
|
||||||
EXPECT_EQ(-1, handle);
|
EXPECT_EQ(-1, handle);
|
||||||
|
|
||||||
EXPECT_EQ(EEXIST, errno);
|
EXPECT_EQ(EEXIST, errno);
|
||||||
|
|
||||||
|
if (handle != -1) {
|
||||||
|
close(handle);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
this->rmdir_and_test(dir_path);
|
this->rmdir_and_test(dir_path);
|
||||||
@@ -399,8 +402,11 @@ TYPED_TEST(fuse_test, create_fails_with_excl_if_file_exists) {
|
|||||||
for (const auto &flags : ops) {
|
for (const auto &flags : ops) {
|
||||||
auto handle = open(file_path.c_str(), flags, ACCESSPERMS);
|
auto handle = open(file_path.c_str(), flags, ACCESSPERMS);
|
||||||
EXPECT_EQ(-1, handle);
|
EXPECT_EQ(-1, handle);
|
||||||
|
|
||||||
EXPECT_EQ(EEXIST, errno);
|
EXPECT_EQ(EEXIST, errno);
|
||||||
|
|
||||||
|
if (handle != -1) {
|
||||||
|
close(handle);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
this->unlink_file_and_test(file_path);
|
this->unlink_file_and_test(file_path);
|
||||||
@@ -408,23 +414,40 @@ TYPED_TEST(fuse_test, create_fails_with_excl_if_file_exists) {
|
|||||||
|
|
||||||
TYPED_TEST(fuse_test, create_fails_if_path_is_directory) {
|
TYPED_TEST(fuse_test, create_fails_if_path_is_directory) {
|
||||||
std::array<int, 7U> ops{
|
std::array<int, 7U> ops{
|
||||||
|
O_CREAT,
|
||||||
O_CREAT | O_APPEND,
|
O_CREAT | O_APPEND,
|
||||||
O_CREAT | O_RDWR,
|
O_CREAT | O_RDWR,
|
||||||
O_CREAT | O_TRUNC | O_RDWR,
|
O_CREAT | O_TRUNC | O_RDWR,
|
||||||
O_CREAT | O_TRUNC | O_WRONLY,
|
O_CREAT | O_TRUNC | O_WRONLY,
|
||||||
O_CREAT | O_TRUNC,
|
O_CREAT | O_TRUNC,
|
||||||
O_CREAT | O_WRONLY,
|
O_CREAT | O_WRONLY,
|
||||||
O_CREAT,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
std::string dir_name{"create_test"};
|
std::string dir_name{"create_test"};
|
||||||
auto dir_path = this->create_directory_and_test(dir_name);
|
auto dir_path = this->create_directory_and_test(dir_name);
|
||||||
|
|
||||||
for (const auto &flags : ops) {
|
for (std::size_t idx{0U}; idx < ops.size(); ++idx) {
|
||||||
|
auto flags = ops.at(idx);
|
||||||
auto handle = open(dir_path.c_str(), flags, ACCESSPERMS);
|
auto handle = open(dir_path.c_str(), flags, ACCESSPERMS);
|
||||||
EXPECT_EQ(-1, handle);
|
#if defined(__APPLE__)
|
||||||
|
if (handle == -1) {
|
||||||
EXPECT_EQ(EISDIR, errno);
|
EXPECT_EQ(EISDIR, errno);
|
||||||
|
} else {
|
||||||
|
if (idx > 1U) {
|
||||||
|
std::cerr << "create flags should return invalid handle|idx|" << idx
|
||||||
|
<< "|flags|" << std::hex << flags << std::endl;
|
||||||
|
EXPECT_EQ(-1, handle);
|
||||||
|
}
|
||||||
|
close(handle);
|
||||||
|
}
|
||||||
|
#else // !defined(__APPLE__)
|
||||||
|
EXPECT_EQ(-1, handle);
|
||||||
|
EXPECT_EQ(EISDIR, errno);
|
||||||
|
|
||||||
|
if (handle != -1) {
|
||||||
|
close(handle);
|
||||||
|
}
|
||||||
|
#endif //! defined(__APPLE__)
|
||||||
}
|
}
|
||||||
|
|
||||||
this->rmdir_and_test(dir_path);
|
this->rmdir_and_test(dir_path);
|
||||||
@@ -450,11 +473,15 @@ TYPED_TEST(fuse_test, create_fails_if_parent_path_does_not_exist) {
|
|||||||
for (const auto &flags : ops) {
|
for (const auto &flags : ops) {
|
||||||
auto handle = open(file_path.c_str(), flags, ACCESSPERMS);
|
auto handle = open(file_path.c_str(), flags, ACCESSPERMS);
|
||||||
EXPECT_EQ(-1, handle);
|
EXPECT_EQ(-1, handle);
|
||||||
|
|
||||||
EXPECT_EQ(ENOENT, errno);
|
EXPECT_EQ(ENOENT, errno);
|
||||||
|
|
||||||
|
if (handle != -1) {
|
||||||
|
close(handle);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if !defined(__APPLE__)
|
||||||
TYPED_TEST(fuse_test, create_fails_if_invalid) {
|
TYPED_TEST(fuse_test, create_fails_if_invalid) {
|
||||||
std::array<int, 1U> ops{
|
std::array<int, 1U> ops{
|
||||||
O_CREAT | O_TRUNC | O_APPEND,
|
O_CREAT | O_TRUNC | O_APPEND,
|
||||||
@@ -466,10 +493,14 @@ TYPED_TEST(fuse_test, create_fails_if_invalid) {
|
|||||||
for (const auto &flags : ops) {
|
for (const auto &flags : ops) {
|
||||||
auto handle = open(file_path.c_str(), flags, ACCESSPERMS);
|
auto handle = open(file_path.c_str(), flags, ACCESSPERMS);
|
||||||
EXPECT_EQ(-1, handle);
|
EXPECT_EQ(-1, handle);
|
||||||
|
|
||||||
EXPECT_EQ(EINVAL, errno);
|
EXPECT_EQ(EINVAL, errno);
|
||||||
|
|
||||||
|
if (handle != -1) {
|
||||||
|
close(handle);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
#endif // !defined(__APPLE__)
|
||||||
|
|
||||||
TYPED_TEST(fuse_test, create_open_fails_if_path_is_directory) {
|
TYPED_TEST(fuse_test, create_open_fails_if_path_is_directory) {
|
||||||
std::array<int, 9U> ops{
|
std::array<int, 9U> ops{
|
||||||
@@ -481,13 +512,28 @@ TYPED_TEST(fuse_test, create_open_fails_if_path_is_directory) {
|
|||||||
std::string dir_name{"create_test"};
|
std::string dir_name{"create_test"};
|
||||||
auto dir_path = this->create_directory_and_test(dir_name);
|
auto dir_path = this->create_directory_and_test(dir_name);
|
||||||
|
|
||||||
for (const auto &flags : ops) {
|
for (std::size_t idx{0U}; idx < ops.size(); ++idx) {
|
||||||
|
auto flags = ops.at(idx);
|
||||||
auto handle = open(dir_path.c_str(), flags);
|
auto handle = open(dir_path.c_str(), flags);
|
||||||
EXPECT_EQ(-1, handle);
|
#if defined(__APPLE__)
|
||||||
if (handle != -1) {
|
if (handle != -1) {
|
||||||
std::cout << std::oct << flags << std::endl;
|
if (idx != 0U) {
|
||||||
|
std::cerr << "open flags should return invalid handle|idx|" << idx
|
||||||
|
<< "|flags|" << std::hex << flags << std::endl;
|
||||||
|
EXPECT_EQ(-1, handle);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
close(handle);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
#endif // defined(__APPLE_)
|
||||||
|
|
||||||
|
EXPECT_EQ(-1, handle);
|
||||||
EXPECT_EQ(EISDIR, errno);
|
EXPECT_EQ(EISDIR, errno);
|
||||||
|
|
||||||
|
if (handle != -1) {
|
||||||
|
close(handle);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
this->rmdir_and_test(dir_path);
|
this->rmdir_and_test(dir_path);
|
||||||
@@ -514,6 +560,10 @@ TYPED_TEST(fuse_test, create_open_fails_if_path_does_not_exist) {
|
|||||||
auto handle = open(file_path.c_str(), flags);
|
auto handle = open(file_path.c_str(), flags);
|
||||||
EXPECT_EQ(-1, handle);
|
EXPECT_EQ(-1, handle);
|
||||||
EXPECT_EQ(ENOENT, errno);
|
EXPECT_EQ(ENOENT, errno);
|
||||||
|
|
||||||
|
if (handle != -1) {
|
||||||
|
close(handle);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} // namespace repertory
|
} // namespace repertory
|
||||||
|
@@ -23,6 +23,68 @@
|
|||||||
|
|
||||||
#include "utils/unix.hpp"
|
#include "utils/unix.hpp"
|
||||||
#include "utils/collection.hpp"
|
#include "utils/collection.hpp"
|
||||||
|
#include "utils/error_utils.hpp"
|
||||||
|
|
||||||
|
namespace {
|
||||||
|
[[nodiscard]] auto get_group_list(auto *pass) -> std::vector<gid_t> {
|
||||||
|
REPERTORY_USES_FUNCTION_NAME();
|
||||||
|
|
||||||
|
std::vector<gid_t> groups{};
|
||||||
|
#if defined(__APPLE__)
|
||||||
|
constexpr const int buffer_count{8};
|
||||||
|
constexpr const int max_group_count{1024};
|
||||||
|
groups.resize(buffer_count);
|
||||||
|
|
||||||
|
std::size_t orig_count{0U};
|
||||||
|
while (true) {
|
||||||
|
auto group_count{static_cast<int>(groups.size())};
|
||||||
|
if (group_count > max_group_count) {
|
||||||
|
repertory::utils::error::raise_error(
|
||||||
|
function_name, "getgrouplist failed: too many groups");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto res{
|
||||||
|
getgrouplist(pass->pw_name, static_cast<int>(pass->pw_gid),
|
||||||
|
reinterpret_cast<int *>(groups.data()), &group_count),
|
||||||
|
};
|
||||||
|
if (res < 0) {
|
||||||
|
if (orig_count == 0U) {
|
||||||
|
repertory::utils::error::raise_error(
|
||||||
|
function_name,
|
||||||
|
fmt::format("failed to get group list|error|{}", errno));
|
||||||
|
}
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
groups.resize(static_cast<std::size_t>(group_count));
|
||||||
|
if (groups.size() == orig_count) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
orig_count = groups.size();
|
||||||
|
}
|
||||||
|
#else // !defined(__APPLE__)
|
||||||
|
int group_count{};
|
||||||
|
auto res = getgrouplist(pass->pw_name, pass->pw_gid, nullptr, &group_count);
|
||||||
|
if (res >= 0) {
|
||||||
|
repertory::utils::error::raise_error(
|
||||||
|
function_name, fmt::format("failed to get group list|error|{}", errno));
|
||||||
|
}
|
||||||
|
#endif // defined(__APPLE__)
|
||||||
|
|
||||||
|
#if !defined(__APPLE__)
|
||||||
|
res = getgrouplist(pass->pw_name, pass->pw_gid, groups.data(), &group_count);
|
||||||
|
if (res >= 0) {
|
||||||
|
repertory::utils::error::raise_error(
|
||||||
|
function_name, fmt::format("failed to get group list|error|{}", errno));
|
||||||
|
}
|
||||||
|
#endif // !defined(__APPLE__)
|
||||||
|
|
||||||
|
return groups;
|
||||||
|
}
|
||||||
|
} // namespace
|
||||||
|
|
||||||
namespace repertory::utils {
|
namespace repertory::utils {
|
||||||
#if defined(__APPLE__)
|
#if defined(__APPLE__)
|
||||||
@@ -42,20 +104,11 @@ auto get_thread_id() -> std::uint64_t {
|
|||||||
}
|
}
|
||||||
|
|
||||||
auto is_uid_member_of_group(uid_t uid, gid_t gid) -> bool {
|
auto is_uid_member_of_group(uid_t uid, gid_t gid) -> bool {
|
||||||
std::vector<gid_t> groups{};
|
REPERTORY_USES_FUNCTION_NAME();
|
||||||
auto res = use_getpwuid(uid, [&groups](struct passwd *pass) {
|
|
||||||
int group_count{};
|
|
||||||
if (getgrouplist(pass->pw_name, pass->pw_gid, nullptr, &group_count) < 0) {
|
|
||||||
groups.resize(static_cast<std::size_t>(group_count));
|
|
||||||
#if defined(__APPLE__)
|
|
||||||
getgrouplist(pass->pw_name, pass->pw_gid,
|
|
||||||
reinterpret_cast<int *>(groups.data()), &group_count);
|
|
||||||
#else // !defined(__APPLE__)
|
|
||||||
getgrouplist(pass->pw_name, pass->pw_gid, groups.data(), &group_count);
|
|
||||||
#endif // defined(__APPLE__)
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
|
std::vector<gid_t> groups{};
|
||||||
|
auto res = use_getpwuid(
|
||||||
|
uid, [&groups](struct passwd *pass) { groups = get_group_list(pass); });
|
||||||
if (not res) {
|
if (not res) {
|
||||||
throw utils::error::create_exception(res.function_name,
|
throw utils::error::create_exception(res.function_name,
|
||||||
{"use_getpwuid failed", res.reason});
|
{"use_getpwuid failed", res.reason});
|
||||||
@@ -73,14 +126,16 @@ auto use_getpwuid(uid_t uid, passwd_callback_t callback) -> result {
|
|||||||
auto *temp_pw = getpwuid(uid);
|
auto *temp_pw = getpwuid(uid);
|
||||||
if (temp_pw == nullptr) {
|
if (temp_pw == nullptr) {
|
||||||
return {
|
return {
|
||||||
std::string{function_name},
|
.function_name = std::string{function_name},
|
||||||
false,
|
.ok = false,
|
||||||
"'getpwuid' returned nullptr",
|
.reason = "'getpwuid' returned nullptr",
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
callback(temp_pw);
|
callback(temp_pw);
|
||||||
return {std::string{function_name}};
|
return {
|
||||||
|
.function_name = std::string{function_name},
|
||||||
|
};
|
||||||
}
|
}
|
||||||
} // namespace repertory::utils
|
} // namespace repertory::utils
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user