diff options
author | Andreas Kling <kling@serenityos.org> | 2022-11-17 20:43:42 +0100 |
---|---|---|
committer | Andreas Kling <kling@serenityos.org> | 2022-11-19 11:11:13 +0100 |
commit | 524baa29e866d6ee5ef2340c911d626c0b247ce8 (patch) | |
tree | 08fddaf6a3350e40f3f489cbdcb60553b17be9e6 /Userland/Libraries/LibC | |
parent | cc189ce0f367023af6d27b9b7ed7499318961eab (diff) | |
download | serenity-524baa29e866d6ee5ef2340c911d626c0b247ce8.zip |
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. :^)
Diffstat (limited to 'Userland/Libraries/LibC')
-rw-r--r-- | Userland/Libraries/LibC/pwd.cpp | 97 |
1 files changed, 14 insertions, 83 deletions
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) |