Add macOS support #34
Some checks failed
BlockStorage/repertory_mac/pipeline/head This commit looks good
BlockStorage/repertory/pipeline/head There was a failure building this commit

This commit is contained in:
2025-08-03 10:41:21 -05:00
parent eee832ce49
commit 29aaf625c7
16 changed files with 292 additions and 133 deletions

View File

@@ -23,6 +23,68 @@
#include "utils/unix.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 {
#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 {
std::vector<gid_t> groups{};
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__)
}
});
REPERTORY_USES_FUNCTION_NAME();
std::vector<gid_t> groups{};
auto res = use_getpwuid(
uid, [&groups](struct passwd *pass) { groups = get_group_list(pass); });
if (not res) {
throw utils::error::create_exception(res.function_name,
{"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);
if (temp_pw == nullptr) {
return {
std::string{function_name},
false,
"'getpwuid' returned nullptr",
.function_name = std::string{function_name},
.ok = false,
.reason = "'getpwuid' returned nullptr",
};
}
callback(temp_pw);
return {std::string{function_name}};
return {
.function_name = std::string{function_name},
};
}
} // namespace repertory::utils