summaryrefslogtreecommitdiff
path: root/Userland/Libraries/LibC
diff options
context:
space:
mode:
authorAndreas Kling <kling@serenityos.org>2022-11-17 20:43:42 +0100
committerAndreas Kling <kling@serenityos.org>2022-11-19 11:11:13 +0100
commit524baa29e866d6ee5ef2340c911d626c0b247ce8 (patch)
tree08fddaf6a3350e40f3f489cbdcb60553b17be9e6 /Userland/Libraries/LibC
parentcc189ce0f367023af6d27b9b7ed7499318961eab (diff)
downloadserenity-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.cpp97
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)