From 524baa29e866d6ee5ef2340c911d626c0b247ce8 Mon Sep 17 00:00:00 2001 From: Andreas Kling Date: Thu, 17 Nov 2022 20:43:42 +0100 Subject: LibC+Tests: Simplify getpwuid_r() and getpwnam_r() and add tests These functions are now implemented in terms of getpwent_r() which allows us to remove two FIXMEs about global variable shenanigans. I'm also adding tests for both APIs. :^) --- Userland/Libraries/LibC/pwd.cpp | 97 ++++++----------------------------------- 1 file changed, 14 insertions(+), 83 deletions(-) (limited to 'Userland') diff --git a/Userland/Libraries/LibC/pwd.cpp b/Userland/Libraries/LibC/pwd.cpp index 688d3f306c..12aed49973 100644 --- a/Userland/Libraries/LibC/pwd.cpp +++ b/Userland/Libraries/LibC/pwd.cpp @@ -20,12 +20,6 @@ extern "C" { static FILE* s_stream = nullptr; static unsigned s_line_number = 0; -static String s_name; -static String s_passwd; -static String s_gecos; -static String s_dir; -static String s_shell; - void setpwent() { s_line_number = 0; @@ -163,91 +157,28 @@ int getpwent_r(struct passwd* passwd_buf, char* buffer, size_t buffer_size, stru } } -static void construct_pwd(struct passwd* pwd, char* buf, struct passwd** result) -{ - auto* buf_name = &buf[0]; - auto* buf_passwd = &buf[s_name.length() + 1]; - auto* buf_gecos = &buf[s_name.length() + 1 + s_gecos.length() + 1]; - auto* buf_dir = &buf[s_gecos.length() + 1 + s_name.length() + 1 + s_gecos.length() + 1]; - auto* buf_shell = &buf[s_dir.length() + 1 + s_gecos.length() + 1 + s_name.length() + 1 + s_gecos.length() + 1]; - - bool ok = true; - ok = ok && s_name.copy_characters_to_buffer(buf_name, s_name.length() + 1); - ok = ok && s_passwd.copy_characters_to_buffer(buf_passwd, s_passwd.length() + 1); - ok = ok && s_gecos.copy_characters_to_buffer(buf_gecos, s_gecos.length() + 1); - ok = ok && s_dir.copy_characters_to_buffer(buf_dir, s_dir.length() + 1); - ok = ok && s_shell.copy_characters_to_buffer(buf_shell, s_shell.length() + 1); - - VERIFY(ok); - - *result = pwd; - pwd->pw_name = buf_name; - pwd->pw_passwd = buf_passwd; - pwd->pw_gecos = buf_gecos; - pwd->pw_dir = buf_dir; - pwd->pw_shell = buf_shell; -} - -int getpwnam_r(char const* name, struct passwd* pwd, char* buf, size_t buflen, struct passwd** result) +// https://pubs.opengroup.org/onlinepubs/9699919799/functions/getpwnam.html +int getpwnam_r(char const* name, struct passwd* pwd, char* buffer, size_t bufsize, struct passwd** result) { - // FIXME: This is a HACK! - TemporaryChange name_change { s_name, {} }; - TemporaryChange passwd_change { s_passwd, {} }; - TemporaryChange gecos_change { s_gecos, {} }; - TemporaryChange dir_change { s_dir, {} }; - TemporaryChange shell_change { s_shell, {} }; - setpwent(); - bool found = false; - while (auto* pw = getpwent()) { - if (!strcmp(pw->pw_name, name)) { - found = true; - break; - } - } - - if (!found) { - *result = nullptr; - return 0; + for (;;) { + if (auto rc = getpwent_r(pwd, buffer, bufsize, result); rc != 0) + return rc; + if (strcmp(pwd->pw_name, name) == 0) + return 0; } - - auto const total_buffer_length = s_name.length() + s_passwd.length() + s_gecos.length() + s_dir.length() + s_shell.length() + 5; - if (buflen < total_buffer_length) - return ERANGE; - - construct_pwd(pwd, buf, result); - return 0; } -int getpwuid_r(uid_t uid, struct passwd* pwd, char* buf, size_t buflen, struct passwd** result) +// https://pubs.opengroup.org/onlinepubs/9699919799/functions/getpwuid.html +int getpwuid_r(uid_t uid, struct passwd* pwd, char* buffer, size_t bufsize, struct passwd** result) { - // FIXME: This is a HACK! - TemporaryChange name_change { s_name, {} }; - TemporaryChange passwd_change { s_passwd, {} }; - TemporaryChange gecos_change { s_gecos, {} }; - TemporaryChange dir_change { s_dir, {} }; - TemporaryChange shell_change { s_shell, {} }; - setpwent(); - bool found = false; - while (auto* pw = getpwent()) { - if (pw->pw_uid == uid) { - found = true; - break; - } - } - - if (!found) { - *result = nullptr; - return 0; + for (;;) { + if (auto rc = getpwent_r(pwd, buffer, bufsize, result); rc != 0) + return rc; + if (pwd->pw_uid == uid) + return 0; } - - auto const total_buffer_length = s_name.length() + s_passwd.length() + s_gecos.length() + s_dir.length() + s_shell.length() + 5; - if (buflen < total_buffer_length) - return ERANGE; - - construct_pwd(pwd, buf, result); - return 0; } int putpwent(const struct passwd* p, FILE* stream) -- cgit v1.2.3