mirror of
https://github.com/RGBCube/serenity
synced 2025-07-25 05:37:43 +00:00
LibCore: Define and use a fallible, OS-independent getpwent(_r) wrapper
Rather than maintaining a list of #ifdef guards to check systems that do not provide the reentrant version of getpwent, we can use C++ concepts to let the compiler perform this check for us. While we're at it, we can also provide this wrapper as fallible to let the caller TRY calling it.
This commit is contained in:
parent
b367da592c
commit
1ee808fae6
3 changed files with 58 additions and 27 deletions
|
@ -52,6 +52,40 @@ static int memfd_create(char const* name, unsigned int flags)
|
|||
} \
|
||||
return success_value;
|
||||
|
||||
// clang-format off
|
||||
template<typename T>
|
||||
concept SupportsReentrantGetpwent = requires(T passwd, T* ptr)
|
||||
{
|
||||
getpwent_r(&passwd, nullptr, 0, &ptr);
|
||||
};
|
||||
// clang-format on
|
||||
|
||||
// Note: This has to be in the global namespace for the extern declaration to trick the compiler
|
||||
// into finding a declaration of getpwent_r when it doesn't actually exist.
|
||||
static ErrorOr<Optional<struct passwd>> getpwent_impl(Span<char> buffer)
|
||||
{
|
||||
if constexpr (SupportsReentrantGetpwent<struct passwd>) {
|
||||
struct passwd passwd;
|
||||
struct passwd* ptr = nullptr;
|
||||
|
||||
extern int getpwent_r(struct passwd*, char*, size_t, struct passwd**);
|
||||
auto result = getpwent_r(&passwd, buffer.data(), buffer.size(), &ptr);
|
||||
|
||||
if (result == 0 && ptr)
|
||||
return passwd;
|
||||
if (result != 0 && result != ENOENT)
|
||||
return Error::from_errno(result);
|
||||
} else {
|
||||
errno = 0;
|
||||
if (auto const* passwd = ::getpwent())
|
||||
return *passwd;
|
||||
if (errno)
|
||||
return Error::from_errno(errno);
|
||||
}
|
||||
|
||||
return Optional<struct passwd> {};
|
||||
}
|
||||
|
||||
namespace Core::System {
|
||||
|
||||
#ifndef HOST_NAME_MAX
|
||||
|
@ -627,6 +661,11 @@ ErrorOr<void> chown(StringView pathname, uid_t uid, gid_t gid)
|
|||
#endif
|
||||
}
|
||||
|
||||
ErrorOr<Optional<struct passwd>> getpwent(Span<char> buffer)
|
||||
{
|
||||
return getpwent_impl(buffer);
|
||||
}
|
||||
|
||||
ErrorOr<Optional<struct passwd>> getpwuid(uid_t uid)
|
||||
{
|
||||
errno = 0;
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue