Add macOS support #34
This commit is contained in:
@@ -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
|
||||
|
||||
|
Reference in New Issue
Block a user