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