1
Fork 0
mirror of https://github.com/RGBCube/serenity synced 2025-07-27 04:47:35 +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:
Timothy Flynn 2022-12-13 14:49:32 -05:00 committed by Tim Flynn
parent b367da592c
commit 1ee808fae6
3 changed files with 58 additions and 27 deletions

View file

@ -128,40 +128,31 @@ ErrorOr<Account> Account::from_uid(uid_t uid, [[maybe_unused]] Read options)
ErrorOr<Vector<Account>> Account::all([[maybe_unused]] Read options)
{
Vector<Account> accounts;
#ifndef AK_OS_MACOS
struct passwd pwd;
struct passwd* ptr = nullptr;
char buffer[1024] = { 0 };
#endif
ScopeGuard pwent_guard([] { endpwent(); });
setpwent();
errno = 0;
#ifndef AK_OS_MACOS
while (getpwent_r(&pwd, buffer, sizeof(buffer), &ptr) == 0 && ptr) {
#else
while (auto const* ptr = getpwent()) {
#endif
while (true) {
auto pwd = TRY(Core::System::getpwent({ buffer, sizeof(buffer) }));
if (!pwd.has_value())
break;
spwd spwd = {};
#ifndef AK_OS_BSD_GENERIC
ScopeGuard spent_guard([] { endspent(); });
if (options != Read::PasswdOnly) {
auto maybe_spwd = TRY(Core::System::getspnam({ ptr->pw_name, strlen(ptr->pw_name) }));
auto maybe_spwd = TRY(Core::System::getspnam({ pwd->pw_name, strlen(pwd->pw_name) }));
if (!maybe_spwd.has_value())
return Error::from_string_literal("No shadow entry for user");
spwd = maybe_spwd.release_value();
}
#endif
accounts.append({ *ptr, spwd, get_extra_gids(*ptr) });
accounts.append({ *pwd, spwd, get_extra_gids(*pwd) });
}
if (errno)
return Error::from_errno(errno);
return accounts;
}
@ -226,13 +217,17 @@ Account::Account(passwd const& pwd, spwd const& spwd, Vector<gid_t> extra_gids)
ErrorOr<DeprecatedString> Account::generate_passwd_file() const
{
StringBuilder builder;
char buffer[1024] = { 0 };
ScopeGuard pwent_guard([] { endpwent(); });
setpwent();
struct passwd* p;
errno = 0;
while ((p = getpwent())) {
if (p->pw_name == m_username) {
while (true) {
auto pwd = TRY(Core::System::getpwent({ buffer, sizeof(buffer) }));
if (!pwd.has_value())
break;
if (pwd->pw_name == m_username) {
builder.appendff("{}:!:{}:{}:{}:{}:{}\n",
m_username,
m_uid, m_gid,
@ -242,15 +237,11 @@ ErrorOr<DeprecatedString> Account::generate_passwd_file() const
} else {
builder.appendff("{}:!:{}:{}:{}:{}:{}\n",
p->pw_name, p->pw_uid,
p->pw_gid, p->pw_gecos, p->pw_dir,
p->pw_shell);
pwd->pw_name, pwd->pw_uid,
pwd->pw_gid, pwd->pw_gecos, pwd->pw_dir,
pwd->pw_shell);
}
}
endpwent();
if (errno)
return Error::from_errno(errno);
return builder.to_deprecated_string();
}